基本排序算法比较


欢迎大家访问我的个人博客:endeavorchuan.com

算法的稳定性

若待排序表中有两个元素a和b,对应关键字A=B,排序之前a在b的前面,若在排序操作之后,a仍然在b的前面,那么这个排序算法就是稳定的。

若在排序之后a移到了b之后,那么这个排序算法就是不稳定的。

一、插入排序

每次将一个待排序的记录按照关键字的大小插入到前面已经有序的子序列中,直到所有的记录插入完成。

从前面的子表中找到待插入元素应该被插入的位置,再给插入位置腾出空间进行插入元素操作。

包括:直接插入排序、折半插入排序、希尔排序

1、直接插入排序

若在排序过程中,待排序表L[1…n]在某次排序过程中,出现如下情况:
Alt
若想把L[i]插入到前半有序序列中,则进行直接插入排序操作,思想如下:

①将L[i]分别于L[1…i-1]比较,找到要插入的位置k

②将L[k…i-1]的所有元素向后移动一位,为L[i]的插入预留位置

③将L[i]复制到L[k]中,即完成了L[i]的插入

时间复杂度:O(n2)。空间复杂度:O(1)。
稳定性:稳定的排序算法。
适用于顺序存储和链式存储结构。

2、折半插入排序

将比较操作和插入操作分离,先使用折半查找法查找出元素的待插入位置,然后移动待插入位置之后的所有元素。

采用折半查找法可以减少元素的比较次数,但不会减少元素的移动次数。

对于数据量较小的排序表,可表现出较直接插入排序更好的性能。

时间复杂度:O(n2)。空间复杂度:O(1)。
稳定性:稳定的排序算法。
适用于顺序存储结构。

3、希尔排序(缩小增量排序)

先选取一个步长d1,将待排序表分成d1组,所有d1的倍数放在同一组,对每组进行直接插入排序。

第一轮:
Alt
如图所示为长度为18的待排序表,按照步长d1=3,将表分为3组,即a、b、c,并分别对这三组进行直接插入排序。

第一轮排序后,在选取步长d2<d1,继续进行划分。

第二轮:
Alt
第二轮将步长缩减为2,将整个待排序表分为2组,即x、y,分别对这两组进行直接插入排序。

之后进行最后一轮排序,将步长缩减至1,即对整个排序表进行直接插入排序。

第三轮:
Alt
最后一轮将整个待排序数组全部进行直接插入排序。

时间复杂度:O(n2)。空间复杂度:O(1)。
稳定性:不稳定的排序算法。
仅适用于顺序存储结构。

二、交换排序

先比较待排序列中两个关键字的大小,根据比较结果调换两个关键字的位置。

1、冒泡排序

对于一个长度为n的待排序表:

①从后往前两两比较相邻元素的值,若为逆序,则调换两元素的位置,直到序列第一次比较完。

第一次比较之后,最小的元素会到达待排序列的第一个位置,也就是它的最终位置;

②第二趟冒泡中,之前确定的最小元素不再参与比较,需要比较的元素为n-1个,直到序列第二次比较完。

③每次冒泡会把值最小的元素放置在最终位置,最多n-1趟冒泡可完全排好序。

时间复杂度:O(n2)。空间复杂度:O(1)。
稳定性:稳定的排序算法。
适用于顺序存储和链式存储结构。

2、快速排序

基于分治法思想进行排序,是冒泡排序的一种改进。

①首先在待排序表中任取一个元素k为基准;Alt
②第一趟排序将整个表分为两部分L[1…k-1]和L[k+1…n],

其中L[1…k-1]中元素全部小于L[k],L[k+1…n]中元素全部大于L[k];Alt
③对于划分出的左右两个子表,继续分别选取基准元素;Alt
④对子表重复上述排序过程;
Alt
⑤递归重复上述过程,直至每个部分只有一个元素或为空为止;Alt
⑥在最后一次排序之后,所有元素都放在了其最终的位置上,快速排序结束。Alt
由上述例子可以看出,快速排序算法的性能主要取决于划分操作的好坏。

快速排序是一个递归的排序算法,需要借助一个递归工作栈保存每层递归调用的必要信息。工作栈的容量应与递归调用的最大深度一致。

为了提高算法效率,第一种方法可以将与其他排序算法相结合,当递归过程中划分得到的子序列规模较小时,可直接采用直接插入排序算法完成后续的排序工作;第二种方法可以尽量选取一个将数据中分的基准元素,可以避免排序中最坏情况的发生。

时间复杂度:O(nlog2n)。空间复杂度:O(nlog2n)
稳定性:不稳定的排序算法。
适用于顺序存储结构。

三、选择排序

1、简单选择排序

对于一个长度为n的待排序表L[n]来说,若前半部分L[1…i-1]有序,后半部分L[i…n]无序。

则每次排序过程中,在L[i…n]中选择一个最小的元素,插入到L[1…i-1]的末尾。

新得到的L[1…i]仍然有序,后半部分L[i+1…n]继续重复上述操作,当后半部分只剩下一个元素时,直接插入前半部分的末尾,此时整个表有序。

时间复杂度:O(n2)。空间复杂度:O(1)
稳定性:不稳定的排序算法。
适用于顺序存储和链式存储结构。

2、堆排序

将待排序表L[1…n]视为一棵完全二叉树的顺序存储结构,利用完全二叉树中双亲结点和孩子结点的内在关系,在当前的无序区中选择关键字最大(最小)的元素。

在完全二叉树中,若L[i]为双亲结点,则L[2i]为它的左孩子结点,L[2i+1]为右孩子结点。

小根堆: L[i]≤L[2i],且L[i]≤L[2i+1],其中i≤n/2,最小结点存放在根节点中。AltAlt
大根堆:L[i]≥L[2i],且L[i]≥L[2i+1],其中i≤n/2,最大结点存放在根节点中。AltAlt
堆排序的第一步就是建立堆,是一个自下向上反复筛选的过程。首先对n/2为根的子树筛选,使其成为堆,再依次对之前各结点为根的子树进行筛选,直到根结点为止。

Alt
大根堆排序过程:

①将存放在待排序表中的n个元素建立成初始堆;

②输出堆顶元素,由于堆本身特点,堆顶元素就是最大值;

③将堆底元素送入堆顶,此时堆被破坏,需重新构造以满足大根堆性质;

④继续输出栈顶元素,重复上述过程,直至堆中只剩下一个元素为止。

时间复杂度:O(nlog2n)。空间复杂度:O(1)
稳定性:不稳定的排序算法。
适用于顺序存储结构。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一个昵称被占用的川川

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值