码迷,mamicode.com
首页 > 编程语言 > 详细

排序算法总结

时间:2015-07-01 14:13:39      阅读:302      评论:0      收藏:0      [点我收藏+]

标签:排序算法

排序算法经常被用来考察一个人的基础能力。因此,对学过的排序算法进行总结,梳理,教材参照网易云课堂里面的浙大开设的数据结构课程里讲到的排序的内容,附上链接: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)。

 

  • 插入排序

思想:通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。

伪代码:

技术分享

以摸牌为例,容易理解。

时间复杂度:顺序T=O(N),逆序T=O(N2 )

稳定性:稳定

小测试2:给定初始序列{34, 8, 64, 51,32, 21},冒泡排序和插入排序分别需要多少次元素交换才能完成?答案:各9次

 

  • 希尔排序

思想:是插入排序的一种更高效的改进版本,设定一个间隔h,每次利用插入排序交换多个i和i+h对,一趟下来后,将h相应的减少,再重复交换,直到h=1,再进行最后一次交换,排序完成。

伪代码:增量为N/2,需要认真自己画一个例子来理解,这样比较容易记。

技术分享

时间复杂度:不固定,最坏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)

稳定性:稳定

  • 小结

技术分享

每种排序算法有其适用场所,在一定条件下,快速排序才是最适合的。

 

本文链接:http://www.ming-yue.cn/sort-conclusion/

版权声明:本文为博主原创文章,未经博主允许不得转载。

排序算法总结

标签:排序算法

原文地址:http://blog.csdn.net/minglaihan/article/details/46709159

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!