众所周知,排序算法在数据结构中是很重要的,而排序又分为内部排序(待排序记录存放在计算机存储器中进行的排序过程)和外部排序(由于待排序记录数量大,以致内存一次不能容纳全部记录,在排序过程中需要对外存进行访问)。本篇文章主要描述内部排序。内部排序可以分为(大的方面5类,小的方面8类):插入排序(直接插入排序、希尔排序)、选择排序(简单选择排序、堆排序)、交换排序(冒泡排序、快速排序)、归并排序、基数排序;以下对这8类排序算法进行一一详细说明。
注:排序算法的稳定性定义如下--->
1、直接插入排序:
思想:首先将序列的第一个记录看成是一个有序的子序列,然后从第二个记录开始逐个进行插入,直至整个序列有序为止。
注意:设立哨兵,作为临时存储和判断数组边界之用。
程序代码:
时间复杂度:O(n^2),特别情况下, 当所要排序的数据是有序的情况下,时间复杂度变为更好的O(n);
空间复杂度:O(1);
稳定性:稳定
2、希尔排序:
思想:先将整个待排序记录序列分割成若干个子序列分别进行直接插入排序,待整个序列中的记录“基本有序”时,再对全体记录进行依次直接插入排序。
注意:分割子序列是通过增量因子进行分割的,增量因子选取时,应注意它除了1外没有公因子,且最后一个增量因子必为1。
程序代码:
时间复杂度:O(n^1.3)---O(n^1.5)
空间复杂度:O(1)
稳定性:不稳定
3、简单选择排序:
思想:在要排序的一组数中,选出最小(或者最大)的一个数与第一个位置的数进行交换,然后在剩下的数中再找最小(或者最大)的与第二个位置的数交换,依次类推,直至第n-1个元素(倒数第二个数)与第n个元素(最后一个数)比较为止。
注意:第一趟,从n个记录中选出关键码最小的记录与第一个记录进行交换;第二趟,从第二个记录开始的n-1个记录里选出关键码最小的记录与第二个记录进行交换;.......第i趟,从第i个记录开始的n-i+1个记录中选出关键码最小的记录与第i个记录进行交换。
程序代码:
时间复杂度:O(n^2)
空间复杂度:O(1)
稳定性:不稳定
4、堆排序:
思想:首先需要建立大根堆(父>子)或者小根堆(父<子),这样就得到了最大值或者最小值(即堆顶元素),此时将堆顶元素与堆中最后一个元素进行交换,再对最后一个元素除外的所有元素进行大根堆或者小根堆的重新调整。这样直到所有元素都调整完毕,就得到了一个有序序列的记录。
注意:父-->子:n-->2*n+1 ,2*n+2 ;子-->父:n-->(n-1)/2
构造大根堆(小根堆):第一次构造大根堆(小根堆),需要从最后一颗子树开始,从后往前多次调整,每次调整的过程是从上往下。
程序代码:
时间复杂度:O(nlog2^n)(log以2为底n的对数)(注:一次堆调整的时间复杂度是O(log2^n))
空间复杂度:O(1)
稳定性:不稳定
拓:堆排序的前身是锦标排序(树形选择排序),它的时间复杂度是O(nlog2^n),空间复杂度(O(n)),是稳定的,但是它因为占用太多的辅助空间,所以不推荐使用,下面是锦标排序的思想图:
5、冒泡排序:
思想:在要排序的一组数中,自上而下的对相邻的两个数依次进行比较和调整,较大的数往下沉,较小的数往上冒。
程序代码:
时间复杂度:O(n^2)
空间复杂度:O(1)
稳定性:稳定
冒泡排序优化:
6、快速排序:
思想:
递归的快速排序-->先在待排序的记录中选择一个数(通常是第一个数或者最后一个数)作为基准,设立两个指向标记,分别指向第一个元素和最后一个元素,然后进行第一趟划分,若最后一个数大于或等于基准值,则使指向最后一个数的指向标记向前移动;若最后一个数小于基准值,则将最后一个数与第一个数进行交换,此时将指向第一个数的指向标记向前移动。则第一趟得到的记录刚好以基准值为分界线,以上述同样的方法再对分界线两边的部分进行排序,基准值就等于说找到了最终位置。
非递归的快速排序-->主要是利用栈来存储两个指向标记的值,其它与递归的快速排序不相上下。
程序代码:
1.递归的快速排序:
2.非递归的快速排序:
时间复杂度:O(nlog2^n)注:快速排序数据越有序,时间复杂度越大,性能越不好。
空间复杂度:O(log2^n)
稳定性:不稳定
7、归并排序:
思想:将两个(或者两个以上)的有序表合并成一个新的有序表,即把待排序序列分为若干个子序列,每个子序列都是有序的。然后再把有序子序列合并为整体有序序列。
程序代码:
时间复杂度:O(nlog2^n)
空间复杂度:O(n)
稳定性:稳定
8、基数排序:
思想:【低位优先,链式队列】,将数字按位数划分出n个关键字,每次针对一个关键字进行排序,然后针对排序后的序列进行下个关键字的排序,循环至所有关键字都是用过,则排序完成。
程序代码:建立下标为0--9的队列,然后依次按关键字(低位优先)将数据入队,然后再出队。直至所有数据都排完。
时间复杂度:O(d*n)d代表数字的个数,n代表要排序的数的总数
空间复杂度:O(n)
稳定性:稳定
排序算法时间,空间复杂度汇总:
end 2016 5 27