链接:https://pan.baidu.com/s/1HETK673JBjvv24tHfexkKw
提取码:6q4t
1.时间复杂度
从小到大排序:
0(1) < O(logn) < O(n) < O(nlogn) < O(n2 ) < O(n3 ) < 0(2n ) < O(nl) < O(nn )
2.线性表特点要求:
有且只有一个前驱点,一个后驱点。一一对应的关系。如vector、list、stack、queue、字符串string.
顺序存储:用一段连续的内存地址存储数据。如vector,优点是访问元素快O(1),插入删除慢O(N).
链式存储:如list(其实是环型双向链表).优点是插入删除快O(1),访问元素慢O(N).
3.栈的存储结构:
可以是顺序存储(底层用数组或vector表示)也可以是链式存储(用list)。
大量的递归会建立函数副本,耗费大量的时间和内存。前行阶段,在每一层递归中,函数的局部变量、参数值、返回值都会压入栈。在退出节点,栈顶的局部变量、参数、返回值就被弹出。所以不能使用太多的递归,不然栈内存溢出。
4.队列的存储结构:
可以是顺序存储(底层用数组或vector表示)也可以是链式存储(用list)。
5.字符串
也是线性表,也有顺序存储和链式存储。
6.二叉树的性质
7.二叉树的存储结构
a.可以使用顺序存储结构,如数组和vector,缺点是会浪费内存。 这个和STL的heap、pri_queue一样的方式。
b.链式存储结构(更多情况使用这方式)
8.二叉树遍历方式
中序最能表示节点真正大小顺序
9.树、二叉树、森林转换
10.赫夫曼树
叶子节点的带权路径长度:该节点到根节点的路径长度与节点上权重的乘积。
树的带权路径长度:为所有叶子节点的带权路径长度之和。
赫夫曼树:带权路径长度最小的二叉树。
赫夫曼树算法的实现原理:(权重越小的,就在最底层的叶子节点)。
赫夫曼树的作用是:解决数据传输最优问题,文件压缩。
需要知道每个字符出现的频率。
11.二叉排序树
基于链表存储,是有序排列。查找、插入过程简单,插入过程包含了查找过程。但删除要多种考虑。如果是删除的是叶子节点直接删即可,如果删除的是只有左子节点或者只有右子节点,子承父业。如果删除的节点同时又左右子节点,用直接前驱点或者直接后继点(离该节点最近的左右2个键)替换该节点,然后删除该前驱点或后续点。查找、插入、删除的时间复杂度都是O(logn)。查找、插入都用到递归原理。
删除代码实现 :
12.平衡二叉树
任何一结点的左子树结点和右子树结点的高度差不超过1.所以平衡因子只能是-1,0,1。
13.B树(多路查找树)
如2-3树,2-3-4树。
阶:节点最大的孩子数目叫做B树的阶。如2-3树的阶是3.
14. B+树
理解:所有的关键字都在叶子结点上,中间的结点不存信息,只存索引。叶子结点按小到大顺序链接起来。
B+很适合范围查找。
15.散列表(也叫哈希表)
最常用的散列函数是:除留余数法。也叫取模
f(key) = key mod p (p<= m)
解决冲突的办法有:链地址法,这个办法就算是STL的中散列表默认的设计。
16.查找
可以分为7种查找算法:顺序查找、二分查找、插值查找、斐波那契查找、分块查找、二叉树查找法、哈希查找
a.顺序存储的顺序查找:其实就是在无序队伍中,逐个比较判断查找。时间复杂度是O(n)。
b.顺序存储有序表查找有:前提都是有序顺序存储(排好顺序,内存连续)。
折半查找(二分查找):最坏情况下,关键词比较次数为log2(n+1),且期望时间复杂度为O(log2n);
插值查找:时间复杂度均为O(log2(log2n))。mid=low+(key-a[low])/(a[high]-a[low])*(high-low),根据关键字在整个有序表中所处的位置,让mid值的变化更靠近关键字key,这样也就间接地减少了比较次数。 对于表长较大,而关键字分布又比较均匀的查找表来说,插值查找算法的平均性能比折半查找要好的多。反之,数组中如果分布非常不均匀,那么插值查找未必是很合适的选择。
斐波那契查找:最坏情况下,时间复杂度为O(log2n),且其期望复杂度也为O(log2n)。
c.线性索引查找:稠密索引、分块索引(最坏的时间复杂度是n的开平方)、倒排索引.
分块查找又称索引顺序查找,它是顺序查找的一种改进方法。
算法思想:将n个数据元素"按块有序"划分为m块(m ≤ n)。每一块中的结点不必有序,但块与块之间必须"按块有序";即第1块中任一元素的关键字都必须小于第2块中任一元素的关键字;而第2块中任一元素又都必须小于第3块中的任一元素,……
算法流程:
step1 先选取各块中的最大关键字构成一个索引表;
step2 查找分两个部分:先对索引表进行二分查找或顺序查找,以确定待查记录在哪一块中;然后,在已确定的块中用顺序法进行查找。
c.链表存储的查找法:二叉树查找法
二叉查找树(BinarySearch Tree,也叫二叉搜索树,或称二叉排序树Binary Sort Tree)或者是一棵空树,或者是具有下列性质的二叉树: 1)若任意节点的左子树不空,则左子树上所有结点的值均小于它的根结点的值; 2)若任意节点的右子树不空,则右子树上所有结点的值均大于它的根结点的值; 3)任意节点的左、右子树也分别为二叉查找树。 二叉查找树性质:对二叉查找树进行中序遍历,即可得到有序的数列。
它和二分查找一样,插入和查找的时间复杂度均为O(logn),但是在最坏的情况下仍然会有O(n)的时间复杂度
d.哈希(散列)查找:复杂度:对于无冲突的Hash表而言,查找复杂度为O(1)(注意,在查找之前我们需要构建相应的Hash表)。
详见:[Data Structure & Algorithm] 七大查找算法 - Poll的笔记 - 博客园
17.排序
1.冒泡排序:时间复杂度O(n²).
2.选择排序:时间复杂度O(n²).移动次数比冒泡排序少,性能好过冒泡排序
3、 直接插入法:时间复杂度O(n²). 性能比冒泡法和选择法好一些
4.希尔排序
5. 堆排序:
这个和STL默认的堆原理一致,使用一个vector和树的结构关联起来。最大的值在队列前面,也是在最顶层,排序即把最顶层的值和队列最后的值交换位置,然后对队列最后的值重新排放其位置。剩余队列的最大值还是在顶层(也是队列最前端)。
6.归并排序
7.快速排序
平均时间复杂度是O(nlogn),最差的时间复杂度是O(n²)。
平均空间复杂度是O(logn),最差的空间复杂度是O(n)。
总结: