感谢各位大佬的光临,希望和大家一起进步,望得到你的三连,互三支持,一起进步
前言
前面讲了很多的排序算法,今天我们来讲一下快速排序的多种方法
一.什么是快速排序
快速排序快速排序是对冒泡排序算法的一种改进,同冒泡排序一样,快速排序也属于交换排序,通过元素之间的比较和交换位置来达到排序的目的快速排序原理 快速排序是基于“分治法”原理实现,所谓分治法就是不断的将原数组序列按照一定规律进行拆分,拆分后各自实现排序直到拆分到序列只剩下一个关键字为止。
二.快排的实现--挖坑法
总思路:快速排序的主要思想还是分治,将一串无序的数字不断地分治变为有序的,先选出一个数,然后将这个数的右边放大于它的数左边小于它的数,这就是一轮,这个数选完之后再选下一个数不断地循环就可以排好。
挖坑法思路:
先选出一个数为坑,再把这个数存为钥匙保存后面可以用,然后从数组的最后开始找小于坑位置的数,找到了之后,与可能位置互换,形成新的坑,再从最开始的位置找大于当前坑位置的数,直到begin与end相等,就结束结束之后,再把钥匙放在他们的中间就完成了一次,后面通过函数递归来完成这个循环
void Quick1sort(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;
Quick1sort(a, left, pivot - 1);
Quick1sort(a, pivot+1,right);
}
这里还要引出一个三数取中的思想,结束快速排序若排的是逆序的话O(N),我们要避免逆序,关键在找钥匙上,如果min或max值为key就会出现这种,避免逆序O(N*logN)
int GetMidIndex(int* a, int left, int right)
{
int mid = (left + right) / 2;
if (a[left] < a[mid])
{
if (a[mid] < a[right])
return mid;
else if (a[left] < a[right])
return left;
else
return right;
}
else if (a[left] > a[mid])
{
if (a[mid] > a[right])
return mid;
else if (a[left] < a[right])
return left;
else
return right;
}
}
三.快排的实现--左右指针法
思路:利用三数取中来找钥匙,从开始end找小找到小的时候停下来,从begin开始找大,找到大的时候停下来,把小的和大的互换,然后继续直到相等,最后再把钥匙放到他们的中间就完成了一轮,后面在用函数递归来完成
void Quick2sort(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 = begin;
while (begin < end)
{
//找小,begin < end防止数组越界
while (begin < end && a[end] >= a[key])
{
end--;
}
//找大,begin < end防止数组越界
while (begin < end && a[begin] <= a[key])
{
begin++;
}
Swap(&a[begin], &a[end]);
}
//把钥匙放到中间去
Swap(&a[begin], a[key]);
int pi = begin;
Quick1sort(a, left,pi-1);
Quick1sort(a, pi + 1, right);
}
四.快排的实现--前后指针法
思路:cur找小,每次遇到比key小的值就停下来,prev++,交换prev和cur的位置的值等cur结束,最后交换key和prve
void Quick3sort(int* a, int left, int right)
{
int index = GetMidIndex(a, left, right);
Swap(&a[left], &a[index]);
int key = left;
int prve = left;
int cur = left + 1;
while (cur <= right)
{
if (a[cur] < a[key])
{
prve++;
Swap(&a[prve], &a[cur]);
}
cur++;
}
Swap(&a[key], &a[prve]);
Quick1sort(a, left, prve-1);
Quick1sort(a, prve + 1, right);
}
总结
今天说了快排的3种实现方法,但是多次调用函数递归,可能回栈溢出,所以还要有快排的非递归的实现,下次在来讲解,还有最后几个排序的收尾