排序算法:
排序算法的稳定性:
在待排序的数据中,如果有值相同的数据,在排序的全程中都不会改变它们的先后顺序,则认为该排序算法是稳定的
冒泡:数据左右进行比较,把最大的数一直交换到最后,特点是该算法对数据的有序性敏感,在排序过程中发现有序可以立即停止排序,如果待排序的数据基本有序,则冒泡的效率非常高
时间复杂度: 最优O(n) 平均: O(n^2)
稳定的
选择: 假定最开始的位置是最小值并记录下标min,然后与后面的数据比较,如果有比min为下标的数据还要小,则更新min,最后判断如果min的值发生了改变,则交换min位置的数据与最开始位置的数据
虽然选择排序的时间复杂度较高,但是数据交换次数少,因此实际运行速度并不慢
是冒泡排序的变种,但是没有对数据有序性敏感,数据混乱情况下比冒泡快
时间复杂度: O(n^2)
不稳定的 (10 10 1)
注意:算法的时间复杂度并不能代表算法的实际时间,有时候时间复杂度高的反而速度更快
插入:把数据看作两个部分,一部分是有序的,把剩余的数据逐个插入进去
时间复杂度: O(n^2)
稳定的
希尔:是插入排序的增强版,由于插入排序数据移动的速度比较慢,所以再此基础上增加了增量的概念,从而提高排序的速度
时间复杂度: O(n^(1.3~2))
不稳定的
快速:
找到一个标杆p,备份标杆的值val,一面从左找比val大的数据,找到后赋值给p,更新标杆p的位置到左标杆
然后从右边找比val小的数,找到后也赋值给p,同样更新p到右标杆,反复执行直到左右标杆相遇停止,最后把val赋值回到p的位置
最终会形成p左边的数都比它小,右边的数都比它大;然后再按照同样的方式对左右两边进行快排,最后全部有序
快速排序的综合性最高,因此叫做快速排序,笔试面试考试最多
时间复杂度: O(nlogN)
不稳定的
1 0 2 3 5 6 4 7 8 9
l r
p
val = 7
归并:
先把一组待排序的数组拆分成单独的个体,存放到临时空间中,然后两两合并
全部合并完成后再从临时空间中拷贝给原内存
由于使用额外的内存空间避免了数据
交换的耗时,是一种典型的以空间换时间的算法
时间复杂度: O(nlogN)
堆:把数据当做完全二叉树看待,然后把树调整成大顶堆或小顶堆,然后把堆顶数据交换到末尾,然后数量--
然后重新调整回大顶堆,重复操作,直到数量为1时结束,既可以循环实现,也可以递归实现(参考heap.c)
时间复杂度: O(nlogN)
计数:
找出数据中最大值和最小值,并创建哈希表,把 数据-最小值 作为数组的下标访问哈希表并标记数量
标记完后,遍历哈希表,当表中的值大于0,把 下标+最小值 还原数据依次放回数组中,是一种典型的以空间换时间的算法
该排序算法理论上速度非常快,它不是基于比较的算法,在一定范围内整数排序时快于任意的一种比较排序算法,
但是有很大的局限性:适合排序整型数据,而且数据的范围差别不宜过大,否则会非常浪费内存反而慢于比较的排序
如果数据越平均、重复数越多,性价比越高
时间复杂度: O(N+k) (其中k是整数的范围)
稳定的
桶:
根据数据的值存储不同的桶中,然后再调用其他的排序算法,度桶中的数据进行排序,然后再从桶中依次拷贝回数组中
从而降低排序的规模依次提高排序的速度,是一种典型的以空间换时间的算法
缺点:如何分桶、桶范围多大,这些都需要堆数据有一定的了解
时间复杂度: O(N+k)
桶排序的稳定性取决于排序使用的算法
基数:
是桶排序的具体实现,首先创建10个队列(链式队列),然后逆序计算出数据的个、十、百...位数,然后入到对应的队列中
结束后从队列中出队会数组中,数据下一位继续入队,依次循环,最大值的位数就是循环次数
缺点:只适合正整数数据,又要准备队列
时间复杂度: O(N+k)
稳定的