排序的基本概念与分类--冒泡排序+直接选择排序+直接插入排序+快速排序

排序
一、排序的基本概念与分类
1、排序的定义
假设含有n个记录的序列为{r1,r2,……rn},其相对应的关键字分别为{k1,k2,……kn},需确定一种序列,使其关键字满足k1<=k2<=……<=km(非递减)或k1>=k2>=……>=km(非递增)关系,即使得序列成为一个按关键字有序的序列{r1,r2,……,rm},这样的操作就称为排序。
排序的依据是关键字之间的大小关系,那么,对于同一个记录集合,针对不同的关键字进行排序,可以得到不同的序列。
2、排序的稳定性
假设在排序前,有ki=kj(1<=i<=n,1<=j<=n,i不等于j),且在排序前的序列中ri位置领先于rj(即i<j)。如果排序后ri仍然领先于rj,则称所用的方法是稳定的;反之,若可能使得排序后的序列中rj领先ri,则称所用的排序算法是不稳定的。
例如有序列:
编号 姓名 总分
1 Li 750
2 Liu 730
3 Zhou 738
4 Han 750
此时我们按总分排序,如果得到
1 Li 750
4 Han 750
2 Zhou 738
3 Liu 730
这样排序算法就是稳定的。而如果得到
4 Han 750
1 Li 750
2 Zhou 738
3 Liu 730
则这样的排序算法就是不稳定的。
对于多个关键字排序时,如果有一组关键字会得到不稳定的结果,则我们就认为此排序算法是不稳定的。

二、冒泡排序
无论学习哪种编程语言,当学习到循环与数组等概念的时候,通常会介绍一种排序算法来作为例子或练习。而这种排序算法通常都是冒泡排序。
1、最简单的冒泡排序
冒泡排序(Bubble Sort)是一种交换排序,它的基本思想是:两两比较相邻记录的关键字,如果反序则交换,直到没有反序为止。
在排序过程中,较小的数字(或较大的数字)会如同水下的气泡一样慢慢浮出水面,冒泡排序的命名就此而来。
//代码见附录
2、冒泡排序优化1
冒泡排序是否可以进行优化呢?答案是肯定的。
如果待排序数据是基本有序的(例如2,1,3,4,5,6,7,8,9,10,除了第一和第二个关键字不同,需要交换外,其他数据关键字都已经有序。此时我们只需交换这两个数字即可,而无需将冒泡排序执行到底。
我们可以设置一个标志位flag,用它来指示一次冒泡排序执行后是否有数据交换。如果一次排序后没有数据交换,我们就可以认为数据已经有序,无需再继续执行后面的工作了。
//代码见附录
代码改动的关键就是在外层循环for()的结束条件中,增加了对flag是否是true的判断。这样的改进能避免数据在有序的情况下做无意义的循环判断,从而提升效率。
3、冒泡排序优化2
从另一个角度来想,一次循环数据从前扫描到后,然后再从前扫描到后……也就是说,“磁头”扫描一个来回移动一个关键字使其有序。如果我们能在“磁头”移动回表头时,也能移动一个关键字,那么就相当于一次扫描一个来回移动两个关键字,可以提升其执行效率。
//代码见附录

三、直接选择排序
冒泡排序是基于比较和交换的排序,其算法思想就是不断交换,通过交换完成最终排序。而直接选择排序则是基于选择的排序,其算法思想是每次选出待排数据的关键字中最大(或最小)的数据作为第i个记录。
1、直接选择排序算法
选择排序算法(Selection Sort)就是通过n-i次关键字比较,从n-i+1个数据中每次挑选出关键字最小(或最大)的数据并和第i(1<=i<=n)个数据交换之。
//代码见附录
注意代码中的min是这次排序过程中最小数据的下标。
从性能上来说,选择排序略优于冒泡排序。

四、直接插入排序
扑克牌是我们都玩过的游戏。那么摸到手的扑克牌如何理牌呢?一般情况下,都是选出一张牌,将它放置在比它大和比它小的两张牌之间。这里我们用于理牌的方法就是直接插入排序。
1、直接插入排序算法
直接插入排序算法(Straight Insertion Sort)的基本操作是将一个数据插入到一个已经排好序的有序表中,从而得到一个新的有序表。重复这个过程,直至所有数据有序。
//代码见附录
需要注意的是,直接插入排序需要一个已经有序的序列作为“基准”。代码中,选区r[0]与r[1]作为基准,在排序前,需要判断r[0]与r[1]的关系保证其是有序表。可以尝试省略掉这一步,观察排序后的内容。
从性能上来说,直接插入排序略优于冒泡排序。

五、快速排序
上文中介绍的的冒泡排序、选择排序、直接插入排序及其改进版本,都属于简单排序算法。因为它们的时间复杂度都为O(n^2)。而改进排序算法(Shell排序、堆排序、归并排序、快速排序)的时间复杂度都为O(nlogn)甚至更快。在这里我们主要学习快速排序。
1、快速排序算法
快速排序算法最早由图灵奖获得者Tony Hoare于1962年设计出来,被称为“20世纪十大算法”之一。
快速排序相当于冒泡排序的升级,二者都属于交换排序类。
快速排序(Quick Sort)的基本思想是:通过一趟排序将待排数据分割成独立的两部分,其中一部分的关键字都比另一部分的关键字小。之后对这两部分分别进行排序,最终达到整体有序。
快速排序算法的文字描述是:
1)设置两个变量i、j,排序开始的时候:i=0,j=N-1;
2)以第一个数组元素作为关键数据,赋值给key,即key=A[0];
3)从j开始向前搜索,即由后开始向前搜索(j--),找到第一个小于key的值A[j],将A[j]和A[i]互换;
4)从i开始向后搜索,即由前开始向后搜索(i++),找到第一个大于key的A[i],将A[i]和A[j]互换;
5)重复第3、4步,直到i=j;此时令循环结束。将key值赋值到i(或j)的位置。
6)递归操作数组A[]在key值左的左半部分。
7)递归操作数组A[]在key值右的右半部分。
//代码见附录

2、快速排序算法的优缺点
快速排序算法之所以叫“快速”排序,意味着目前阶段没有人找到更优秀于这个算法的排序算法。如果某一天有人找到了更好的排序算法,“快速”就会名不副实,不过,至今为止,Tony Hoare发明的排序算法经过多次优化后,在整体性能上,依然是排序算法中的王者。
不过快速排序算法仍有缺陷,快速排序算法虽然对大数据排序十分擅长,但不擅长数据不多时进行排序。在数据不多时,快速排序与冒泡排序几乎看不出时间上的优势,只有数据足够大时,快速排序才能发挥出它的优势。因此我们在对数据进行排序时,若数据量不太多,可以选择使用三种简单排序算法(冒泡排序、选择排序、直接插入排序);若数据量巨大,我们再选择快速排序。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值