您的位置:首页 > 其它

快速排序的一种优化算法(三向切分)

2016-08-09 15:52 127 查看
快速排序:

时间复杂度O(N*logN),最坏情况为O(N^2)

空间复杂度O(1)

但是堆栈深度一般情况为O(logN),最坏情况为O(N)

快速排序实现:

partition划分算法:

int Partition(SeqList R,int i,int j)
{
//调用Partition(R,low,high)时,对R[low..high]做划分,
//并返回基准记录的位置
ReceType pivot=R[i]; //用区间的第1个记录作为基准 '
while(i<j){ //从区间两端交替向中间扫描,直至i=j为止
while(i<j&&R[j].key>=pivot.key) //pivot相当于在位置i上
j--; //从右向左扫描,查找第1个关键字小于pivot.key的记录R[j]
if(i<j) //表示找到的R[j]的关键字<pivot.key
R[i++]=R[j]; //相当于交换R[i]和R[j],交换后i指针加1
while(i<j&&R[i].key<=pivot.key) //pivot相当于在位置j上
i++; //从左向右扫描,查找第1个关键字大于pivot.key的记录R[i]
if(i<j) //表示找到了R[i],使R[i].key>pivot.key
R[j--]=R[i]; //相当于交换R[i]和R[j],交换后j指针减1
} //endwhile
R[i]=pivot; //基准记录已被最后定位
return i;
} //partition


然后,对整个数组进行递归排序:

QUICKSORT(A, p, r)
if p < r
then q ← PARTITION(A, p, r)   //关键
QUICKSORT(A, p, q - 1)
QUICKSORT(A, q + 1, r)


算法导论中提到的快速排序的优化版本:就地重排

PARTITION(A, p, r)
x ← A[r]         //以最后一个元素,A[r]为主元
i ← p - 1
for j ← p to r - 1    //注,j从p指向的是r-1,不是r。
do if A[j] ≤ x
then i ← i + 1
exchange A[i] <-> A[j]
exchange A[i + 1] <-> A[r]
return i + 1


本文重点:三向切分

快速排序什么时候不适用?元素重复率特别高的时候。
如何优化?三向切分。前后各俩指针,总共四个指针。俩额外的指针指向跟待选元素相同的元素,最后全部置换到中间。
三向切分的好处?重复率高的时候,避免相同元素来回交换,节省交换次数。对于包含大量重复元素的数组,这个算法将排序时间从线性对数级降到了线性级别。



代码:

#include <iostream>
using namespace std;
template <typename T>
void sawp(T a[],int first,int second){
T temp;
temp = a[first];
a[first] = a[second];
a[second] = temp;
}
template <typename T>
int sort(T a[],int low,int high){
if(low < high){
int lt = low,i=low+1,gt = high;
int temp = a[low];
while(i <= gt){
if(a[i] < temp){
sawp(a,lt++,i++);
}else if(a[i] > temp){
sawp(a,i,gt--);
}else{
i++;
}
}
sort(a,low,lt-1);
sort(a,gt+1,high);
}
}
int main() {
int a[] = {2,2,2,2,2,0,0,0,0,0,0,1,5};
//int a[] = {2,0,1,5};
int len = sizeof(a)/sizeof(int);
sort(a,0,len-1);
for (int i = 0; i < len; ++i)
cout << a[i] << " ";
cout << endl;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: