排序
稳定排序:冒泡排序、插入排序、归并排序、基数排序
不稳定排序:选择排序、快速排序、希尔排序、堆排序
稳定的算法在排序的过程中不会改变元素彼此的位置的相对次序,反之不稳定的排序算法经常会改变这个次序
-
冒泡排序
每次找相邻的元素,如果左边比右边大,就交换,这样保证每次扫下来当前待排序的列最后一个元素是当前列中最大的元素,这样就不用管它了,把它踢掉,对剩下的继续上述扫描直到没有为止。
因为如果两个相邻元素相同,是不会交换的;如果两个相等元素没有相邻,即使通过交换能让两个元素相邻,也不会交换,所以相同元素前后顺序不变,是稳定的。
最好时间复杂度: Θ ( n ) \Theta(n) Θ(n),最坏时间复杂度: Θ ( n 2 ) \Theta(n^2) Θ(n2)。
-
选择排序
每次从待排序的序列中找到最小(最大)的元素放在开头,再从剩下的元素中找到最小(最大)放在已排好序的末尾,知道待排序列没有元素为止。
在一趟选择,如果一个元素比当前元素小,而小的元素又出现在和当前元素相等的元素的后面,稳定性就被破坏了。比如 5 8 5 2 9 5\ 8\ 5\ 2\ 9 5 8 5 2 9,第一遍选择 5 5 5 和 2 2 2 会交换,于是原序列中 5 5 5 的相对前后顺序就破坏了,它是不稳定的。
比较次数 Θ ( n 2 ) \Theta(n^2) Θ(n2) ,与元素初始状态无关,总比较次数 N = ( n − 1 ) + ( n − 2 ) + ⋯ + 1 = n ∗ ( n − 1 ) 2 N=(n-1)+(n-2)+\dots+1=\frac{n*(n-1)}2 N=(n−1)+(n−2)+⋯+1=2n∗(n−1) ;交换次数 Θ ( n ) \Theta(n) Θ(n),最好情况 0 0 0 次(有序),最坏交换 n − 1 n-1 n−1 次,逆序交换 n 2 \frac n 2 2n 。
-
插入排序
从有序数列和无序数列开始,每次从无序数列弹出一个数,在有序数列中依次比较,找到一个合适的位置插入。
显然,这个算法具有稳定性。
时间复杂度: Θ ( n 2 ) \Theta(n^2) Θ(n2)。
-
快速排序
设定一个分界值,让左边的元素不大于分界值,右边元素不小于分界值,然后左右依次递归下去。至于实现:
1)设置两个变量 i , j i,j i,j ,排序开始的时候: i = 0 i=0 i=0 , j = N j=N j=N ;
2)以第一个数组元素作为关键数据,赋值给key,即 key = A [ 0 ] =A[0] =A[0] ;
3)从 j j j 开始向前搜索,即由后开始向前搜索(j–) ,找到第一个小于key的值A[j],将A[j]和A[i]的值交换;
4)从i开始向后搜索,即由前开始向后搜索(i++),找到第一个大于key的A[i],将A[i]和A[j]的值交换;
5)重复第3、4步,直到i=j; (3,4步中,没找到符合条件的值,即3中A[j]不小于key,4中A[i]不大于key的时候改变j、i的值,使得j=j-1,i=i+1,直至找到为止。找到符合条件的值,进行交换的时候i, j指针位置不变。另外,i==j这一过程一定正好是i+或j-完成的时候,此时令循环结束)。
演示:
假设一开始序列 { x i } \{x_i\} { xi} 是: 5 , 3 , 7 , 6 , 4 , 1 , 0 , 2 , 9 , 10 , 8 5,3,7,6,4,1,0,2,9,10,8 5,3,7,6,4,1,0,2,9,10,8 。
此时, r e f = 5 ref=5 ref=5, i = 1 i=1 i=1, j = 11 j=11 j=11,从后往前找,第一个比 5 5 5 小的数是 x 8 = 2 x_8=2 x8=2 ,因此序列为: 2 , 3 , 7 , 6 , 4 , 1 , 0 , 5 , 9 , 10 , 8 2,3,7,6,4,1,0,5,9,10,8 2,3,7,6,4,1,0,5,9,10,8 。此时 i = 1 i=1 i=1 , j = 8 j=8 j=8 ,从前往后找,第一个比 5 5 5 大的数是 x 3 = 7 x_3=7 x3=7 ,因此序列为: 2 , 3 , 5 , 6 , 4 , 1 , 0 , 7 , 9 , 10 , 8 2,3,5,6,4,1,0,7,9,10,8 2,3,5,6,4,1,0,7,9,10,8 。此时, i = 3 i=3 i=3 , j = 8 j=8 j=8 ,从第 8 8 8 位往前找,第一个比 5 5 5 小的数是 x 7 = 0 x_7=0 x7=0 ,因此: 2 , 3 , 0 , 6 , 4 , 1 , 5 , 7 , 9 , 10 , 8 2,3,0,6,4,1,5,7,9,10,8 2,3,0,6,4,1,5,7,9,10,8 。此时,$ i=3$ , j = 7 j=7 j=7 ,从第 3 3 3 位往后找,第一个比 5 5 5 大的数是 x 4 = 6 x_4=6 x4=6 ,因此: 2 , 3 , 0 , 5 , 4 , 1 , 6 , 7 , 9 , 10 , 8 2,3,0,5,4,1,6,7,9,10,8 2,3,0,5,4,1,6,7,9,10,8 。此时, i = 4 i=4 i=4 , j = 7 j=7 j=7 ,从第 7 7 7 位往前找,第一个比 5 5 5 小的数是 x 6 = 1 x_6=1 x6=1 ,因此: 2 , 3 , 0 , 1 , 4 , 5 , 6 , 7 , 9 , 10 , 8 2,3,0,1,4,5,6,7,9,10,8 2,3,0,1,4,5,6,7,9,10,8 。此时, i = 4 i=4 i=4 , j = 6 j=6 j=6 ,从第 4 4 4 位往后找,直到第 6 6 6 位才有比 5 5 5 大的数,这时,