![](https://img-blog.csdnimg.cn/20201014180756928.png?x-oss-process=image/resize,m_fixed,h_64,w_64)
数据结构
LaVine
这个作者很懒,什么都没留下…
展开
-
图的总结
图的概念连通:如果两个顶点有路径,则是连通连通图:如果任意两个点都有连通的路径,则是连通图连通分量:就是极大连通子图,包含结点有尽可能多的边生成树:一些结点包含尽可能少的边,但是要确保连通,不存在环路如果是有向图则为强连通,强连通分量图的存储结构和基本操作邻接矩阵法邻接表法表示方法不唯一图的遍历广度优先遍历:对每一层尽可能的访问完,类似树的层序遍历,需要使用辅助队列空间复杂度是辅助队列时间复杂度主要集中在,找边和访问结点上深度优先遍历:对每个结点尽可能的往深处探索,会使用到递归工原创 2020-12-23 14:41:17 · 144 阅读 · 0 评论 -
树的总结
树的基本性质路径:一般是只有从上往下的路径结点数 = 总度数 +1度为m的树,一定有有一个结点有m个子树二叉树的定义和性质一般是用完全二叉树来定义的注意子树和父节点的关系完全二叉树只有倒数第一,二层会有叶子结点n1的结点只能为1or0如果二叉树是采用顺序存储,一定要将空的位置也要留下来,这样就可以根据编号找到父子结点二叉树的遍历根据遍历序列恢复二叉树;前中后序遍历 表达式 会得到对应的表达式层序遍历需要辅助队列二叉排序树左 < 根 < 右二叉排序树插入又删除形原创 2020-12-23 09:54:30 · 131 阅读 · 0 评论 -
栈和队列总结
输出合法性关键:一个结点出栈后,比它之前入栈的结点而且在它之后出栈的,出栈顺序和入栈顺序相反栈的存储链式存储,一般采用带头结点的头插法顺序存储,需要注意栈顶指针的两种方式队列的存储结构需要有两个指针,指向队头和队尾顺序存储:为了防止假溢出,需要每次入队出队进行Mod操作为了区分是队空还是队满,1,设置size变量,每次入队出队都需要进行修改;2,牺牲一个空间不进行存储,如果队尾指针的下一个是队头则说明队满队列的实际应用缓冲区对树的层序遍历栈的实际应用函数调用压栈信息表达式求值原创 2020-12-22 16:38:32 · 213 阅读 · 0 评论 -
线性表总结
静态分配,静态数组动态分配,动态数组顺序表具有随机存储的特性,查找时间复杂度是O(1)增,删的时间复杂度都是O(n)链表带头结点的头插法要注意避免断链,十分容易对链表逆置操作尾插法:需要保留一个指向链尾的指针需要注意删除和添加结点是否会导致断链的发生...原创 2020-12-21 21:57:32 · 96 阅读 · 0 评论 -
归并排序
思路:对于两个有序的数组进行归并成一个有序的大数组每次新数组的指针都会指向下一个待归并的数字,然后每次两个数组内选中一个最小的元素然后放入大数组当中如果是对一个无序的数组进行归并排序,需要划分两个子序列,然后递归的对左右两个子序列进行排序,最后再进行合并的操作代码实现:B = (int *)malloc(sizeof(int)*n); void Merge(int A[],int low,int high,int mid){ int i,j,k; for(int i = low;原创 2020-12-21 21:46:16 · 253 阅读 · 0 评论 -
快速排序
快排思路:每次选择Low指向的数,然后找出它应该去的位置具体实现:把high和low遍历,按照要求high只能是比关键点大的数,low只能是比关键点小的数如果发现不符合要求,需要将它赋值给另一边空出来的位置覆盖,然后换另一边执行找到不符合规则的数最后覆盖int Partition(int A[],int low,int high){ int pivot; pivot = low; while(low < high){ while(A[high] >=原创 2020-12-21 20:09:31 · 81 阅读 · 0 评论 -
8.4 选择排序
简单选择排序的思想从后续的序列找出最小的元素然后交换void SelectSort(int A[],int n){ int i,j; int temp; for(i = 0;i < n-1;i++){ int min = i; for(j = i+1;j < n-1;j++){ if(A[i] > A[j]){ min = j; } } Swap(A[i]原创 2020-12-17 13:54:40 · 139 阅读 · 0 评论 -
6.4_5_有向无环图描述表达式.key
如何根据表达式进行合并AOV网,进行拓扑排序AOV网,表示工程,一定是有向无环图,因为表示工程的前后关系,如果形成回路就出现悖论问题拓扑排序方式首先选择入度为0的结点,然后删去结点和与之相关的所有边,不断重复直到全部的结点被删除位置代码实现:设置两个数组,一个记录入度,一个记录最终值先寻找入度为0的结点,并且更新记录入度的值,然后根据记录值,把它指向的结点入度-1,重新更新逆拓扑排序先寻找到出度为0的结点,然后删除有关的边,如此反复使用DFS算法进行逆拓扑排序,思路,不断递归找到最后一原创 2020-12-14 16:08:20 · 184 阅读 · 0 评论 -
6.4.1 最小生成树
生成树的概念:在确保连通的情况下,有更少的边,n-1条边最小生成树对于带权无向图中,确保生成树的权值之和最小prim算法选择一个顶点,然后逐个选择到生成树中代价最小的顶点无论怎样生成,从哪里出发,最后生成树的形态可能不同,但权值都是一样的克鲁斯卡尔算法选择最小的边,然后相连,如果两端是连通的就不连因为prim是采用选点的方式,时间复杂度是O(V^2)因为克鲁斯卡尔算法是选边,所以时间复杂度和边有关...原创 2020-12-13 21:48:55 · 90 阅读 · 0 评论 -
5.4 树和森林
森林的双亲表示法每个结点都会指向唯一的双亲,可以定义数据结构来标记该结点的前驱tips,删除一个结点,最好是将后面的结点覆盖需要删除的结点,删除结点的同时还需要将所有指向该结点的记录孩子表示法方式:链式+顺序顺序存放每个结点,每个结点后面都会指向下一个结点的指针孩子兄弟表示法(最重要)要点:左指针指向第一孩子,右指针指向兄弟完成森林到树的转换二叉树转换成森林从根节点出发,右指针指向都是平级的树,然后再各个转换成树对树的先根遍历等同对二叉树的先序遍历对树的后根遍历等同于对二叉树的中序遍原创 2020-12-10 19:42:21 · 76 阅读 · 2 评论 -
5.3 线索二叉树
question:如何根据中序遍历序列找到一个结点的前驱使用土办法:分配两个指针,一个根据遍历找到该结点,一个结点记录该结点的前一个结点BiNode *p = NULL;BiNode *pre = NULL;BiNode *final = NULL;void findInorder(BiTree T){ if(T!=NULL){ findInorder(T->lchild); visit(T); findInorder(T->rchi.原创 2020-12-09 21:59:01 · 157 阅读 · 1 评论 -
5.3_6_在线索二叉树中找前驱后继
如何找到一个结点的后继?思路如果这个结点已经被线索化,只需要找到他的rchild如果这个结点未被线索化,需要找到右孩子的最左边的孩子实现代码:BiTNode *Firstnode(BiTNode *p){ while(p->ltag==0){ p = p->lchild; } return p;}//找到最左下的结点BiTNode *Nextnote(BiTNode *p){ if(p->rtag == 0) return Firstnode(p->原创 2020-07-13 07:50:40 · 646 阅读 · 0 评论 -
5.3_4_线索二叉树的概念
如果只是单纯的二叉树,只有得到根节点才能完成遍历的序列如何找到一个结点的指针?已知结点p思路从根节点出发,设定一个q结点和pre结点代表q结点的前驱pre指针的结点为q结点的前驱,如果q==p,那么pre就是p结点的前驱如果需要找到q结点的后继,那么当pre==p的时候,q就是p的后继了二叉树线索化因为链式存储的二叉树,结点为n就会有n+1个空链域,如果全部利用起来,进行线索化,就可以很方便的找到前驱和后继前驱线索:由左孩子充当后继线索:由右孩子充当用ltag,rtag:如果置为1原创 2020-07-10 23:22:33 · 178 阅读 · 0 评论 -
5.3_1_二叉树的先中后序遍历(优化版) (2)
先序遍历:根左右中序遍历:左根右后序遍历:左右根先序遍历:实现代码:void PreOrder(BiTree T){ if(T!=null){ visit(); PreOrder(T->lchild); PreOrder(T->rchlid); }}时间复杂度O(h)求树的深度int treeDepth(BiTree T){ if(T == NULL){ return 0; } else{ int i = treeDepth(T->lchi原创 2020-07-10 07:52:31 · 73 阅读 · 0 评论 -
5.2_3_二叉树的存储结构
顺序存储只能是完全二叉树的顺序来存储,实现逻辑关系如果不是完全二叉树,按照完全二叉树一一对应起来,需要设置一位Empty来判断是否有数据i的左子树2ii的右子树2i+1结点为i的结点,父节点为i/2向下取整链式存储struct ElemType{ int value;};typedef struct BiTNode{ ElemType data; struct BiTNode *lchild,*rchlid;}BiTNode,*BiTree;BiTree root =..原创 2020-07-06 20:24:08 · 173 阅读 · 0 评论 -
5.2_2_二叉树的性质
二叉树的常考性质n = n0 + 2n2 + 1n0 = n2 +1高度为h的二叉树,最多有2^(h-1),刚好是满二叉树完全二叉树常考性质具有n个结点的二叉树,高度为log2(n+1)向上取整log2n向下取整 + 1完全二叉树结点计算因为n = 1的结点最多只有1个,所以n1 = 1 or 0已知所有结点的总数是可以知道各个结点的数量的n0 = n2 + 1n = n0 + n2 + n1n0 + n2必为奇数如果总结点为2k个那么n1一定为1,n0 = k,n2 = k-1原创 2020-07-04 23:17:01 · 248 阅读 · 0 评论 -
5.2_1_二叉树的定义和基本术语
二叉树根节点左右子树每个结点都是两颗子树二叉树是有序树,不能调换满二叉树高度为h,且含有2^h -1棵子树,除了叶子结点,其余的结点都是含有两个子节点从1开始编号i左节点为2i,右节点2i+1求父节点为i/2向下取整完全二叉树在满二叉树去掉后面的编号的结点满二叉树是特殊的完全二叉树编号和满二叉树一致,所以关于父子结点的计算相同叶子结点最多在最后两层最多只有一个度为1的结点,而且必定是左孩子,不是右孩子i <= n/2 为分支结点;i >原创 2020-07-04 22:59:40 · 97 阅读 · 0 评论 -
5.2_1_二叉树的定义和基本术语
二叉树根节点左右子树每个结点都是两颗子树二叉树是有序树,不能调换满二叉树高度为h,且含有2^h -1棵子树,除了叶子结点,其余的结点都是含有两个子节点从1开始编号i左节点为2i,右节点2i+1求父节点为i/2向下取整完全二叉树在满二叉树去掉后面的编号的结点满二叉树是特殊的完全二叉树编号和满二叉树一致,所以关于父子结点的计算相同叶子结点最多在最后两层最多只有一个度为1的结点,而且必定是左孩子,不是右孩子i <= n/2 为分支结点;i >原创 2020-07-04 22:21:37 · 132 阅读 · 0 评论 -
5.1_1_树的定义和基本术语
概念:除了根节点,每个结点只有一个前驱子树必须是互不相交的结点之间的关系:路径只能从上往下长度就是路径上的边结点、树的属性描述:高度是树有多少层结点的度:有多少个孩子(分支)树的度:最多的度注意层次的开始有序树:不可以交换顺序无序树:结点的左右关系森林:m棵互不相交的集合允许有空森林的概念重点:子树;路径:只能从上往下结点的度:结点的分支数树的度:树中各结点的最大值...原创 2020-07-03 23:22:48 · 107 阅读 · 0 评论 -
4.3.3 KMP算法 下
KMP算法特点是,为了避免回退,就设计了失败后,将子串指针向前回退的next数组本章是设计next数组设计思想因为当k位不匹配的时候,前1~k-1位是匹配的所以需要寻找前k位以前的前缀和后缀是否匹配前缀,包含第一个字符,不包含最后一个字符的子串后缀:包含最后一个字符,且不包含第一个字符的子串当j匹配失败时候,将前面已匹配的串记为S,next[j] = S的最长相等前后缀 +1规定next[1] = 0总结:如果是第一个不匹配,则返回到0,i,j各+1然后在前面的已经匹配好的子串中,寻原创 2020-07-01 19:46:26 · 109 阅读 · 0 评论 -
4.2.2 KMP算法上
设计一个next数组,将一旦数组不匹配,j应该回溯到next的指针下因为第k个匹配不成功,说明1~k-1都是成功的移动思想:朴素模式是同时移动i,j让指向子串和主串的指针重新遍历,我们可以采用重新设计一个next数组,根据算法,只移动子串的指针j回溯到特定的位置,然后重新匹配next数组设计特点:next[1] = 0int Index_KMP(SString S,SString T,int next[]){ int i = 1; int j = 1; while(i&l原创 2020-07-01 18:29:33 · 81 阅读 · 0 评论 -
4.2_1_串的朴素模式匹配算法
模式匹配概念从主串找到模式串中相同的子串,并返回所在位置朴素模式匹配发现不同就检查子串int Index(SString S,SString T){ int k = 1; int i = k,j=k; while(i<=S.length && j<=T.length){ if(S.ch[i]==T.ch[j]){ i++; j++; }else{原创 2020-07-01 16:55:41 · 371 阅读 · 0 评论 -
6.4_2_最短路径问题_BFS算法
单源最短路径无权图 – BFS带权图,无权图 – 小迪算法d[],记录最短距离p[],记录前驱访问顶点的时候,d[]数组记录为前驱数组的 d +1path[]记录前驱广度优先生成树,是高度最小的生成树原创 2020-06-24 21:20:06 · 257 阅读 · 0 评论 -
6.4.1 最小生成树
生成树:包含所有的顶点的极小连通子图最小生成树:带权连通无向图,各边的权值之和必须是连通的Prim算法:思想:从某一个顶点出发,挑出权值最小的边连通,然后再挑下一条相对于部分树权值最小的边最小生成树不唯一,但权值之和是唯一的相同的时间复杂度,只和顶点V有关,O(V^2),适合边稠密的图克里斯卡尔算法:1,从权值最小的边2,如果没有连通,就连通时间复杂度,O(log2e * e)...原创 2020-06-24 20:42:41 · 167 阅读 · 0 评论 -
7.4_2_散列查找(下).key
处理冲突:拉链法:同义词存放在一个链表开放定制法:线性探测法:往后一步一步查找位置删除元素:不能直接删除,给一个删除标记,还可以继续往下探测看起来很满,其实很空同义词、非同义词大量堆积平方探测法:d = 0,1,-1,4,-4,9,-9H(key) + d % mm 为表长只有是 4j + 3的质数,才能探测到所有位置伪随机序列法:伪随机序列是另一种增量本质是增量不同再散列法:多准备散列法,发生冲突就再使用备用的哈希函数...原创 2020-06-19 15:51:15 · 104 阅读 · 0 评论 -
7.4_1_散列查找(上).key
特点:每个数据元素的关键字与其存储地址直接相关,通过哈希函数如果不同的关键字映射到同一值会同义词,产生的是冲突查找长度 = 0ASL对比查找长度,失败情况:N/M装填因子 = 表中记录数/散列表长度设计更好的散列函数除留余数法:key % p ,p是最接近m的质数(尽可能的减少冲突)直接定制法:适合连续的数值数字分析法:选取数码分布较均匀的若干位(手机号码)平方取中法:关键字平方中间几位作为散列地址“用空间换时间”...原创 2020-06-19 15:16:01 · 112 阅读 · 0 评论 -
7.2.1 &7.2.2 顺序查找和二分查找
1,顺序查找:线性查找,通常用顺序表ASL = (n+1)/2查找失败n+1顺序表优化折半查找:有序的顺序表,递增or递减只能基于顺序,注意排序int Binary_Search(SeqList L,ElemType e){ int low,high,mid; low = 0; high = L.length-1; while(low <= high){ mid = (high + low)/2; if(L.data[mid] == e){ return mid;原创 2020-06-16 22:50:39 · 148 阅读 · 0 评论 -
8.1_排序的基本概念.key
排序(Sort),就是重新排列表中的元素,使表中的元素满⾜按关键字有序的过程。算法的稳定性:相同元素排序之后相对位置不变排序算法:内部排序:关注算法时间、空间复杂度更低外部排序:数据太多,无法全部放入内存,还要关注如何读/写操作更少...原创 2020-06-08 18:06:51 · 121 阅读 · 0 评论 -
6.2_4_图的基本操作
判断图G是否存在边<a,b>或者(a,b)采用邻接矩阵直接查看坐标是否为1,时间复杂度O(n)采用邻接表查看a结点的链表,时间复杂度为O(V)列出图G中与结点x相连的边对于无向图来说采用邻接矩阵,需要扫描x结点的一行查看为1的结点,时间复杂度为O(V)采用邻接表,需要遍历x结点的链表,时间复杂度为O(1)~O(v)对于有向图来说采用邻接矩阵,需要扫描x结点的一行查看为1的结点,时间复杂度为O(V)采用邻接表,查找出度,直接遍历x的链表即可O(1)~O(v),如果要原创 2020-06-07 19:07:36 · 501 阅读 · 0 评论 -
6.2_3_十字链表、邻接多重表
十字链表法:用于存储有向图邻接多重表:用于存储无向图十字链表法:通过一个指针找到指向的,通过另一个结点找到被指向的只要顺着两个指针就能很容易的找到入度和出度注意:十字链表只用于存储有向图在无向图中,如果进行删除操作需要删除多份文件,有冗余,优化这个邻接表邻接多重表用于存放无向图,每个结点有两个指针和两个标示位特点:每一份数据是唯一的,删除的话直接删除即可,解决了邻接表删除不方便的问题邻接矩阵:问题:冗余邻接表法:问题①入度不方便查找:十字链表法;问题②删除不方便:邻接多重表法...原创 2020-06-05 17:30:36 · 196 阅读 · 0 评论 -
6.2_2_邻接表法
邻接表法(顺序+链式)无向图:时间复杂度是O(V+2E)有向图:边界点的数量是E,整体空间复杂度为O(V+E)如何找到顶点的度?入度?出度?对于无向图来说:度只要扫描结点的指针后面的个数就可以得到结点的个数对于有向图来说:找到出度只要扫描该结点指针指向的链表即可找入度很麻烦对于有向图来说,邻接表存储有向图的最大问题就是统计入度很困难对于一个图,使用邻接矩阵的表示方法是唯一的如果使用邻接表的方法则邻接表不唯一邻接表用于解决邻接矩阵存储稀疏图的浪费的问题,但对于寻找入度来说是原创 2020-06-05 17:06:10 · 594 阅读 · 0 评论 -
6.2_1_邻接矩阵法
图的存储–邻接矩阵法无向图:是对称矩阵,可以压缩0表示不连接,1表示连接有向图:求度、入度、出度: 无向图:扫描一行或者一列的非0元素,得到度 有向图:出度,扫描行;入度,扫描列。度 = 入度+出度邻接矩阵法(网): 矩阵内标识内标识权值,不存在度则标为无穷大0或者无穷:表示两个顶点之间不存在路径适合用于存储稠密度图,否则会有很多浪费设图G的邻接矩阵为A(矩阵元素为0/1),则An 的元素An [i][j]等于由顶点i到顶点j的长度为n的路径的数目...原创 2020-06-05 12:02:39 · 911 阅读 · 0 评论 -
6.1_1_图的基本概念
图的定义图G由顶点集V和边集E组成,|V|表示顶点的个数,又称作G的阶,|E|表示边的条数线性表可以使空表,树可以使空树,但图不可以是空图,V一定是非空集边一定要对应的点;点不一定要有边有向图<a,b> vs 无向图(a,b)简单图、多重图简单图不存在重复的边不存在指向自身的边复杂图存在重复的边或者有指向自身的边顶点的度、入度、出度无向图:顶点的v的度是指依附于该顶点的度之和有向图:入度 = 出度 = |e|顶点-顶点的关系路径–顶点p到顶点q的路径是顶原创 2020-06-04 23:30:47 · 397 阅读 · 0 评论 -
5.5_3_哈夫曼树
哈夫曼树(最优二叉树)结点的权:结点的带权路径长度:从根到结点的路径长度*权值树的带权路径长度:所有根节点的带权路径长度(WPL)WPL最小的树就是哈夫曼树哈夫曼树构造结点总数是2N-1哈夫曼编码基于哈夫曼树可变长编码任何一个编码都不是另一个编码的前缀,不会产生歧义字符集中的每一个字符都只能是叶子结点,频率作为权值,这种就是哈夫曼树可以用于数据的压缩...原创 2020-06-04 16:28:02 · 139 阅读 · 0 评论 -
5.5_2_平衡二叉树
平衡树(AVL) – 树上任一结点的左子树和右子树高度相差不超过1结点平衡因子 = 左子树高-右子树高插入操作:插入操作可能会让路径上所有的结点都收到影响如果发生不平衡,从插入点往回,找到第一个不平衡结点,调节以该结点为根的子树每次调整的对象都是“最小不平衡子树”①调整LL子树LL(右旋)RR(左旋)LR(左旋再右旋)RL(右旋再左旋)...原创 2020-06-04 15:19:42 · 106 阅读 · 0 评论 -
5.5_1_二叉排序树
特点:左节点 < 根节点 < 右节点进行中序遍历可以得到有序序列BST用于元素的组织、搜索二叉树结点定义:typedef int ElemType;typedef struct BTNode{ ElemType data; struct BTNode *lchild,*rchild;}BSTNode,*BSTree;查找特定的结点:BSTNode *BST_Search_P1(BSTree T,int key){ while(T->data!=key&&a原创 2020-06-03 18:49:18 · 309 阅读 · 1 评论