一 最短路径
最短路径分为单源最短路径和任意两点的最短路径,前者用Dijkstra算法,后者用floyed算法。
Dijkstra算法是一种广度优先算法,以起始点层层往外扩展,直至到终点为止。其把顶点分为两个集合:
1. 已经求出最短路径的节点集合 S
2. 未确定最短路径的顶点集合U
通过逐渐把U中的节点不端加入到S中,直至U为空。再插入的过程中,要保证V到S中的任意顶点长度不大于V到U中任意顶点长度。
假设在中间某一步的时候,上一步选取t节点作为中间节点,那么此时查看t的out vertex,那么查看V经过t到这些out vertex的边的长度的最小值是否比之前不经过t的小,如果小,则进行更新。
floyed算法:
i -> j 的最短路径无外乎两种可能:
1. i 直接到 j
2. i 经过若干中间节点到 j ,即Dis(i,k) + Dis(k,j) 和 Dis(i,j) 的大小比较~~
二. 哈希
Hash主要为了在O(1)时间复杂度下查找一个元素。Hash函数的定义:一般是取原始字符的某几位(或随机)映射为一个hash值,比如可以取前几位,把原始字符串分成不同的段,段之间相加得到映射后的hash值。
Hash中两个比较重要的点是:
1. 映射后的hash值分布要均匀
2. 映射后的hash值得冲突要尽量少
一般冲突发生后,可以解决的方法:
1. 线性探测法:在附近依次找一个hash值为空的位置,一定能找到一个,但是增加冲突的可能,因为hash后的值会更聚集。
2. 二次探测法:不长不是加1,步长1 2 4 8 ... 增加
3. 伪随机
以上三种方法属于开放定址法。还有两种方法分别是 再hash方法,链地址法。
三. 检索
检索看的是查找成功/不成功的时候的平均查找长度ASL。不同于检索排序看中的则是元素的比较次数和元素的移动次数。
1. 顺序查找
2. 分块查找:块间有序,块内无序,块内顺序查找。
动态查找/静态查找。
二叉搜索树,ASL容易受树的形态影响。因此对树的形态加个限制,变成了平衡二叉搜索树,其左右子树深度之差不超过2,只能是1,-1,0.
AVL中比较重要的操作就是左旋,右旋操作,调整树,使得树变成平衡的树。
旋转的情况分为下面四种情况:
当前节点的左子树插入左节点:右旋
当前节点的左子树插入右节点:左旋
当前节点的右子树插入左节点:右旋
当前节点的右子树插入右节点:左旋
四. 排序
1. 找出数组中超过一半的数字
维持两个数字,一个是目前出现次数比较多的数字,一个是该数字出现的次数count,遍历数组,如果当前数字和保存的数字相同,则count + 1,如果不相同,则count - 1。如果count = 0,则保存数字 = 当前的数字,重新计数,count + 1
2. 堆建成后,如何进行堆排序呢?每次将堆顶得元素和堆的最后一次元素替换,并将最后一个原色从堆中删除,重新调整堆,依次这样可以得到一个有序的序列。堆排序不受初始数字的排列顺序影响,时间复杂度恒为O(nlogn)
3. 插入排序:把后面未排序数组第一个数字依次插入到前面已排序数组中。时间复杂度O(nn),受初始数字序列的影响
二分插入排序:插入排序的一种小改进,时间复杂度O(nn)
希尔排序:根据一个递减序列 d1 d2 ... 1,d1为增量元素把原始数组划分成不同的组,对组内元素进行排序。时间复杂度O(nlogn)
选择排序:从后面未排序数组中选择一个最大/小值插入到已排序数组中去
冒泡排序:依次交换两个数字,使得大的在后,小的在前,每次都能把最大的一个元素沉淀到数组最后面
快速排序:
堆排序:
归并排序:讲数组分成元素个数只有1/2个的小数组,依次向上进行归并。
桶排序:将数据划分到不同的桶内,桶之间是有序的,对桶内的元素排序即可。
基数排序:将所有待比较数值(注意,必须是正整数)统一为同样的数位长度,数位较短的数前面补零. 然后, 从最低位开始, 依次进行一次稳定排序(我们常用上一篇blog介绍的计数排序算法, 因为每个位可能的取值范围是固定的从0到9).这样从最低位排序一直到最高位排序完成以后, 数列就变成一个有序序列.
比如这样一个数列排序: 342 58 576 356, 以下描述演示了具体的排序过程(红色字体表示正在排序的数位)
第一次排序(个位):
3 4 2
5 7 6
3 5 6
0 5 8
第二次排序(十位):
3 4 2
3 5 6
0 5 8
5 7 6
第三次排序(百位):
0 5 8
3 4 2
3 5 6
5 7 6
结果: 58 342 356 576
两个问题:
- 为什么要从低位开始向高位排序?
如果要从高位排序, 那么次高位的排序会影响高位已经排好的大小关系. 在数学中, 数位越高,数位值对数的大小的影响就越大.从低位开始排序,就是对这种影响的排序. 数位按照影响力从低到高的顺序排序, 数位影响力相同则比较数位值.
- 为什么同一数位的排序子程序要使用稳定排序?
稳定排序的意思是指, 待排序相同元素之间的相对前后关系,在各次排序中不会改变.比如实例中具有十位数字5的两个数字58和356, 在十位排序之前356在58之前,在十位排序之后, 356依然在58之前.
稳定排序能保证,上一次的排序成果被保留,十位数的排序过程能保留个位数的排序成果,百位数的排序过程能保留十位数的排序成果.
索引查找:由索引表和数据表组成。索引表可以是线性的,也可以是树状结构的。