《大话数据结构》第9章 排序 9.10 总结回顾
9.10 总结回顾
事实上,目前还没有十全十美的排序算法,有优点就会有缺点,即使是快速排序法,也只是在整体性能上优越,它也存在排序不稳定、需要大量辅助空间、对少量数据排序无优势等不足。因此我们就来从多个角度来剖析一下提到的各种排序的长与短。
本章内容只是在讲排序,我们需要对已经提到的各个排序算法进行对比来总结回顾。
首先我们讲了排序的定义,并提到了排序的稳定性,排序稳定对于某些特殊需求来说是至关重要的,因此在排序算法中,我们需要关注此算法的稳定性如何。
我们将排序记录是否全部被放置在内存中,将排序分为内排序与外排序,外排序需要在内外存之间多次交换数据才能进行。我们本章主要讲的是内排序的算法。
根据排序过程中借助的主要操作,我们将内排序分为:插入排序、交换排序、选择排序和归并排序四类。之后介绍的七种排序法,就分别是各种分类的代表算法。
我们将七种算法的各种指标进行对比,如表9-10-2所示。
从算法的简单性来看,我们将七种算法分为两类
1) 简单算法:冒泡、简单选择、直接插入。
2) 改进算法:希尔、堆、归并、快速。
从平均情况来看,显然后三种改进算法要胜过希尔排序,并远远胜过前三种简单算法。
从最好情况看,反而冒泡和直接插入排序要更胜一筹,也就是说,如果你的待排序序列总是基本有序,反而不应该考虑四种复杂的改进算法。
从最坏情况看,堆排序与归并排序又强过快速排序以及其他简单排序。
从这三组时间复杂度的数据对比中,我们可以得出这样一个认识。堆排序和归并排序就像两个参加奥数考试的优等生,心理素质强,发挥稳定。而快速排序像是很情绪化的天才,心情好时表现极佳,碰到较糟糕环境会变得差强人意。但是他们如果都来比赛计算个位数的加减法,它们反而算不过成绩极普通的冒泡和直接插入。
从空间复杂度来说,归并排序强调要马跑得快,就得给马吃个饱。快速排序也有相应的空间要求,反而堆排序等却都是少量索取,大量付出,对空间要求是O(1)。如果执行算法的软件所处的环境非常在乎内存使用量的多少时,选择归并排序和快速排序就不是一个较好的决策了。
从稳定性来看,归并排序独占鳌头,我们前面也说过,对于非常在乎排序稳定性的应用中,归并排序是个好算法。从待排序记录的个数上来说,待排序的个数n越小,采用简单排序方法越合适。反之,n越大,采用改进排序方法越合适。这也就是我们为什么对快速排序优化时,增加了一个阀值,低于阀值时换作直接插入排序的原因。
你会发现,此时简单选择排序就变得非常有优势,原因也就在于,它是通过大量比较后选择明确的记录进行移动,有的放矢。因此对于数据量不是很大,而记录的关键字信息量较大的排序要求,简单排序算法是占优的。另外,记录的关键字信息量大小对那四个改进算法影响不大。
从上表的数据中,似乎简单选择排序在三种简单排序中性能最差,其实也不完全是,比如说如果记录的关键字本身信息量比较大(例如关键字都是数十位的数字),此时表明其占用存储空间很大,这样移动记录所花费的时间也就越多,我们给出三种简单排序算法的移动次数比较,如表9-10-3所示。
总之,从综合各项指标来说,经过优化的快速排序是性能最好的排序算法,但是不同的场合我们也应该考虑使用不同的算法来应对它。
9.11 结尾语
大家举手很快,因为绝大数同学应该都看过这道题目。没有做过题目的同学通常十有易做图会落入一个小小的陷阱,在九个点围成的框中打转转,然后发现至少要五段以上的直线才能连成。结果是,要找到答案,必须在思维上突破这九个点所围成的框框的限制。
学完排序,你能够感受到,我们的算法研究者们都是在“似乎不可能”的情况下,逐步提高排序算法的性能的。在剩下的几分钟时间里,我们再来做一道智力题,感受一下把不可能变为可能。
请问如何把图9-11-1的用四段直线一笔将这九个点连起来?
如果智力题这就结束了,那就不考大家了。现在我的问题是如何做到三段直线一笔将这九个点连起来?
此时,大家都在交头接耳,心里一定想着,“这怎么可能?”我来公布答案,那就是用一条“Z”字线即可一笔连成。也许,最快找出这个答案的是那些没有学过数学的孩子。作为易做图,我们已被另一些“框框”所框住大脑。那就是数学上有一条基本公理:两条平行线永不相交。另外数学上有另一个基本假设:点没有大小。可在现实中任何一点都会有大小。突破这一限制,只要无限延长“Z”字三段线,九点必可一笔连。来看图9-11-3。
有同学说,我图中的点比刚才的要大,这不符合题意。我想有这样想法的同学,可能还是没有理解我想表达的意思,事实上,刚才的小黑点再小,它也是有大小的,你可以想像三根直线足够长,它们就可以将这九个点相连了。
别急,题目没完,我现在要求只用一条直线将这九点一笔连,如何做?
显然,大家的思维已经被打开。我们可轻易找到答案,因为只要再次突破几何学中“线没粗细”的框框,用一条很粗的线,比如蘸了墨水的大刷子,画一条粗粗的直线将九点全部包含其中即可。
不是不可能用四段、三段、一段直线一笔连九点,只是暂时还没有找到方法而已。现实生活中所有的发明创造都是建立在打破前人所认定的“框框”的思维定势基础上的。这道智力题当然不是要挑战数学的权威,它只是在给我们启示:“所有的事情都是可能的,只是我们暂时还没有找到方法而已。”本章的结束,其实也就是数据结构这门课的结束了。数据结构和算法,还有很多内容我们并没有涉及。要想真正掌握数据结构,并把它应用到工作中,你们的路还很长。
最后送大家电影《当幸福来敲门》中的一句话:“You got a dream,you gotta protect it. People can’t do something themselves, they wanna tell you you can’t do it. If you want something, go get it. Period.如果你有梦想的话,就要去捍卫它。当别人做不到的时候,他们就想要告诉你,你也不能。如果你想要些什么,就得去努力争取。这就样!”
我们生命中,矛盾和困惑往往一直伴随。很多同学来学习数据结构,其实并不是真的明白它的重要性,通常只是因为学校开了这门课,而不得不来这里弄个PASS,过后,真到需要用时,却发现力不从心而追悔莫及。比如图9-11-4,悲剧通常就是这样产生的。因此尽管现在是课程的最后,对于个别没有重视这门课的同学来说有些晚了,我还是想再亡羊补牢:数据结构和算法对于程序员的职业人生来说,那就是两个圆圈的交集部分,用心去掌握它,你的编程之路将会是坦途。
同学们,再见!
补充:综合编程 , 其他综合 ,