mindmap
排序算法
插入排序
直接插入排序
希尔排序
选择排序
选择排序
堆排序
交换排序
冒泡排序
快速排序
归并排序
插入排序
1. 直接插入排序
思想:将某一个数插入到一组有序序列中生成一个新的有序序列。借鉴玩扑克牌游戏的方法。
直接插入排序的特性总结:
- 元素集合越接近有序,直接插入排序算法的时间效率越高
- 时间复杂度:O(N^2)
- 空间复杂度:O(1),它是一种稳定的排序算法
- 稳定性:稳定
2. 希尔排序
思想:设定一个gap,将序列分成gap组,所有距离相同gap将其分成一组,需保证在每一个组内的序列有序。 希尔排序的特性总结:
希尔排序的特性总结:
- 希尔排序是对直接插入排序的优化。
- 当gap > 1时都是预排序,目的是让数组更接近于有序。当gap == 1时,数组已经接近有序的了,这样就会很快。这样整体而言,可以达到优化的效果。
- 希尔排序的时间复杂度不好计算,因为gap的取值方法很多,导致很难去计算,这里不深究。时间复杂度O(N^1.5)
- 空间复杂度O(1)
- 稳定性:不稳定。
选择排序
1. 选择排序
思想:第一次选择最小(或最大)的元素放在序列末尾(或开头),之后选择次小(大)的元素放在倒数第二的位置,重复上述步骤直到都排序完成
直接选择排序的特性总结:
- 直接选择排序思考非常好理解,但是效率不是很好(不论数组是否有序都会执行原步骤)。实际中很少使用
- 时间复杂度:O(N^2)
- 空间复杂度:O(1)
- 稳定性:不稳定
2. 堆排序
思想:构建一个大堆堆或者小堆堆,堆顶元素与最后面的元素交换,重新构建剩余的元素的堆,直到所有的元素都排齐为止。
扩展:一般堆是一个完全二叉树或近似完全,其存储采用一维数组的方式存储。某一个下标为i的节点,其父节点下标为(i-1)/2,其子节点的下标为2i+1和2i+2。
直接选择排序的特性总结:
- 堆排序使用堆来选数,效率就高了很多。
- 时间复杂度:O(N*logN)
- 空间复杂度:O(1)
- 稳定性:不稳定
交换排序
冒泡排序
思想:两两比较两个数的大小,如果前一个比后一个大,就交换位置,直到将最大的数冒泡到最末尾的位置,如此循环,使得最后序列有序。如果一趟下来没有数交换位置,那么就说明序列排序完成了。
冒泡排序的特性总结:
- 冒泡排序是一种非常容易理解的排序
- 时间复杂度:O(N^2)
- 空间复杂度:O(1)
- 稳定性:稳定
快速排序
思想:选择任意一个基准值(通常是最左边或者最右边),把元素分成两部分,左边部分都小于基准值,右边部分都大于基准值,左边和右边的部分也是同样操作,直到排齐。
方法:
- hoare版本
选定一个基准值,最好选定最左边或者最右边.
确定两个指针left 和right 分别从左边和右边向中间遍历数组。
如果选最右边为基准值,那么left指针先走,如果遇到大于基准值的数就停下来。
然后右边的指针再走,遇到小于基准值的数就停下来。
交换left和right指针对应位置的值。
重复以上步骤,直到left = right ,最后将基准值与left(right)位置的值交换。
- 挖坑法
先将选定的基准值(最左边)直接取出,然后留下一个坑 当右指针遇到小于基准值的数时,直接将该值放入坑中,而右指针指向的位置形成新的坑位, 然后左指针遇到大于基准值的数时,将该值放入坑中,左指针指向的位置形成坑位, 重复该步骤,直到左右指针相等。最后将基准值放入坑位之中。
快速排序的特性总结:
- 快速排序整体的综合性能和使用场景都是比较好的,所以才敢叫快速排序,序列越无序,效果越好。
- 时间复杂度:O(N*logN)
- 空间复杂度:O(logN)
- 稳定性:不稳定
归并排序
思想:用分冶治之的方式,将两堆有序的序列合并成一堆有序的序列。所以一开始先从一个数开始,一个合并成两个,两个合并成四个。。。
归并排序的特性总结:
- 归并的缺点在于需要O(N)的空间复杂度,归并排序的思考更多的是解决在磁盘中的外排序问题。
- 时间复杂度:O(N*logN)
- 空间复杂度:O(N)
- 稳定性:稳定