拜托,面试不要问我比较排序了——一文搞懂比较排序

比较排序算法小结

前面几篇文章介绍了几类排序的算法:插入交换选择归并。这几类算法有一个共同的特点,都是基于比较的方式进行排序。对于插入、交换、选择,都又划分为基本排序算法及其对应的优化,三种基本排序算法,虽然理解起来直观,但执行效率低下。对应优化算法,依然建立在原有思想的指导之上,对基本算法进行了针对性的修改,具体整理如下:
比较排序

插入排序

直接插入排序将原始序列分为待排序列与已排序列,已排序列初识状态中元素个数为空,通过相邻元素之间的比较,顺序将待排序列中元素加入到已排序列中,最后待排序列变为空。
一个具体的示例是:在打扑克牌时,我们手里抓到的牌是没有顺序的,从左侧第二张牌开始,与手中左侧前面的牌比较,放到合适位置,然后再操作第三章牌,不断重复的这个过程,其实就是直接插入排序。
直接插入排序实例

插入排序的优点是:当初始序列较短以及基本有序的情况下,效率较高。而Shell排序(该算法由1959年公布)正是发扬了这个优点,将待排序列进行分组,达到序列较短的目的,在针对分组内进行直接插入排序后,再进行较大分组的排序时,序列已经基本有序,可以高效的实现排序效果。

交换排序

冒泡排序虽然名字比较好记,但并不是一个高效的算法,它通过相邻元素之间的两两比较来选出最值。之所以低效是因为每次的比较都没能利用前面比较的结果,其对应的优化算法——快速排序(该算法1962年才被提出),基于轴值的比较将元素进行“二分”分解,不断的分组使小组内的元素个数减少,达到0或1个元素个数的基准条件时,即完成了分组的要求,快速排序经过分解实现排序,没有明显的合并过程。

选择排序

直接选择排序与冒泡的区别在于:比较的时候没有进行交换,只记录了索引位置,经过每轮的比较后,得到最值的索引,然后进行一次交换,交换的次数虽然减少了,但比较的次数没有减少,双层循环的实现方式上效率也并不高。
堆排序的实现建立在最大堆或最小堆的基础上,堆的物理结构可通过数组实现,通过这种数据结构封装的相对值的位置,我们不再关心具体实现细节,直接选取最值即可。实际上在最值移出堆的时候,都要调整堆内部结构,调整算法时间复杂度上为O(logN)。

小结

可以看出,三种优化排序都体现了分治算法的设计思想,而上面没有提到的归并排序,更是典型的分治算法的实现思路,从优化算法的提出年份,可以看出这些算法的提出年份都很近,这也说明了为什么比较排序算法凝结了人类的智慧的精华,值得我们细细体会。

参考资料:
算法导论

欢迎关注我的GitHub,下载排序代码(Java语言描述)示例

欢迎关注我的公众号,了解更多内容:
我的公众号

发布了159 篇原创文章 · 获赞 225 · 访问量 21万+

猜你喜欢

转载自blog.csdn.net/lyg673770712/article/details/86713465