一、快排的三种方法
1、最早的方法
(1)思路:给出一个key值(默认为数组第一个位置上的数),从数组开头开始找大于key的数,数组末端开始找小于key的数,找到之后两位置上的数进行交换
(2)画图理解:
(3)代码:
int Partition2(int*arr, int left, int right)
{
itn start=left;
int key = arr[left];
while (left < right)
{
while (left < right&&arr[left] <= key)
left++;
while (left<right&&arr[right]>=key)
right--;
if (left < right)
swap(arr[left], arr[right]);
}
//特例如{5,6},key为5,不判断就交换,数组就无序了
if (arr[left]<key)//注意点,要记得判断一下
swap(arr[left], arr[start]);
return left;
}
2、挖坑法
(1)思路:给出一个key值(默认为数组第一个位置上的数),在该位置上挖一个坑。这个位置上就少了一个数;然后从数组右边开始遍历,寻找一个值比key小的数,挖出这个数来,对上一个坑进行填坑。然后从数组前面遍历,寻找一个比key大的数,填上面的坑。直到左边和右边相遇,最后把key补在坑上
(2)画图理解:
(3)代码:
int Partition(int*arr, int start, int end)
{
int key = arr[start];
while (start < end)
{
while (start < end&&key <= arr[end])//注意要写上=
end--;
if (start < end)
arr[start]= arr[end];
while (start < end&&key >= arr[start])
start++;
if (start < end)
arr[end] = arr[start];
}
arr[start] = key;
return start;
}
3、前后指针法
(1)思路:设置前后指针,前指针依次++,后指针只有在前指针指向的数小于key的时候++。当后指针++,并且其++后的值不等于前指针,那么俩位置上的数交换。当快指针到到最后位置,把key的值交换到前指针的后一个位置上。
(2)画图理解:
(3)代码:
int Partion(int*arr,int start, int end)
{
int key = arr[end];
int ps = start - 1;
int pf = start;
while (pf < end)
{
if (arr[pf] < key&&(++ps != pf))
swap(arr[pf], arr[ps]);
++pf;
}
swap(arr[end], arr[++ps]);
return ps;
}
二、快排两种实现方式
1、递归
void Qsort(int*arr, int start, int end)
{
if (start < end)
{
int index = Partition3(arr, start, end);
Qsort(arr, start, index - 1);
Qsort(arr, index + 1, end);
}
}
2、循环
void Qsort1(int*arr, int start, int end)
{
stack<int>coll;
coll.push(end);
coll.push(start);
while (!coll.empty())
{
int left = coll.top();
coll.pop();
int right = coll.top();
coll.pop();
int index = Partition3(arr, left, right);
if (left < index - 1)
{
coll.push(index - 1);
coll.push(left);
}
if (index + 1 < right)
{
coll.push(right);
coll.push(index + 1);
}
}
}
三、快排的时间复杂度
快排最优的情景:就是如上图所示key的值取到中间值,递归次数最少
快排最差的情景:就是key值取到了边界值(最大或最小),递归的次数为n,时间复杂度为O(N)
四、对快排的优化
1、三数取中法:对于key取值位置的优化,有可能key取到边界值,造成快排的效率变低。具体实现是,判断前中后三个点的值,取中间的值作为key。
int midpos(int*arr, int left, int right)
{
int mid = left + (right - left) / 2;
if (arr[left] > arr[right])
{
if (arr[mid] > arr[left])
return left;
else if (arr[mid] < arr[right])
return right;
else
return mid;
}
else
{
if (arr[mid]>arr[right])
return right;
else if (arr[mid] < arr[left])
return left;
else
return mid;
}
return -1;
}
2、如果对一段长度小于13的数据进行排序,可用直接插入法替代快排,可以有效减少递归深度。
本文详细介绍了快速排序的三种方法:最早的方法、挖坑法和前后指针法,并提供了对应的代码实现。此外,还讨论了快排的两种实现方式:递归和循环,并分析了快排的时间复杂度。最后,提出了两种优化方案:三数取中法和直接插入法。
6290

被折叠的 条评论
为什么被折叠?



