当你清楚的知道自己想要什么,并且意愿非常强烈的时候,你总会有办法得到的。💓💓💓
目录
✨说在前面
🍋知识点一:快速排序
• 🌰1.快速排序介绍
• 🌰2.霍尔排序
•🔥三数取中优化
•🔥小区间优化
• 🌰3.前后指针法
• 🌰4.快排非递归方法
🍋知识点二:归并排序
• 🌰1.归并排序介绍
• 🌰2.归排非递归方法
🍋知识点三:排序算法总结
• 🌰1.复杂度即稳定性分析
• 🌰2.排序性能比较
• ✨SumUp结语
✨说在前面
亲爱的读者们大家好!💖💖💖,我们又见面了,上一篇文章中我带大家学习了冒泡排序、插入排序、希尔排序、选择排序、堆排序和计数排序,如果大家没有掌握好,可以再回去看看,复习一下,再进入今天的内容。
今天我们将要学习的排序有——快速排序(霍尔法、左右指针法、非递归)、归并排序(递归、非递归)。如果大家准备好了,那就接着往下看吧~
👇👇👇
💘💘💘知识连线时刻(直接点击即可)🎉🎉🎉复习回顾🎉🎉🎉
【数据结构】排序算法(冒泡排序、插入排序、希尔排序、选择排序、堆排序、计数排序)
博主主页传送门:愿天垂怜的博客
🍋知识点一:快速排序
• 🌰1.快速排序介绍
快速排序(Quick Sort)是一种非常高效的排序算法,由C. A. R. Hoare在1960年提出。它的基本思想是:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。
以霍尔版本示例:
• 🌰2.霍尔排序
快速排序霍尔法基于分治法的策略来将一个大列表(或数组)分为两个较小的子列表,这两个子列表分别包含原列表中所有小于和大于某个“基准”(pivot)值的元素。然后,递归地对这两个子列表进行相同的操作,直到整个列表变得有序。
霍尔法基本思想:
-
选择基准值:从待排序的列表中选出一个元素作为基准值。选择基准值的方法有多种,如选择第一个元素、最后一个元素、中间元素,或者使用更复杂的策略如“三数取中”法来选择,以期望得到更平衡的分区。
-
分区操作:重新排列列表,所有比基准值小的元素摆放在基准前面,所有比基准值大的元素摆在基准的后面(相等的数可以到任一边,但通常放在基准的一边以保持稳定性,尽管快速排序本身不是稳定的排序算法)。这一步是快速排序的核心,也是它名称的由来——通过一次分区操作,列表就被“快速”地分成了两部分。
-
递归排序:递归地对基准值左右两边的子列表进行快速排序。由于分区操作保证了基准值左边的所有元素都不大于基准值,右边的所有元素都不小于基准值,因此可以独立地对这两个子列表进行排序。
-
终止条件:递归的终止条件是子列表的大小为0或1,即不需要再排序。
代码如下:
void QuickSort(int* arr, int left, int right)
{
assert(arr);
//保证区间存在且元素大于1
if (left >= right)
return;
//记录基准值
int keyi = left;
//记录区间端点值
int begin = left, end = right;
while (begin < end)
{
//找比基准值大的数
while (arr[end] >= arr[keyi] && begin < end)
end--;
//找比基准值小的数
while (arr[begin] >= arr[keyi] && begin < end)
begin++;
//找到后交换
Swap(arr + begin, arr + end);
}
//交换keyi与begin的值
Swap(arr + left, arr + keyi);
keyi = begin;
//递归左右区间
QuickSort(arr, left, keyi - 1);
QuickSort(arr, keyi + 1, right);
}
霍尔法时间复杂度分析:
-
最好情况:在最好情况下,即每次分区操作都能将数组划分为两个大小相等的部分,此时快速排序的时间复杂度为O(nlogn)。这是因为每次分区后,问题规模减半,递归深度为logn,每层递归需要遍历数组一次,所以总的时间复杂度是O(nlogn)。
-
最坏情况:在最坏情况下,例如排序序列本身为有序,此时快速排序的时间复杂度退化到O(n^2)。这是因为每次分区操作只能排除一个元素,那么总的消耗与递归深度成等差数列,总的时间复杂度是O(n^2)。
-
平均情况:平均情况下,快速排序的时间复杂度也是O(nlogn)。这是通过随机选择基准元素或采用其他策略(如三数中值分割法)来减少最坏情况发生的概率来实现的。
稳定性分析:
-
快速排序的不稳定性:
在快速排序的过程中,通过选取一个基准元素(keyi),将数组分为两部分,小于基准的元素放在基准前面,大于基准的元素放在基准后面。这个过程中,如果数组中存在两个相等的元素,并且这两个元素分布在基准的两侧,那么在交换过程中,它们的相对位置很可能会发生改变。具体来说,当基准元素与某个大于它的元素交换时,如果基准元素原本与某个等于它的元素相邻,且该等于它的元素在基准的另一侧,那么交换后,这两个相等元素的相对位置就发生了改变。 -
实例说明:
考虑一个序列 [6,6,6,5,6,6,6],如果选取第一个元素6作为keyi,进行一趟快速排序后,得到 [5,6,6,6,6,6,6] 。在这个例子中,显然6的相对位置发生了改变,因此快速排序是不稳定的。
总结:霍尔法的时间复杂度为O(nlogn),但某些情况下会退化到O(n^2),是不稳定的排序算法。
左边做key,右边先走为什么可以保证相遇的位置一定比key要小?
-
L遇R:R先走,停下来,R停下来的条件是遇到比key小的值,R停下的位置一定比key小。此时,即L没有找到大的,遇到R停下了。
-
R遇L:R先走,找小,没有找到比key小,直接和L相遇了,L停留的位置是上一轮交换的位置,上一轮交换,把比key小的值换到L的位置了。