二叉树—堆(C语言实现)

 一、树的概念及结构

1.树的概念

树是一种非线性的数据结构,它是有n(n > 0)个有限结点组成一个具有层次关系的集合。把它叫做树是因为它看起来像一颗倒挂的树,也就是说它是根朝上,而叶朝下。

●  有一个特殊的结点,成为根结点,根结点没有前驱结点

●  除根节点外,其余节点被分成M(M > 0)个互不相交的集合T1、T2、......、Tm,其中每个集合Ti(1 <= i <= m)又是一颗结构与树相类似的子树。每棵子树的根结点有且只有一个前驱,可以有0个或多个后继

●  因此,树是递归定义

注意:树形结构中,子树之间不能有交集,否则就不是树形结构。

2.树的相关概念

3.树的表示

树结构相对线性表就比较复杂,要存储表示起来就比较麻烦,既然保存值域,也要保存结点和结点之间的关系,实际上数有很多表示方式比如:双亲表示法,孩子表示法,孩子双亲表示法以及孩子兄弟表示法等。我们这里就简单的理解其中最常用的孩子兄弟表示法。

typedef int DataType;
struct Node
{struct Node* firstChild1; // 第一个孩子结点struct Node* pNextBrother; // 指向其下一个兄弟结点DataType data; // 结点中的数据域
};

二、二叉树的概念及结构

1.概念

一颗二叉树是节点的一个有限集合,该集合:
1.由一个根结点加上两颗别称为左子树和右子树的二叉树组成

2.或者为空

由上图可知:

1.二叉树不存在度大于2的结点

2.二叉树的子树有左右之分,次序不能颠倒,因此二叉树是有序树

 注意:对于任意的二叉树都是有以下几种情况符合而成的:

2.特殊的二叉树 

(1)满二叉树:一个二叉树,如果每一层的结点数都要达到最大值,则这个二叉树就是满二叉树。也就是说,如果一个二叉树的层数为K,且总结点数是2^{k}-1,则它就是满二叉树。

(2)完全二叉树:完全二叉树是效率很高的数据结构,完全二叉树是由满二叉树印出来的。对于深度为K的,有n个结点的二叉树,当且仅当其每一个结点都与深度为K的满二叉树中编号从1至n的结点——对应时称之为完全二叉树。要注意的是满二叉树是一种特殊的完全二叉树。

3.二叉树的性质

(1)若规定根结点的层数为1,则一颗树非空二叉树的第i层上最多有2^{i-1}个结点。

(2)若规定根结点的层数为1,则深度为h的二叉树的最大结点数是2^{h}-1

(3)对任何一颗二叉树,如果度为0其叶结点个数为n0,度为2的分支结点个数为n2,则有n0=n2+1 

<1>类比归纳(图解) :

<2>定义推导:

假设二叉树有N个结点

从总结点数角度考虑:N = n0 + n1 + n2   ①

从边的角度考虑,N个结点的任意二叉树,总共有N-1条边

因为二叉树中每一个结点都有双亲,根结点没有双亲,每个结点向上与其双亲之间存在一条边,因此N个结点的二叉树总共有N-1条边。

因为度为0的节点没有孩子,故度为0的节点不产生边;度为1的结点只有一个孩子。故每个度为1的结点产生一条边;度为2的结点有两个孩子,故每个度为2的结点产生两条边,所以总边数为:n1 + 2*n2

故从边的角度考虑:N-1 = n1 + 2*n2   ②

结合①和②得:n0 + n1 + n2 = n1 + 2*n2 - 1

n0 = n2 + 1

(4)若规定根结点的层数为1,具有n个结点的满二叉树的深度,h =\log2^{^{n+1}}(是log以2为底,n+1为对数)

(5)对于具有n个结点的完全二叉树,如果从上到下从左至右的数组顺序对所有节点从0开始编号,则对于序号为i的节点结点有:

1.若 i > 0,i 位置结点的双亲序号:( i -1) / 2;i = 0,i 为根节点编号,无双亲结点

2.若2i + 1 < n,左孩子序号:2i + 1,2i +1 >= n否则无左孩子

3.若2i + 2 < n,右孩子序号:2i + 2,2i + 2 >= n否则无右孩子 

4.题目 

1. 某二叉树共有 399 个结点,其中有 199 个度为 2 的结点,则该二叉树中的叶子结点数为(B)
A 不存在这样的二叉树
B 200
C 198
D 199

 由性质3:n0 = n2 + 1 = 199 + 1 = 200

