🍬个人主页:Yanni.---
🌈数据结构:Data Structure.
🎂C语言笔记:C Language Notes
🏀OJ题分享: Topic Sharing
目录
[编辑 代码实现](#编辑 代码实现)
[编辑 代码实现](#编辑 代码实现)
前言:
今天给大家带来快速排序,所谓快速,那肯定是时间复杂度更优化的排序,学会了这个排序,在校招的题目,学校的考试,自己对数据结构的理解会变得更好的!
快速排序
快速排序是一种高效的排序算法,其基本思想是通过将待排序的序列划分为左右两个子序列,其中左子序列的元素都小于右子序列的元素,再递归地对子序列进行排序,直到整个序列有序为止。
思路分析
1.选出一个基准值key(一般都是以第一位或者最后一位为准)。
2.将所有比key小的值放在左边,所有比key大的值放在右边。
3.这样就分为了左右两个区间。
4.再将左右两个区间重复1和2操作,依次分治下去,最后就排好序了。
要实现这样的思路有三种方法:挖坑法,左右指针法,前后指针法。
三值取中法
为了避免极端情况(比如序列为逆序或者顺序的情况),选出基准值key可以用三值取中法来进行选择,三值分别是首值,中间值,尾值。
从这三个值当中选择中等的值来作为我们的基准值key,可以增加时间效率。
cs
int GetMidIndex(int* a, int left, int right)
{
int mid = (right + left) >> 1;
if (a[left] > a[mid])
{
if (a[mid] > a[right])
{
return mid;
}
else if (a[left] > a[right])
{
return right;
}
else {
return left;
}
}
//a[left]<a[mid]
else {
if (a[mid] < a[right])
{
return mid;
}
else if (a[left] > a[right])
{
return left;
}
else {
return right;
}
}
}
挖坑法
思路分析
1.将选出的基准值key的位置作为一个坑(pivot)。
2.然后从最后一位开始遍历,找到比key小的值停下,将这个值放到坑里面,然后坑就到了新位置
3.再从第一位开始遍历,找到比key大的值停下,将这个值放在新的坑里面,坑又到了新的位置
4.依次反复进行直到前后遍历碰撞。
图解如下:
代码实现
cs
int PartSort1(int* a, int left, int right)
{
int Index = GetMidIndex(a,left, right);//这里是三数取中,会在下面讲解
Swap(&a[left], &a[Index]);
int begin = left;
int end = right;
int pivot = begin;
int key = a[begin];
while (begin < end)
{
while (begin < end && a[end] >= key)
{
end--;
}
a[pivot] = a[end];
pivot = end;
while (begin < end && a[begin] <= key)
{
begin++;
}
a[pivot] = a[begin];
pivot = begin;
}
pivot = begin;
a[pivot] = key;
return pivot;
}
左右指针法
思路分析
1.左指针begin,右指针end,利用这两个指针前后遍历分别找到比key大的值和比key小的值。
2.将两个值进行交换,再重复1的操作。
3.当begin=end时操作停止,最后将key值与begin位置的值进行交换,完成了排序。
图解如下:
代码实现
cs
int PartSort2(int* a, int left, int right)
{
int Index = GetMidIndex(a, left, right);
Swap(&a[left], &a[Index]);
int begin = left;
int end = right;
int key = begin;
while (end > begin)
{
while (end > begin && a[end] >= a[key])
{
end--;
}
while (end > begin && a[begin] <= a[key])
{
begin++;
}
Swap(&a[end], &a[begin]);
}
Swap(&a[begin], &a[key]);
return begin;
}
前后指针法
思路分析
1.前指针prev,后指针cur,让cur去找比key大的值,找到后prev向前移动一位(prev++),并且与cur位置的值进行交换。
2.重复执行1的操作,知道cur把所有的数据遍历完成。
3.最后将key值与prev位置的值进行交换,完成排序。
图解如下:
代码实现
cs
int PartSort3(int* a, int left, int right)
{
int prev = left;
int cur = left + 1;
int key = left;
while (cur <= right)
{
if (a[cur] < a[key]&&prev++ != cur)
{
Swap(&a[cur], &a[prev]);
}
cur++;
}
Swap(&a[prev], &a[key]);
return prev;
}
快速排序实现
利用分治思想,用递归算法来进行代码实现。
cs
void QuickSort(int* a, int left, int right)
{
if (left >= right)//递归条件
{
return;
}
int KeyIndex = PartSort1(a, left, right);//挖坑法
//int KeyIndex = PartSort2(a, left, right);//左右指针法
//int KeyIndex = PartSort3(a, left, right);//前后指针法
if (KeyIndex - left - 1 > 10)
{
QuickSort(a, left, KeyIndex - 1);
}
else {
InsertSort(a + left, KeyIndex - 1 - left+1);//直接插入排序
}
if (right - KeyIndex - 1 > 10)
{
QuickSort(a, KeyIndex + 1, right);
}
else {
InsertSort(a + KeyIndex + 1, right - (KeyIndex + 1) + 1);//直接插入排序
}
}
冒泡排序
冒泡排序是交换排序的一种。
所谓交换,就是根据序列中两个记录键值的比较结果来对换这两个记录在序列中的位
置,交换排序的特点是:将键值较大的记录向序列的尾部移动,键值较小的记录向序列的前部移
动
思路分析
1.将第一个数与第二个数比较,大者则交换顺序。
2.然后比较对象向后移动一位,继续上一步操作。
3.直到比较完成为止,这样最大的数就排到最后一位。
然后再重复上面的操作,最后所以的数都排好,这就是冒泡排序。
代码实现
这里的flag是优化了基础的冒泡排序,提高了时间效率。
利用flag判断每次轮回序列是否已经排序好,这样可以避免重复的排序。
cs
void BubbleSort(int* a,int n)
{
int end = n - 1;
for (int j = 0; j < end; j++)
{
int flag = 0;
for (int i = 1; i <= end-j; i++)
{
if (a[i - 1] > a[i])
{
Swap(&a[i - 1], &a[i]);
flag = 1;
}
}
if (flag == 0)
{
break;
}
}
}
好啦,这就是今天学习的分享啦!看到希望大家的三连呀!
如果有不当之处,欢迎大佬指正!