快速排序優化——三數取中法

快速排序優化

前面的三篇文章中,爲大家介紹了快速排序的三種劃分方法。那麼,這裏我們想一想,快速排序是否也會有效率低的情況呢?答案是肯定的,快速排序對於數據是敏感的,如果這個數列是非常無序,雜亂無章的,那麼快速排序的效率是非常高的,可是如果數列有序,往往快速排序的時間複雜度便由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;
}

這種方法對快速排序的效率有很高的提升哦,大家可以記下這種優化方法哦

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章