2.在具有 2n 个结点的完全二叉树中,叶子结点个数为(A)
A n
B n+1
C n-1
D n/2

度为0 —> n0个,度为1 —> n1个,度为2 —> n2个

因为n0 + n1 + n2 = 2N,n0 = n2 + 1

则2n0 + n1 - 1 = 2N

因为完全二叉树的n1的数量是0 or 1,为了保证等号左侧与等号右侧统一成偶数,此时,n1 = 0

所以n0 = N

3.一棵完全二叉树的结点数位为531个,那么这棵树的高度为(B)
A 11
B 10
C 8
D 12

5.二叉树的存储结构 

二叉树一般有两个结构,一种是顺序结构,一种是链式结构。

(1)顺序结构

顺序结构存储就是使用数组来存储,一般使用数字只适合表示完全二叉树,因为不是完全二叉树会有空间的浪费。而现实中使用中只有堆才会使用数组来存储。

二叉树顺序存储在物理上是一个数组,在逻辑上是一颗二叉树。

(2)链式存储

二叉树的链式存储结构是指,用链表来表示一棵二叉树,即用链来表示元素的逻辑关系。通常的方法是链表中每个结点右三个域组成,数据域和左右指针域,左右指针分别表示用来给出结点左孩子和右孩子所在的链节点的存储地址。

三、二叉树的顺序结构及实现

普通的二叉树是不适合用数组来存储的,因为可能会存在大量的空间浪费。而完全二叉树更适合使用顺序结构存储。现实中我们通常把堆(完全二叉树)使用顺序结构的数组来存储,需要注意的是这里的堆和操作系统虚拟进程地址空间中的堆是两回事,一个是数据结构,一个是操作系统中管理内存的一块区域分段。

1.堆的概念及结构

如果有一个关键码的集合K={ K_{0}K_{1}K_{2},……,K_{n-1} },把它的所有元素按完全二叉树的顺序存储方式存储在一个一维数组中,并满足:K_{i} \leqK_{2i+1}K_{i} \leq K_{2i+2}K_{i}\geq K_{2i+1} 且 K_{i}\geq K_{2i+2})i = 0 , 1 , 2……,则称为小堆(大堆)。将根结点最大的堆交租最大堆或大根堆,根结点最小的堆叫做最小堆会小根堆。

2.堆的性质

(1)堆中某个结点的值总是不大于或不小于其父亲结点的值

(2)堆总是一颗完全二叉树

3.堆的实现

<1>堆的创建图示

通过插入数据和向上调整算法实现,后面会有解释

<2>Heap.h

#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<stdbool.h>typedef int HPDateType;
typedef struct Heap
{HPDateType* a;int size;int capacity;
}HP;//交换函数
void swap(HPDateType* p1, HPDateType* p2);//初始化和销毁
void HPInit(HP* php);
void HPDestory(HP* php);//向上调整算法
void AdjustUp(HPDateType* a, int child);
//插入数据
void HPPush(HP* php, HPDateType x);void AdjustDown(HPDateType* a, int n, int parent);
//删除数据
void HPPop(HP* php);
//返回堆顶的元素
HPDateType HPTop(HP* php);
//判空
bool HPEmpty(HP* php);

<3>Heap.c

(1)交换函数
//交换函数
void swap(HPDateType* p1, HPDateType* p2)
{HPDateType tmp = *p1;*p1 = *p2;*p2 = tmp;
}
(2)初始化
void HPInit(HP* php)
{assert(php);php->a = NULL;php->capacity = php->size = 0;
}
(3)销毁
void HPDestory(HP* php)
{assert(php);free(php);php->a = NULL;php->capacity = php->size = 0;
}
(4)向上调整算法
//向上调整算法
void AdjustUp(HPDateType* a, int child)
{int parent = (child - 1) / 2;//堆的父子关系while (child > 0){if (a[child] < a[parent])//向上调整{swap(&a[child], &a[parent]);//交换位置child = parent;//最初的parent赋值给childparent = (child - 1) / 2;//重新规划parent}else{break;}}
}
(5)插入数据(建堆)

 堆的创建过程图示:

时间复杂度为:logN 

 

