如何优化合并排序和快速排序
和并排序和快速排序在元素的重复率特别高的时候排序的时间变长。我们可以利用三向切分的办法来避免相同的元素进行交换,以减少交换次数。
具体如下图所示:
总共有3个指针,lt,i,和gt,这个三个指针分别指着队首,队首的下一位,队尾。以队首为参考点,设该数组为a。设中间变量temp.
temp ← a[lt] //队首设为参考变量
if a[i] < temp:
swap(a,lt++,i++)
else if a[i] > temp:
swap(a,i,j--)
else
i++
如果lt的值和i的值随着移动,到最后结束的时候,lt的左边的值一定是比temp小的值,gt右边的值一定是比temp大的值,中间lt 和 gt 之间的值是相等的,最后可以免去交换。递归交换后,后面的递归表达式为
sort(a,begin,lt-1)
sort(a,gt+1,end)
如果中间有重复的元素,最后面的各个指针所指的位置如下:
所以第一个递归的sort中用lt-1的优化会比较快,用lt也可以执行。
代码示例:
#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++; } } cout<<"sort("<<"a,"<<low<<","<<high<<")"<<endl; cout<<"lt="<<lt<<",i="<<i<<",gt="<<gt<<endl; for (int j = 0; j < 13; ++j) { cout << a[j] << " "; } cout<<endl; sort(a,low,lt); sort(a,gt+1,high); } } int main() { int c[] = {2,2,2,2,2,0,0,0,0,0,0,1,5}; int a[] = {1,2,3,4,5,5,5,5,9,10,11,12,13}; int b[] = {13,12,11,10,9,8,7,6,5,4,3,2,1}; //int a[] = {2,0,1,5}; int len = sizeof(b)/sizeof(int); sort(b,0,len-1); //for (int i = 0; i < len; ++i) //cout << a[i] << " "; cout << endl; }