快速排序優化
前面的三篇文章中,爲大家介紹了快速排序的三種劃分方法。那麼,這裏我們想一想,快速排序是否也會有效率低的情況呢?答案是肯定的,快速排序對於數據是敏感的,如果這個數列是非常無序,雜亂無章的,那麼快速排序的效率是非常高的,可是如果數列有序,往往快速排序的時間複雜度便由O(nlog2n)退化到O(n ^2),即相當於冒泡排序。所以,我們需要優化快速排序,這裏用到的便是三數取中
三數取中
即知道這組無序數列的首和尾後,我們便可以求出這個無需數列的中間位置的數,我們只需要在首,中,尾這三個數據中,選擇一個排在中間的數據作爲基準值,進行快速排序,即可進一步提高快速排序的效率。那麼爲什麼要取中間呢?我們可以假設待排序的數列是一組高度有序的數列,顯然首極大可能是最小值,尾極大可能是最大值,此時如果我們選取一個排在中間的值,哪怕是在最壞的情況下,begin和end只需要走到中間位置,那麼這個中間值的位置也就確定下來,而不需要begin或end指針要把整個數列遍歷一邊,從而大大提高快速排序的效率。這種優化方法很簡單,只需要在選取基準值之前,執行一邊三數取中的函數即可,想必這個函數大家都會寫吧。
int choicmidenum(int* array,int begin,int end)
{
int mid = begin + (end - begin)/2;//獲取中間值的下標
//當begin<mid時,
if(array[begin] < array[mid])
{
//如果mid<end
if(array[mid] < array[end])
return mid;
else
{
if(array[begin] > array[end])//若begin>end
return begin;
else
return end;
}
}
//mid>begin
else
{
//mid>end
if(array[mid] > array[end])
return mid;
else
{
if(array[begin] < array[end])//begin<end
return begin;
else
return end;
}
}
}
我們取霍爾劃分看一下優化後的代碼
int houlepartion(int* array,int begin,int end)
{
//三數取中
int mid = getmid(array,begin,end);
swap(array,begin,mid);//交換mid和begin的值
//選擇基準值
int key = array[begin];//設置基準值
int start = begin;//記錄基準值的位置
while(begin<end)
{
//從後往前找第一個小於key的位置
while(begin<end&&array[end] >= key)
--end;
//從前往後找第一個大於key的位置
while(begin<end&&array[begin] <= key)
++begin;
swap(array,begin,end);
}
swap(array,start,begin);
return begin;
}
這種方法對快速排序的效率有很高的提升哦,大家可以記下這種優化方法哦