//插入数据
void HPPush(HP* php, HPDateType x)
{assert(php);//空间不够if (php->size == php->capacity){int newcapacity = php->capacity == 0 ? 4 : php->capacity * 2;HPDateType* tmp = (HPDateType*)realloc(php->a, newcapacity * sizeof(HPDateType));if (tmp == NULL){perror("realloc fail!");return;}php->a = tmp;php->capacity = newcapacity;}php->a[php->size] = x;//插在数组的结尾php->size++;AdjustUp(php->a, php->size - 1);//传的是下标,用来找父子关系
}
(6)向下调整算法

我们通过从根结点开始的向下调整算法可以把它调整成一个小堆。向下调整算法的前提:左右子树必须是一堆,才能调整。 

//向下调整算法(前提:左右字树是小堆/左右子树是大堆)
void AdjustDown(HPDateType* a,int n,int parent)
{//假设法:先假设左孩子小int child = parent * 2 + 1;//child >= n说明孩子已经不存在了,超出二叉树范围了(叶子)while (child < n)  {//找出小的那个孩子if (a[child] > a[child + 1] && child +1 < n){++child;//让右孩子成为小的}if (a[child] < a[parent]){swap(&a[child], &a[parent]);parent = child;child = parent * 2 + 1;}else{break;}}
}
(7)删除数据

删除堆是删除堆顶的数据,将堆顶的数据根最后一个数据交换,然后删除数组最后一个数据,在进行向下调整算法

