排序算法常常被用来考察一个人的基础能力。因此,对学过的排序算法进行总结。梳理。教材參照网易云课堂里面的浙大开设的数据结构课程里讲到的排序的内容,附上链接:http://mooc.study.163.com/learn/ZJU-1000033001?tid=1000044001#/learn/content?type=detail&id=1000112012&cid=100015100。在此感谢。
如有错误,敬请指正。——2015.6.30
几个会用到的概念:
稳定性:随意两个相等的数据,排序前后的相对位置不发生改变。
- 冒泡排序
思想:它反复地走訪过要排序的数列,一次比較两个元素,假设他们的顺序错误就把他们交换过来。走訪数列的工作是反复地进行直到没有再须要交换,也就是说该数列已经排序完毕。
这个算法的名字由来是由于越小的元素会经由交换慢慢“浮”到数列的顶端。
伪代码:
解释的已经非常清楚了。当中注意,flag用来区分,假设本轮没有发生交换,那么说明已经排好序了,能够结束了。
时间复杂度:顺序T=O(N)。逆序T=O(N2 )
稳定性:稳定
小測试1:对于7个数进行冒泡排序,最坏情况下须要进行的比較次数为(答案是21)。
- 插入排序
思想:通过构建有序序列。对于未排序数据,在已排序序列中从后向前扫描。找到对应位置并插入。
伪代码:
以摸牌为例。easy理解。
时间复杂度:顺序T=O(N),逆序T=O(N2 )
稳定性:稳定
小測试2:给定初始序列{34, 8, 64, 51,32, 21}。冒泡排序和插入排序分别须要多少次元素交换才干完毕?答案:各9次
- 希尔排序
思想:是插入排序的一种更高效的改进版本号,设定一个间隔h。每次利用插入排序交换多个i和i+h对,一趟下来后。将h对应的降低,再反复交换,直到h=1,再进行最后一次交换,排序完毕。
伪代码:增量为N/2。须要认真自己画一个样例来理解,这样比較easy记。
时间复杂度:不固定,最坏O(N2)
稳定性:因为多次插入排序。我们知道一次插入排序是稳定的,不会改变同样元素的相对顺序,但在不同的插入排序过程中,同样的元素可能在各自的插入排序中移动。最后其稳定性就会被打乱,所以shell排序是不稳定的。
- 选择排序
思想:首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置。然后,再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。以此类推,直到全部元素均排序完成。
伪代码:
当中每次找到最小元的位置是通过比較大小来实现,也就是说要比較N-1次
时间复杂度:不固定,最坏O(N2)
稳定性:不稳定
- 堆排序
思想:堆积是一个近似全然二叉树的结构,并同一时候满足堆积的性质:即子结点的键值或索引总是小于(或者大于)它的父节点。
伪代码:
每次通过PercDown找到当前最大的节点。第一步BuildHeap就是建立一个最大堆,然后第二步将最大的节点和最后一个节点交换(由于最大值在排序结果中在最后),然后继续调整以下的为最大堆,每次将最大的数交换到末尾。然后舍弃继续排序。直到完毕。
时间复杂度:平均为O(nlogn)。空间复杂度为O(1)
稳定性:不稳定
- 归并排序
思想:归并操作(merge),也叫归并算法。指的是将两个已经排序的序列合并成一个序列的操作。归并排序算法依赖归并操作。
伪代码:
核心:
递归方式:
非递归:
归并操作的步骤例如以下:
1)申请空间,使其大小为两个已经排序序列之和,该空间用来存放合并后的序列
2)设定两个指针。最初位置分别为两个已经排序序列的起始位置
3)比較两个指针所指向的元素,选择相对小的元素放入到合并空间,并移动指针到下一位置
4)反复步骤3直到某一指针到达序列尾
5)将还有一序列剩下的全部元素直接拷贝到合并序列尾
时间复杂度:平均和最坏都是O(nlogn),空间复杂度:O(N)
稳定性:稳定
- 高速排序
思想:高速排序使用分治法(Divide and conquer)策略来把一个序列(list)分为两个子序列(sub-lists)。
从数列中挑出一个元素,称为”基准”(pivot),又一次排序数列。全部元素比基准值小的摆放在基准前面,全部元素比基准值大的摆在基准的后面(同样的数能够到任一边)。在这个分区结束之后,该基准就处于数列的中间位置。
这个称为分区(partition)操作。
递归地(recursive)把小于基准值元素的子数列和大于基准值元素的子数列排序。
递归的最底部情形,是数列的大小是零或一。也就是永远都已经被排序好了。
尽管一直递归下去,可是这个算法总会结束,由于在每次的迭代(iteration)中。它至少会把一个元素摆到它最后的位置去。
伪代码:
第一段是一种找pivot的方法。即通过比較首尾和中间值取一个中间值放到n-1的位置上,然后在算法中。从左右依次比較。替换。递归的解决这个问题。当数据量小于cutoff时。採用插入排序。
时间复杂度:平均O(nlogn),最坏O(n2),空间复杂度:最好O(logn),最坏O(n)
稳定性:不稳定
- 基数排序
思想:一种非比較型整数排序算法,其原理是将整数按位数分割成不同的数字,然后按每一个位数分别比較。因为整数也能够表达字符串(比方名字或日期)和特定格式的浮点数。所以基数排序也不是仅仅能使用于整数。基数排序的方式能够採用LSD(Least significant digital)或MSD(Most significant digital),LSD的排序方式由键值的最右边開始,而MSD则相反,由键值的最左边開始。
伪代码:
时间复杂度:O(k*n)。n是排序元素个数,k是数字位数。空间复杂度:O(k*n)
稳定性:稳定
- 小结
每种排序算法有其适用场所,在一定条件下,高速排序才是最适合的。