问题:对于一个有着非常多重复数字的数组
因为有很多重复数字,会导致partition以v划分出来的数组,有一部分会非常大,那么还是会出现分出来的两个子数组可能一大一小,那么快速排序生成的递归树的平衡度就比归并排序差,并且不能保证深度就是logn,很有可能高于logn,最差就演变成O(n^2)
改进:将小于v和大于v的元素分别放在数组的两端
i一直往后遍历数据,直到e>=v
j一直往前遍历数据,直到e<=v
扫描二维码关注公众号,回复:
11126724 查看本文章
将遍历到的数据归并----交换i和j两个所指的元素
继续遍历,知道i和j两个数重合
这样做可以将等于v的元素分散到两个数组之中,使得不会出现两个数组长度相差过大的情况。
#include <iostream>
#include <algorithm>
#include <ctime>
using namespace std;
//双路快排
//对arr[l,r]做partition
int partition(int arr[], int l,int r){
//[l+1,i-1]<v [j,r]>v
int v = arr[l];
int i=l+1;
int j=r;
while(true)
{
if(i<=r && arr[i]<v) i++;//从左到右,找到一个>=v的数字
if(j>l && arr[j]>v) j--; //从右到左,找到一个<=v的数字
if(i>j) break;
swap(arr[i],arr[j]);
i++;
j--;
}
swap(arr[l],arr[i-1]);
return i-1;
}
void quickSort(int arr[], int l,int r){
if(l>=r)
return;
int p=partition(arr,l,r); //为数组的第一个数找到正确的位置并返回
quickSort(arr,l,p-1);//<v部分做快排
quickSort(arr,p+1,r);//>v部分做快排
}
int main()
{
int a[10]= {5,8,7,9,6,3,4,1,2,0};
quickSort(a,0,9);
for(int i=0; i<10; i++)
{
cout<<a[i]<<" ";
}
cout<<endl;
return 0;
}
测试有重复数值: