排序算法各个算法介绍

本文详细介绍了几种基本的排序算法:冒泡排序、选择排序、插入排序、希尔排序以及归并排序和快速排序。每种排序算法的原理、过程和时间复杂度进行了分析,其中快速排序由于其高效的性能和原地排序特性,成为大规模数据排序的首选。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、基本排序算法
1、 冒泡排序
假如我们现在按身高升序排队,一种排队的方法是:从第一名开始,让两人相互比身高,若前者高则交换位置,更高的那个在与剩下的人比,这样一趟下来之后最高的人就站到了队尾。接着重复以上过程,直到最矮的人站在了队列首部。我们把队头看作水底,队尾看作水面,那么第一趟比较下来,最高的人就像泡泡一样从水底”冒“到水面,第二趟比较则是第二高的人……排队的过程即为对数据对象进行排序的过程(这里我们排序的”指标“是身高),上述过程即描述了冒泡排序的思想。从以上过程我们可以看到,若对n个人进行排队,我们需要n-1趟比较,而且第k趟比较需要进行n-k次比较。通过这些信息,我们能够很容易的算出冒泡排序的复杂的。首先,排序算法通常都以数据对象的两两比较作为”关键操作“,这里我们可以得出,冒泡排序需要进行的比较次数为: (n-1) + (n-2) + … + 1 = n*(n-1) / 2,因此冒泡排序的时间复杂度为O(n^2)。
2. 选择排序
回到上面我们提到的排队问题,除了上面提到的方法,还有这样一种排队的方法,让目前队头的人依次与其后的每个人进行比较,比较后较矮的那个人继续与后面的人进行比较,这样第一趟比较下来,就能够找到最矮的人, 然后把这个最矮的人和当前队头的人交换一下位置。然后第二趟比较,让第二名依次与后面比较,可以找到第二矮的人,然后让第二矮的人和当前队列第二名交换位置,依此类推,一共进行n-1趟比较后,就能完成整个排队过程。根据上述描述,我们可以知道,第k趟比较需要进行的数组元素的两两比较的次数为n-k次,所以共需要的比较次数为n*(n-1) / 2,因此选择排序算法的时间复杂度与冒泡排序一样,也为O(n^2)。
3. 插入排序
回想下我们平时打扑克抓牌的过程,通常我们用右手抓牌,每抓一张牌,就放到左手上,抓下一张牌后,会把这张牌依次与左手上的牌比较,并把它插入到一个合适的位置(通常按照牌面大小)。上述的过程即为插入排序的过程,假设待排序数组为a,我们从a[1]开始,让a[1]与a[0]比较,若a[1]较小,则让a[1]和a[0]交换位置,此时a[0]和a[1]就相当于已经放入左手中的牌。然后我们再让a[2]与a[1]、a[0]比较,并为它找到一个合适的位置,以此类推,直到为数组的最后一个元素也找到了合适的位置。理解了插入排序的思想后,我们便能够得到它的时间复杂度。对于n个元素,一共需要进行n-1轮比较,而第k轮比较需要进行k次数组元素的两两比较,因此共需要进行的比较次数为:1 + 2 + … + (n-1),所以插入排序的时间复杂度同冒泡排序一样,也为O(n^2)。
4. 希尔排序
希尔排序是对插入排序的一种改进,它的核心思想是将待排序数组中任意间隔为h的元素都变为有序的,这样的数组叫做h有序数组。比如数组[5, 3, 2, 8, 6, 4, 7, 9, 5], 我们可以看到a[0]、a[3]、a[6]是有序的,a[1]、a[4]、a[7]是有序的,a[2]、a[5]、a[8]是有序的,因此这个数组是一个h有序数组(h=3)。根据h有序数组的定:义,我们可以知道,当h=1时,相应的h有序数组就是一个已经排序完毕的数组了。希尔排序的大致过程如下:把待排序数组分割为若干子序列(一个子序列中的元素在原数组中间隔为h,即中间隔了h-1个元素),然后对每个子序列分别进行插入排序。然后再逐渐减小h,重复以上过程,直至h变为足够小时,再对整体进行一次插入排序。由于h足够小时,待排序数组的逆序数已经很小,所以再进行一次希尔排序是很快的。希尔排序通常要比插入排序更加高效。 实现希尔排序时,我们需要选取一个h的取值序列,这里我们直接采用算法(第4版) (豆瓣)一书中提供的h取值序列(1,4,13,40,121, …)。即h = 3 * k + 1,其中k为[0, N/3)区间内的整数。
二、归并排序
归并排序使用了一种叫做”分治“的思想来解决排序问题。分治也就是"分而治之“,也就是把一个大问题分解为众多子问题,而后分别得到每个子问题的解,最终以某种方式合并这些子问题的解就可以得到原问题的解。归并排序的主要思想是:将待排序数组递归的分解成两半,分别对它们进行排序,然后将结果“归并”(递归的合并)起来。我们知道,递归算法都有一个base case,递归分解数组的base case就是分解完的两个数组长度为为1,这时候它们本身就有序,此时就可以进行归并了。
三、快速排序
快速排序是目前应用最广泛的排序算法之一,它是一般场景中大规模数据排序的首选,它的实际性能要好于归并排序。通常情况下,快速排序的时间复杂度为O(nlogn),但在最坏情况下它的时间复杂度会退化至O(n^2),不过我们可以通过对输入数组进行“随机化”(打乱元素的排列顺序)来避免最坏情况的发生。除了实际执行性能好,快速排序的另一个优势是它能够实现“原地排序”,也就是说它几乎不需要额外的空间来辅助排序。
快速排序的主要思想如下:假设待排序数组为a[0…N-1],递归的对该数组执行以下过程:选取一个切分元素,而后通过数组元素的交换将这个切分元素移动到位置j,使得所有a[0…j-1]的元素都小于等于a[j],所有a[j+1…N-1]的元素都大于等于a[j]。
在快速排序中,切分元素的选取很关键,通常我们可以选取输入数组的第一个元素作为切分元素,然后把它交换到数组中的合适位置使得它左边的元素都小于等于它,右边的元素都大于等于它,而后对其左右两边的子数组递归执行切分过程,即可完成对整个数组的排序。
四、堆排序
堆排序(Heapsort)是指利用堆这种数据结构所设计的一种排序算法。堆积是一个近似完全二叉树的结构,并同时满足堆积的性质:即子结点的键值或索引总是小于(或者大于)它的父节点。堆排序可以说是一种利用堆的概念来排序的选择排序。分为两种方法:
大顶堆:每个节点的值都大于或等于其子节点的值,在堆排序算法中用于升序排列;
小顶堆:每个节点的值都小于或等于其子节点的值,在堆排序算法中用于降序排列;
堆排序的平均时间复杂度为 Ο(nlogn)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值