最详细的排序算法讲解!一看就懂!

您所在的位置:网站首页 izone成员年龄大小排序 最详细的排序算法讲解!一看就懂!

最详细的排序算法讲解!一看就懂!

2024-04-17 07:20| 来源: 网络整理| 查看: 265

排序算法对大家来说肯定都不陌生吧,作为最基础且最重要的算法之一,在面试中经典排序算法也经常被要求手撕代码。可是排序算法实在是太多了(见下图),有些名字听起来都莫名其妙的,比如鸡尾酒排序,侏儒排序,煎饼排序等。 当然,这篇文章会为大家讲解众多排序算法中最经典的部分,也是大家最熟悉的几种算法,包括冒泡排序、插入排序、选择排序、归并排序、计数排序、基数排序、桶排序、希尔排序、堆排序。同时也会利用一些手绘图来帮助大家更好地理解,希望大家在阅读完本文章后都能够有所收获。

声明: 在下面讲解的所有算法中,我们默认需要对待处理的数组进行升序排序。即排序好的数组中,元素的大小从左到右递增排序。

预备知识

在正式开始讲解各种排序算法之前,我还希望大家思考一个问题。什么样的排序算法才是一个好的算法,各种各样的排序算法它们的应用场景又有什么不同?希望大家在读完这篇文章之后能够有一个答案。

其实,要想真正学好排序算法,我们要做的不仅仅是了解它的算法原理,然后背下代码就完事。更重要的是,我们要学会去分析和评价一个排序算法。那么对于这么多的排序算法,我们应该关注它们的哪些方面呢?

1.排序算法的时间复杂度

分析一个算法的好坏,第一个当然就是应该分析该算法的时间复杂度。排序算法需要对一组数据进行排序,在实际的工程中,数据的规模可能是10个、100个,也可能是成千上万个。同时,对于要进行排序处理的数据,可能是接近有序的,也可能是完全无序的。因此,在分析其时间复杂度时,我们不仅要考虑平均情况下的时间复杂度,还要分析它在最好情况以及最坏情况下代码的执行效率有何差异。

对于一个常见的排序算法来说,执行过程中往往会涉及两个操作步骤,一个是进行元素的比较,二是对元素进行交换或者移动。所以在分析排序算法的时间复杂度时,也要特别注意算法实现过程中不同的元素比较和交换(或移动)的次数。

2.排序算法的空间复杂度

这里需要引入一个新的概念,原地排序。原地排序就是指在排序过程中不必申请额外的存储空间,只利用原来存储待排数据的存储空间进行比较和排序的排序算法。换句话说,原地排序不会产生多余的内存消耗。

3.排序算法的稳定性

对于一般的算法,我们一般只需要分析它的时间复杂度和空间复杂度,但是对于排序算法来说,我们还有一个非常重要的分析指标,那就是排序算法的稳定性。

稳定性是指,在需要进行排序操作的数据中,如果存在值相等的元素,在排序前后,相等元素之间的排列顺序不发生改变。

大家可能会想,反正都是相等的元素,通过排序后谁在前谁在后有什么不一样呢?对排序算法进行稳定性分析又有什么实际意义呢?

其实,在学习数据结构与算法的过程中,我们解决的问题基本上都是对简单的数字进行排序。这时,我们考虑其是否稳定似乎并没有什么意义。

但是在实际应用中,我们面对的数据对象往往都是复杂的,每个对象可能具有多个数字属性且每个数字属性的排序都是有意义的。所以在排列时,我们需要关注每个数字属性的排序是否会对其他属性进行干扰。

举个例子,假如我们要给大学中的学生进行一个排序。每个学生都有两个数字属性,一个是学生所在年级,另一个是学生的年龄,最终我们希望按照学生年龄大小进行排序。而对于年龄相同的同学,我们希望按照年级从低到高的顺序排序。那么要满足这样的需求,我们应该怎么做呢?

第一个想到的,当然就是先对学生的年龄进行排序,然后再在相同年龄的区间里对年级进行排序。这种办法很直观且似乎没什么问题,但是仔细一想,会发现如果我们要进行一次完整的排序,我们需要采用5次排序算法(按年龄排序1次,四个年级分别排序4次)。那么我们有没有更好地解决办法呢?

如果我们利用具有稳定性的排序算法,这个问题就会更好地解决了。我们先按照年级对学生进行排序,然后利用稳定的排序算法,按年龄进行排序。这样,只需要运用两次排序,我们就完成了我们的目的。

这是因为,稳定的排序算法能够保证在排序过程中,相同年龄的同学,在排序之后,他们的顺序不发生改变。由于第一次我们已经将学生按年级排序好了,于是在第二次排序时,我们运用稳定的排序算法,相同年龄的学生依旧按年级保持顺序。

了解如何分析排序算法后,接下来就可以开始下面各种排序算法的学习了。

算法介绍1.插入排序(Insertion Sort)

在讲解插入排序之前,我们先来回顾一下,在一个有序数组中,我们是如何插入一个新的元素并使数组保持有序的呢?

我们需要遍历整个数组,直到找到该元素应该插入的位置,然后将后面相应的元素往后移动,最后插入我们的目标元素。(插入过程如下图)

插入排序其实就是借助这样的思想,首先我们将数组中的数据分为两个区间,一个是已排序区间,另一个是未排序区间,同时这两个区间都是动态的。开始时,假设最左侧的元素已被排序,即为已排序区间,每一次将未排序区间的首个数据放入排序好的区间中,直达未排序空间为空。

插入排序算法图解如下:

插入排序代码实现:#include #include using namespace std; void InsertionSort(vector&, int); int main() { vector test = { 3, 7, 6, 4, 5, 1, 2, 8 }; InsertionSort(test, test.size()); for (auto x : test) cout


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3