//删除数据(堆顶的数据)
//不能挪动数据,覆盖删除堆顶数据—>关系错乱
//堆顶数据交换到最后一个数据,再删除最后一个数据,在进行向下调整算法
void HPPop(HP* php)
{assert(php);assert(php->size > 0);swap(&php->a[0], &php->a[php->size - 1]);php->size--;//先size--了,缩小数组大小//所以调用完AdjustDown()函数后,交换到最后一位的堆顶元素就已经被删除了AdjustDown(php->a, php->size, 0);}
(8)返回栈顶元素
//返回堆顶的元素
HPDateType HPTop(HP* php)
{assert(php);assert(php->size > 0);return php->a[0];
}
(9)判空
//判空
bool HPEmpty(HP* php)
{assert(php);return php->size == 0;
}

<4>test.c

void TestHeap1()
{int a[ ] = { 2,4,5,6,1,7,8,9 };HP hp;HPInit(&hp);for (size_t i = 0; i < sizeof(a) / sizeof(int); i++){HPPush(&hp, a[i]);}while (!HPEmpty(&hp)){printf("%d ", HPTop(&hp));HPPop(&hp);}
} 
int main()
{TestHeap1();return 0;
}

4.堆的应用 

<1>堆排序 

(1)建堆

升序:建大堆

降序:建小堆

 (2)排序

● 向上调整建堆思想:

例如,我们想得到升序,先建好大堆,再将堆的最后一个元素与栈顶元素交换,此时数组的最后一个空间存储的就是集合中的最大元素(位置锁定了),然后对新的堆顶元素进行向下调整之后,栈顶元素就是集合中第二大的元素。再将栈顶元素与数组的倒数第二个位置进行交换,逐此往复。直到所有元素都锁定了。

向上调整建堆的时间复杂度: O(N*logN)

void swap(int* p1, int* p2)
{int tmp = *p1;*p1 = *p2;*p2 = tmp;
}
void AdjustUp(int* a, int child)
{int parent = (child - 1) / 2;//堆的父子关系while (child > 0){if (a[child] < a[parent])//向上调整{swap(&a[child], &a[parent]);//交换位置child = parent;//最初的parent赋值给childparent = (child - 1) / 2;//重新规划parent}else{break;}}
}//堆排序
//->时间复杂度:O(N* logN)
//这里我们把数组当做完全二叉树
void HeapSort(int* a, int n)
{//向上调整建堆//降序,建小堆 (升序,建大堆)for (int  i = 0; i < n; i++){AdjustUp(a, i);}int end = n - 1;while (end > 0){//把最大的数换到最后一位swap(&a[0], &a[end]);//在将第一个数向下调整,选出次大的数AdjustDown(a, end, 0);//最后一位数据被固定,数组的范围缩小--end;}
}void TestHeap3()
{int a[] = { 5,4,3,16,17,20 };HeapSort(a, sizeof(a) / sizeof(int));
}
int main()
{TestHeap3();return 0;
}

● 向下调整建堆思想 

以最后一个有子树的元素为根结点所形成的树开始建堆(向下调整算法),下来是以倒数第二个有子树的元素为根节点所形成的树建堆,直到以栈顶元素为根结点所形成的树建堆完成。

 

向下调整建堆的时间复杂度: O(N)


#include<stdio.h>
#include<stdlib.h>
void swap(int* p1, int* p2)
{int tmp = *p1;*p1 = *p2;*p2 = tmp;
}void AdjustDown(int* a, int n,int parent)
{//建小堆int child = 2 * parent + 1;//先假设左孩子小while (child < n){if (a[child] > a[child + 1]){child++;}if (a[child] < a[parent]){swap(&a[child], &a[parent]);parent = child;child = 2 * parent + 1;}else{break;}}
}void HPSort(int* a, int n)
{//向下调整建堆(从最后一个有子树的元素开始向上建)->666	//数组最后一个元素的小标为n-1for (int i = (n - 1 - 1) / 2; i >= 0; i--){AdjustDown(a, n, i);}
}int main()
{int a[] = { 5,6,2,3,7,8,9,1,4 };int n = sizeof(a) / sizeof(a[0]);HPSort(a, n);for (int i = 0; i < n; i++){printf("%d ",a[i]);}return 0;
}

<2>Top—K问题

即求数据集合中前K个最大的元素或最小的元素,一般情况下数据量都比较大

对于Top—K问题,能想到的最简单直接的方式就是排序

void TestHeap2()
{int a[] = { 27,15,19,18,28,34,65,49,25,37 };HP hp;HPInit(&hp);for (size_t i = 0; i < sizeof(a) / sizeof(int); i++){HPPush(&hp, a[i]);}//找出最小的前k个int k = 0;scanf("%d", &k);while (k--){printf("%d ", HPTop(&hp));HPPop(&hp);}printf("\n");
}int main()
{TestHeap2();return 0;
}

但是:如果数据量非常大,排序就不太可取了(可能数据都不能快速全部加载到内存中)。

最佳的方式就是用堆来解决。

(1)用数据集合中前K个元素来建堆——>O(K)

求前K个最大的元素,则建小堆

求前K个最小的元素,则建大堆

(2)用剩余的N-K个元素一次与堆顶元素进行比较,不满足则替换堆顶元素——>O((N-K)*logN)

将剩余的N-K个元素一次与对顶元素比较完后,堆中剩余的K歌元素就是所求的前K个最小的或最大的元素。

合计时间复杂度是O(N)

#include<stdio.h>
#include<stdlib.h>
#include<time.h>void swap(int* p1, int* p2)
{int tmp = *p1;*p1 = *p2;*p2 = tmp;
}void AdjustDown(int* a, int n,int parent)
{//建小堆int child = 2 * parent + 1;//先假设左孩子小while (child < n){if (a[child] > a[child + 1]){child++;}if (a[child] < a[parent]){swap(&a[child], &a[parent]);parent = child;child = 2 * parent + 1;}else{break;}}
}void PrintTopK(int* a, int n, int k)
{// 1. 建堆--用a中前k个元素建堆for (int i = (k - 1 - 1) / 2; i >= 0; i--){AdjustDown(a, n, i);//小堆}// 2. 将剩余n-k个元素依次与堆顶元素交换,不满则则替换for (int j = k; j < n-1; j++){if (a[0] < a[j]){a[0] = a[j];AdjustDown(a, n, 0);}}for (int s = 0; s < k - 1; s++){printf("%d ", a[s]);}printf("\n");
}
void TestTopk()
{int n = 10000;int* a = (int*)malloc(sizeof(int) * n);srand(time(0));for (size_t i = 0; i < n; ++i){a[i] = rand() % 1000000;}a[5] = 1000000 + 1;a[1231] = 1000000 + 2;a[531] = 1000000 + 3;a[5121] = 1000000 + 4;a[115] = 1000000 + 5;a[2335] = 1000000 + 6;a[9999] = 1000000 + 7;a[76] = 1000000 + 8;a[423] = 1000000 + 9;a[3144] = 1000000 + 10;printf("最大的前k个数\n");int k;scanf("%d", &k);PrintTopK(a, n, k);
}
int main()
{TestTopk();return 0;
}

另一种写法,在文件中生成: 

void CreateNDate()
{// 造数据int n = 10000;srand(time(0));const char* file = "data.txt";FILE* fin = fopen(file, "w");if (fin == NULL){perror("fopen error");return;}for (size_t i = 0; i < n; ++i){int x = rand() % 1000000;fprintf(fin, "%d\n", x);}fclose(fin);
}void HeapTest()
{int k;printf("请输入K:");scanf("%d", &k);int* a = (int*)malloc(sizeof(int) * k);if (a == NULL){perror("malloc error");return;}//打开文件,读前k个数const char* file = "data.txt";FILE* fout = fopen(file, "r");if (fout == NULL){perror("fopen error");return;}for (int i = 0; i < k; i++){fscanf(fout,"%d", &a[i]);}//建有k个数的小堆for (int i = (k - 1 - 1) / 2; i >= 0; i--){AdjustDown(a, k, i);}//读取剩下的N-K个int x = 0;while (fscanf(fout,"%d", &x) > 0){if (a[0] < x){a[0] = x;AdjustDown(a, k, 0);}}//打印for (int i = 0; i < k; i++){printf("%d ", a[i]);}printf("\n");
}int main()
{CreateNDate();HeapTest();return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/341690.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C++设计模式-单例模式,反汇编

文章目录 25. 单例模式25.1. 饿汉式单例模式25.2. 懒汉式单例模式25.2.1. 解决方案125.2.2. 解决方案2 &#xff08;推荐写法&#xff09; 运行在VS2022&#xff0c;x86&#xff0c;Debug下。 25. 单例模式 单例即该类只能有一个实例。 应用&#xff1a;如在游戏开发中&#x…

搭建大型分布式服务(三十九)SpringBoot 整合多个kafka数据源-支持Aware模式

系列文章目录 文章目录 系列文章目录前言一、本文要点二、开发环境三、原项目四、修改项目五、测试一下五、小结 前言 本插件稳定运行上百个kafka项目&#xff0c;每天处理上亿级的数据的精简小插件&#xff0c;快速上手。 <dependency><groupId>io.github.vipjo…

算法第三天力扣第69题:X的平方根

69. x 的平方根 (可点击下面链接或复制网址进行做题) https://leetcode.cn/problems/sqrtx/https://leetcode.cn/problems/sqrtx/ 给你一个非负整数 x &#xff0c;计算并返回 x 的 算术平方根 。 由于返回类型是整数&#xff0c;结果只保留 整数部分 &#xff0c;小数部分将被…

SpringBoot的第二大核心AOP系统梳理

目录 1 事务管理 1.1 事务 1.2 Transactional注解 1.2.1 rollbackFor 1.2.2 propagation 2 AOP 基础 2.1 AOP入门 2.2 AOP核心概念 3. AOP进阶 3.1 通知类型 3.2 通知顺序 3.3 切入点表达式 execution切入点表达式 annotion注解 3.4 连接点 1 事务管理 1.1 事务…

【踏雪无痕的痕六】——数学中有意思的问题

一、背景介绍 提出一个问题往往比解决一个问题更有意义&#xff0c;因为提出一个问题相当于提出了一个思考问题的维度&#xff1b;而解决一个问题是沿着这个维度将已有的知识串起来的过程 三、过程 1.数人数你会吗&#xff1f; 小名再第10位&#xff0c;小李再第15位&#…

【源码】Spring Data JPA原理解析之Repository自定义方法命名规则执行原理(二)

Spring Data JPA系列 1、SpringBoot集成JPA及基本使用 2、Spring Data JPA Criteria查询、部分字段查询 3、Spring Data JPA数据批量插入、批量更新真的用对了吗 4、Spring Data JPA的一对一、LazyInitializationException异常、一对多、多对多操作 5、Spring Data JPA自定…

位运算算法

位运算是计算机中常用的一种运算方法&#xff0c;它直接对二进制数的位进行操作。位运算主要包括按位与&#xff08;&&#xff09;、按位或&#xff08;|&#xff09;、按位异或&#xff08;^&#xff09;、按位取反&#xff08;~&#xff09;、左移&#xff08;<<&a…

【云原生】Kubernetes----Ingress对外服务

目录 引言 一、K8S对外方式 &#xff08;一&#xff09;NodePort 1.作用 2.弊端 3.示例 &#xff08;二&#xff09;externalIPs 1.作用 2.弊端 3.示例 &#xff08;三&#xff09;LoadBalancer 1.作用 2.弊端 &#xff08;四&#xff09;Ingress 二、Ingress的…

ChatGPT-4o抢先体验

速度很快&#xff0c;结果很智能&#xff0c;支持多模态输入输出&#xff0c;感兴趣联系作者。 windows/linux/mac 客户端下载参考&#xff1a;https://github.com/lencx/Noi

dns域名解析服务和bond网卡

目录 dns域名解析服务 一、DNS 1、定义 2、以www.baidu.com为例 3、域名体系结构 4、DNS解析使用的协议和端口 5、dns域名解析的过程 6、dns解析的优先级 二、如何实现域名解析 1、域名解析 2、bind配置文件位置 &#xff08;一&#xff09;正向解析 &#xff08;…

IP协议1.0

基本概念&#xff1a; • 主机: 配有IP地址, 但是不进⾏路由控制的设备; • 路由器: 即配有IP地址, ⼜能进⾏路由控制; • 节点: 主机和路由器的统称; IP协议的报头 • 4位版本号(version): 指定IP协议的版本, 对于IPv4来说, 就是4. • 4位头部⻓度(header length): IP头部的⻓…

高并发系统限流原理

短时间内巨大的访问流量&#xff0c;我们如何让系统在处理高并发的同时还能保证自身系统的稳定性&#xff1f;估计有人会说&#xff0c;增加机器就可以了&#xff0c;因为我的系统架构设计就是按照分布式思想进行架构设计的&#xff0c;所以可以只需要增加机器就可以解决问题了…

计算机组成原理·考点知识点整理

根据往年考试题&#xff0c;对考点和知识点的一个整理。 校验编码 码距 一种编码的最小码距&#xff0c;其实就是指这种编码的码距。码距有两种定义&#xff1a; 码距所描述的对象含义 2 2 2 个特定的码其二进制表示中不同位的个数一种编码这种编码中任意 2 2 2 个合法编码的…

QT+FFmpeg+Windows开发环境搭建(加薪点)

01、Windows 环境搭建 FFMPEG官网:http://ffmpeg.org/ 02、下载4.2.1版本源码 源码:https://ffmpeg.org/releases/ffmpeg-4.2.1.tar.bz2 03、下载4.2.1编译好的文件 下载已经编译好的FFMPEG)(迅雷下载很快) 网址:https://ffmpeg.zeranoe.com/builds/ 32位下载地址:(迅雷…

【wiki知识库】05.分类管理模块--后端SpringBoot模块

&#x1f4dd;个人主页&#xff1a;哈__ 期待您的关注 目录 一、&#x1f525;今日目标 二、☀SpringBoot代码修改 1.使用逆向工程生成Category表结构 2. 新增CategoryQueryParam 3.新增CategorySaveParam 4.新增CategotyQueryVo 三、&#x1f916;新增分类管理的相关接口…

8. C#多线程基础概念

文章目录 一. 目标二. 技能介绍① 进程和线程② 为什么需要多线程③ C#实现多线程的方式④ 线程的操作(创建_终止_挂起_恢复) 一. 目标 进程和线程基本概念为什么需要多线程?C#实现多线程的方式?线程Thread的创建,终止,挂起和恢复? 二. 技能介绍 ① 进程和线程 什么是进程…

IO流,文件操作

参考 Java IO 基础知识总结 | JavaGuide 史上最骚最全最详细的IO流教程&#xff0c;没有之一&#xff01; - 宜春 - 博客园 零、io-流简介 IO 即 Input/Output&#xff0c;输入和输出。数据输入到计算机内存的过程即输入&#xff0c;反之输出到外部存储&#xff08;比如数据…

Microsoft Outlook Lite 引入短信功能

随着科技的不断进步&#xff0c;我们的沟通方式也在不断演变。微软最新推出的 Outlook Lite 应用&#xff0c;不仅为我们提供了一个轻量级的电子邮件管理工具&#xff0c;现在更是带来了一项令人兴奋的新功能——短信服务。 Outlook Lite&#xff1a;轻量级&#xff0c;功能全…

手眼标定学习笔记

目录 标定代码&#xff1a; 手眼标定原理学习 什么是手眼标定 手眼标定的目的 eye in hand eye to hand AXXB问题的求解 标定代码&#xff1a; GitHub - pumpkin-ws/HandEyeCalib 推荐博文&#xff1a; https://zhuanlan.zhihu.com/p/486592374 手眼标定原理学习 参…

带DSP音效处理D类数字功放TAS5805M中文资料

国产替代D类数字功放中文资料访问下方链接 ACM8628 241W立体声182W单通道数字功放中文寄存器表 内置DSP多种音频处理效果ACM8628M-241W立体声或182W单通道数字功放 1 特性 具有增强处理能力和低功率损耗的 TAS5805M 23W、无电感器、数字输入、立体声、闭环 D 类音频放大器 …