- 第一章 算法
- 第二章 线性表(包含栈、队列)
—— 一、顺序表
—— 二、单链表
—— 三、静态链表
—— 四、循环链表
—— 五、双链表
—— 六、栈
—— 七、队列 - 第三章 树
—— 一、基本定义
—— 二、树的遍历
—— 三、树的表示法
—— 四、二叉树
—— 五、二叉树的实现
—— 六、线索二叉树
—— 七、二叉搜索树
—— 八、线段树
—— 九、序列树 - 第四章 散列表
—— 一、散列技术
—— 二、散列函数
—— 三、重新散列技术 - 第五章 图
- —— 一、基本概念
- —— 二、图的表示法
- —— 三、图的遍历
- 第六章 排序
- 第七章 优先队列
- 第八章 并查集
冷知识汇总
- 顺序存储大多是浪费空间的
第一章 算法
- 算法需要的时间资源的量称为时间复杂度
- 可操作性最好且最有实际价值的是最坏情况下的时间复杂性
- 算法实现的三要素:数据、运算、控制
顺序结构、分支结构、循环结构、递归和无条件转移 - 机器语言能直接表达的数据只有最原始的位、字节和字
- 抽象数据类型:是算法的一个数据模型连同定义在该模型上并作为算法构件的一组运算(简单来说就是不用顾及运算的函数体)
其实我们常用的基本数据类型也是抽象数据类型的一种 - 高级语言就是汇编语言的抽象
汇编语言就是机器语言的抽象 - 数据结构:反映数据的内部构成,同一类数据的全体称为数据类型
- return语句有终止函数的作用
- 在程序中动态分配的数据必须在退出程序之前用free释放空间,否则容易造成内存泄漏
- 间接或直接调用自身的算法称为递归算法,每个递归函数都必须有非递归定义的初始值
第二章 表
一、顺序表
- 顺序表的算法的复杂度(这里以下全部默认为时间复杂度)大多是O(n)
二、单链表
- 单链表包含一个数据域和一个指针域
- 单链表必须从表头开始操作,因此大多功能的时间复杂度也是O(n)
三、静态链表
- 静态链表特征:(游标都是指向下标的)
①第一个可用空间的游标指向下一个可用空间的下标
②头结点游标指向第一个可用空间的下标
③最后的已用空间的游标指向头结点下标 - 间接寻址法实现表就是数组存放指针,指针再指向数据
其好处是当数据量很大时,该方法实现的表实现插入算法要比顺序表快得多
四、循环链表(只是方便了表头表尾罢了)
- 在单链表的基础上添加一个尾指针,并使它指向头结点
- 判断空表的条件不再是检测指针空了而是是否指向头结点
五、双链表(方便整个表)
- 一个结点有两个指针
- 找尾结点只需要head->left
- 在插入结点时,先处理好的是新结点的出指针,再处理新结点的入指针,且顺序一定不能乱
- 删结点时只需要处理该结点的左右结点的两个指针
六、栈
- 栈只表首(栈顶)进行插入和删除操作,简称LIFO表,多用数组实现
- 栈在使用完后必须释放空间以免产生内存泄漏
- 由于栈空间常不会被充分使用,因此引出利用栈底位置不变的特性,多个栈共享空间
七、队列
- 队列只在表首(队首)出(删除),表尾(队尾)进(插入),简称FIFO表
- 循环队列的方向是顺时针方向,且有三种表示方式
①两游标直接指向队首和队尾
②队首游标指向队首下一个元素
③队尾游标指向下一个元素
他们的判断队列是否为满的条件不相同
第三章 树
一、基本定义
- 度
①一个结点的儿子结点个数称为该结点的度
②一棵树的度是指该树结点的最大的度
③度不为零的结点为分枝结点
④除根结点外的分枝结点统称为内部结点 - 路径
①两结点路径长度为他们之间边的数目
②两结点存在路径则有祖先关系
③任一结点既是自己的祖先也是自己的子孙
④结点的高度是指从该结点到自身所在的树的叶结点的最长路径长度
⑤结点的深度(层数)是指该结点到树根的路径长度 - 序
①有序树:树的每一组兄弟结点之间定义一个从左到右的次序
②有序树中不同次序则为不同的树
③无序树没有讲究
二、树的遍历
- 三种遍历分别对应根的位置而已
- 画树的方法:
①肯定有中序遍历和另外两种的其中一种的遍历结果
②前序遍历是可知第一个元素是根结点,后序遍历是可知最后一个元素是根结点,中序遍历则是把元素从中间分开的作用
③依照②的规律,按前/后序找到根,然后按中序遍历从中分开,递归上述步骤就行了,画完后再遍历一次检查清楚 - 一棵表达式树的中序标号表就是中缀表达式,后序标号表就是后缀表达式
三、树的表示法
- 父结点组数表示法
数组下标(从1开始)为树的层序遍历结果,数组元素为下标结点的父结点 - 儿子链表表示法
①数组加链表
②用数组存各儿子链的表头,数组下标(从1开始)为树的层序遍历结果,然后儿子链也是按层序遍历一个接一个 - 左儿子右兄弟表示法
①双链表
②左指针接儿子右指针接兄弟
四、二叉树
- 二叉树的结点最多两个,且有左右之分
- 二叉树的计算:
①高度为h>=0的二叉树至少有多少个结点:h+1(单侧树嘛)
②高度不超过h的二叉树至多有多少个结点:2h+1 -1
③含有n>=1个结点的二叉树的高度至多为:n-1;至少为:[logn] 取下限 (也是单侧树)
④深度为n的满二叉树的结点为:2n
⑤已知哈夫曼树叶结点为m,则它所具有的结点数为:2m-1
⑦根据子结点数求结点数:步骤太多了就不写了,直接跳转这个写得挺好!;简单来说就是根据每层的结点数推算得出是最后一层还是最后两层有叶子结点,以及总结点数的奇偶得出最后一层有2a还是2a-1个叶子结点
⑥根据树和结点的度计算叶子结点数:同上链接 都有;简单来说就是根据总结点数的两条公式进行求解 - 近似满二叉树(完全二叉树)
①最大度为2
②只有左叶结点
③深度为h时,至少有2h-1个结点,至多有2h-1个结点
五、二叉树的实现(递归)
- 顺序存储(层序遍历)
①当i>1时,结点i的父节点为:[i/2] 取下限
②结点i的左儿子为:2i
③结点i的右儿子为:2i+1
④i为奇数且不为1时,左兄弟为:i-1
⑤i为偶数时,右兄弟为:i+1
⑥最坏情况下,k个结点的右支数需要2k-1个结点存储空间 - 结点度表示(后序遍历【有种递归回溯内味】)
①用数组存储结点并附加该结点的度:(b,3)
②0表示无度,1表示只有左儿子,2表示只有右儿子,3表示有两儿子 - 指针实现
六、线索二叉树(中序遍历)
- 因为用指针实现二叉树时,n个结点的二叉树就有n+1个空指针,造成极大存储空间浪费
- 因此在结点中添加两个线索标志,用于标识左右指针是作指针还是线索
- 线索是指向中序遍历前继结点的指针
七、二叉搜索树(中序遍历)
- 有序排列
- 数组实现字典
①使用二分法搜索时,时间复杂度为O(logn) - 链表实现字典
- 二叉搜索树实现字典
八、线段树(层序)
- 有序排列
- 就是把线段平分平分平分
- 结构中,需要有一个正则覆盖计数
- 是一棵平衡二叉树
- 正则覆盖:当线结点v被线段[l,r]覆盖,并且结点v的父结点不被线段[l,r]覆盖,此时结点v就是[l,r]的正则覆盖结点
- 线段树中的每一层最多只有两个结点是同一线段的正则覆盖结点
九、序列树(层序)
- 和线段树一样,都是平分平分平分,这里是把序列平分
- 结构中,它需要一个标准子序列的最大值和一个最小值,这点和线段树不同
- 也是一棵平衡二叉树
- 标准子序列:即每个结点对应的子序列
- 引进堆概念(因此当给出序列要你判断是否为堆时,只需要层序遍历写出来就看出来了)
十、哈夫曼树
- 特点:
①树中只存在度为2和0的结点
②n2 = n0 - 1 - 常考:有30个结点的哈夫曼树,对多少个字符进行编码。解法就是:有30个结点的哈夫曼树,对多少个字符进行编码。解法就是:n0+n2 = 30 => n0 + n0 - 1 = 30 , 解出n0即是答案
第四章 散列表
一、散列技术
- 符号表:
①链表实现
②位向量实现
③定长数组实现:使用数组存储集合的元素,带有一个last游标 - 开散列
①把集合元素划分为有限个类(也叫桶),再用散列函数将每个元素映射到桶中
②一个桶用一个表存储 - 闭散列
①将符号表元素按散列函数放桶数组中
②一个桶只存放一个元素
③产生冲突时,按线性用重新散列技术试探下一个桶直至空桶再存放当前元素
④在桶中需要存放一个empty标记和一个delete标记
二、散列函数
m为正整数、B为桶数、a为小数、c为整数
- 除余法:h(k) = k%m;m小于B,简单起见取m=B居多
- 数乘法:h(k) = [B(ka-[ka])] 取下限;a一般取黄金比例:0.618
- 平方取中法:h(k) = [k2/c]%B 取下限;Bc2和n2要大致相同,适用于B和c均不是偶数时,因此可选c与B互素
- 基数转换法:将键值看成用另一个进制表示的数后,再将它转换为原来进制表示的数,取其中若干位作为散列函数值;一般取大于原来基数的数作为转换的基数,并且这两个基数互素
- 随机数法:h(k) = random(k);random为随机函数,适用于键的长度不等时
三、重新散列技术
采用线性重新散列技术会出现 “聚集” 现象,因此应采用跳跃式重新散列技术
- 二次散列技术:h2i-1(x) = (h(x)+i2)%B , h2i = (h(x)-i2)%B;此方法只有当B为形如4j+3的素数时,才能探索到整个散列表
- 随机重新散列技术:hi(x) = (h(x)+di)%B , i = 1, 2……B-1 , d1, d2……dB-1是1, 2……B-1的一个随机排序
- 双重散列技术:该方法有两个散列函数h和h’,h(x) = (h(x)+ih’(x))%B , i = 1 , 2 , ……B-1;其中h’(x)的值和B互素
第五章 图
一、基本概念
- 图包括顶点集和边集,记为G = (V,E)
- 完全图(e是边数,n是顶点数):
①若是无向图,则e=n(n-1)/2(一画图就能明白了)
②若是有向图,则e=n(n-1) - 关联:就是边(u,v)关联于顶点u和v
- 顶点的度:
①若是无向图,则是关联于顶点的边数
②若是有向图,则以顶点为起点的边数称为出度;以顶点为终点的边数称为入度 - 路:就是边
- 简单路:一条路上除起点和终点可能相同,其他顶点均不相同
- 有根图:从顶点v可到达途中其他所有顶点,则v是根
- 连通图:无向图中任意两不同顶点都是连通的
- 连通分支:无向图的极大连通子图;显然,连通图只有一个连通分支,即自身
- 强连通分支 :有向图中任意两不同顶点互相连通,则G是强连通图,G的极大强连通图则是强连通分支;显然,强连通图只有一个强连通分支,即自身
二、图的表示法
-
邻接矩阵:
①无向图:对称矩阵;行或列代表顶点的度;浪费空间
②有向图:行表示出度,列表示入度;
-
邻接表
三、图的遍历
- 广度优先(队列)
- 深度优先(右手原则)