排序算法
一、算法核心思想分类
根据算法的核心思想,可以将十大排序算法分为两类:
1. 比较排序
常见的快速排序、归并排序、堆排序、冒泡排序等属于比较排序。
在排序的最终结果里,元素之间的次序依赖于它们之间的比较。每个数都必须和其他数进行比较,才能确定自己的位置。
2. 非比较排序
计数排序、基数排序、桶排序属于非比较排序。
非比较排序是通过确定每个元素之前,应该有多少个元素来排序。针对数组arr,计算arr[i]之前有多少个元素,则唯一确定了arr[i]在排序后数组中的位置。
二、稳定性
稳定排序是指原来相等的两个元素前后相对位置在排序后依然不变。
抽象来说就是,有两个排序关键字的时候(而且往往需要不止一次的排序),稳定排序可以让第一个关键字排序的结果服务于第二个关键字排序中数值相等的那些数。
1. 冒泡排序
在冒泡排序的算法中,每一次循环都是比较两个相邻的元素,前面比后面大的话,就把前面的往后移,后面的往前挪,说白了就是交换一下这俩元素,相等的话不会执行交换,所以相等的元素的前后相对位置不会发生改变,所以冒泡排序可以是稳定的。
2. 选择排序
每次考虑一个位置(从前到后,每次循环递增),找出从该位置(当前 index)开始到数组末尾中的最小元素,与该位置进行交换(将当前的最小值与当前 index 处的元素进行交换),可能破坏稳定性。
3. 插入排序
从后往前插,一直找到不比它大的元素(说明这时候前面的元素小于等于当前考察的元素),该元素后面就是当前元素该插入的位置,所以并未改变相等元素的先后顺序,所以插入排序可以是稳定的。
4. 希尔排序
希尔排序是按照不同步长对元素进行插入排序,一次插入排序是稳定的,不会改变相同元素的相对顺序,但在不同的插入排序过程中,相同的元素可能在各自的插入排序中移动,最后其稳定性就会被打乱,所以希尔排序是不稳定的。
5. 归并排序
每次将当前数组一分为 2 ,将两个排好序的数组进行合并,小的放入,移动指针。
归并排序可以是稳定的。
6. 快速排序
快排的核心思想就是每次我选取一个枢纽元,将小于这个枢纽元的元素划分到一块儿,大于这个枢纽元的元素划分到另一块儿,然后将枢纽元放在这两块儿的中间。快排是不稳定的。因为最后交换的那一次可能将原本相等的两个元素的相对顺序打乱。
7. 堆排序
堆排序的过程是从第 n / 2 开始和其子节点共 3 个值选择最大(大顶堆)或者最小(小顶堆),这 3 个元素之间的选择当然不会破坏稳定性。但当为 n / 2 - 1, n / 2 - 2, … 1 这些个父节点选择元素时,就会破坏稳定性。有可能第 n / 2 个父节点交换把后面一个元素交换过去了,而第 n / 2 - 1个父节点把后面一个相同的元素没有交换,那么这 2 个相同的元素之间的稳定性就被破坏了。所以,堆排序不是稳定的排序算法
三、时间复杂度空间复杂度
可以大致将时间复杂度分为三档,将空间复杂度分为两档。
1. 时间复杂度
· O(n2)
包括传统的冒泡排序、选择排序、插入排序
· O(nlogn)
包括希尔排序、归并排序、快速排序、堆排序
· O(n +/* k)
包括计数排序、桶排序、基数排序
2. 空间复杂度
· O(1)
所有的比较排序
· O(n)
所有的非比较排序