Vector::sort排序

template <typename T> void Vector<T>::sort(Rank lo, Rank hi) { //向量區間[lo, hi)排序
   switch (rand() % 5) { //隨機選取排序算法。可根據具體問題的特點靈活選取或擴充
      case 1:  bubbleSort(lo, hi); break; //起泡排序
      case 2:  selectionSort(lo, hi); break; //選擇排序(習題)
      case 3:  mergeSort(lo, hi); break; //歸併排序
      case 4:  heapSort(lo, hi); break; //堆排序(稍後介紹)
      default: quickSort(lo, hi); break; //快速排序(稍後介紹)
   }
   /*DSA*/ //selectionSort(lo, hi);
}

起泡排序 bubbleSort(lo, hi):

template <typename T> //向量的起泡排序
void Vector<T>::bubbleSort(Rank lo, Rank hi) //assert: 0 <= lo < hi <= size
{ while (!bubble(lo, hi--)); } //逐趟做掃描交換,直至全序

template <typename T> bool Vector<T>::bubble(Rank lo, Rank hi) { //一趟掃描交換
   bool sorted = true; //整體有序標誌
   while (++lo < hi) //自左向右,逐一檢查各對相鄰元素
      if (_elem[lo - 1] > _elem[lo]) { //若逆序,則
         sorted = false; //意味着尚未整體有序,並需要
         swap(_elem[lo - 1], _elem[lo]); //通過交換使局部有序
      }
   return sorted; //返回有序標誌
}

選擇排序selectionSort(lo, hi):


template <typename T>
Rank Vector<T>::max(Rank lo, Rank hi) { //在[lo, hi]內找出最大者
   Rank mx = hi;
   while (lo < hi--) //逆向掃描
      if (_elem[hi] > _elem[mx]) //且嚴格比較
         mx = hi; //故能在max有多個時保證後者優先,進而保證selectionSort穩定
   return mx;
}


template <typename T> //向量選擇排序
void Vector<T>::selectionSort(Rank lo, Rank hi) { //assert: 0 < lo <= hi <= size
   /*DSA*/printf("\tSELECTIONsort [%3d, %3d)\n", lo, hi);
   while (lo < --hi)
      swap(_elem[max(lo, hi)], _elem[hi]); //將[hi]與[lo, hi]中的最大者交換
}

歸併排序 mergeSort(lo, hi):

template <typename T> //向量歸併排序
void Vector<T>::mergeSort(Rank lo, Rank hi) { //0 <= lo < hi <= size
   /*DSA*/printf("\tMERGEsort [%3d, %3d)\n", lo ,hi);
   if (hi - lo < 2) return; //單元素區間自然有序,否則...
   int mi = (lo + hi) >> 1; //以中點爲界
   mergeSort(lo, mi); mergeSort(mi, hi); merge(lo, mi, hi); //分別對前、後半段排序,然後歸併
}

template <typename T> //有序向量的歸併
void Vector<T>::merge(Rank lo, Rank mi, Rank hi) { //以mi爲界、各自有序的子向量[lo, mi)和[mi, hi)
   T* A = _elem + lo; //合併後的向量A[0, hi - lo) = _elem[lo, hi)
   int lb = mi - lo; T* B = new T[lb]; //前子向量B[0, lb) = _elem[lo, mi) 
   for (Rank i = 0; i < lb; B[i] = A[i++]); //複製前子向量
   int lc = hi - mi; T* C = _elem + mi; //後子向量C[0, lc) = _elem[mi, hi)
   for (Rank i = 0, j = 0, k = 0; (j < lb) || (k < lc); ) { //將B[j]和C[k]中的小者續至A末尾
      if ( (j < lb) && ( !(k < lc) || (B[j] <= C[k]) ) ) A[i++] = B[j++];
      if ( (k < lc) && ( !(j < lb) || (C[k] <  B[j]) ) ) A[i++] = C[k++];
   }
   delete [] B; //釋放臨時空間B
} //歸併後得到完整的有序向量[lo, hi)

堆排序heapSort(lo, hi):

template <typename T> void Vector<T>::heapSort(Rank lo, Rank hi) { //0 <= lo < hi <= size
   /*DSA*/printf("\tHEAPsort [%3d, %3d)\n", lo, hi);
   PQ_ComplHeap<T> H(_elem, lo, hi); //取出待排序區間並建成完全二叉堆,O(n)
   while (!H.empty()) //反覆迭代,直至堆空
      _elem[--hi] = H.delMax(); //摘除最大元並轉移至原區間:等效於堆頂與末元素對換後下濾
}
template <typename T> T PQ_ComplHeap<T>::delMax() { //刪除非空完全二叉堆中優先級最高的詞條
   T maxElem = _elem[0]; _elem[0] = remove(_size - 1); //摘除堆頂(首詞條),代之以末詞條
   percolateDown(_size, 0); //對新堆頂實施下濾調整
   return maxElem; //返回此前備份的最大詞條
}

快速排序quickSort(lo, hi):

template <typename T> //向量快速排序
void Vector<T>::quickSort(Rank lo, Rank hi) { //0 <= lo < hi <= size
   /*DSA*/printf("\tQUICKsort [%3d, %3d)\n", lo, hi);
   if (hi - lo < 2) return; //單元素區間自然有序,否則...
   Rank mi = partition(lo, hi - 1); //在[lo, hi - 1]內構造軸點
   quickSort(lo, mi); //對前綴遞歸排序
   quickSort(mi + 1, hi); //對後綴遞歸排序
}
template <typename T> //軸點構造算法:通過調整元素位置構造區間[lo, hi]的軸點,並返回其秩
Rank Vector<T>::partition(Rank lo, Rank hi) { //版本B:可優化處理多個關鍵碼雷同的退化情況
   swap(_elem[lo], _elem[lo + rand() % (hi - lo + 1)]); //任選一個元素與首元素交換
   T pivot = _elem[lo]; //以首元素爲候選軸點——經以上交換,等效於隨機選取
   while (lo < hi) { //從向量的兩端交替地向中間掃描
      while (lo < hi)
         if (pivot < _elem[hi]) //在大於pivot的前提下
            hi--; //向左拓展右端子向量
         else //直至遇到不大於pivot者
            { _elem[lo++] = _elem[hi]; break; } //將其歸入左端子向量
      while (lo < hi)
         if (_elem[lo] < pivot) //在小於pivot的前提下
            lo++; //向右拓展左端子向量
         else //直至遇到不小於pivot者
            { _elem[hi--] = _elem[lo]; break; } //將其歸入右端子向量
   } //assert: lo == hi
   _elem[lo] = pivot; //將備份的軸點記錄置於前、後子向量之間
   return lo; //返回軸點的秩
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章