List::sort排序

template <typename T> void List<T>::sort(ListNodePosi(T) p, int n) { //列表區間排序
   switch (rand() % 3) { //隨機選取排序算法。可根據具體問題的特點靈活選取或擴充
      case 1:  insertionSort(p, n); break; //插入排序
      case 2:  selectionSort(p, n); break; //選擇排序
      default: mergeSort(p, n); break; //歸併排序
   }
}

先來看看有序列表查找算法:

template <typename T> //在有序列表內節點p(可能是trailer)的n個(真)前驅中,找到不大於e的最後者
ListNodePosi(T) List<T>::search(T const& e, int n, ListNodePosi(T) p) const {
// assert: 0 <= n <= rank(p) < _size
               /*DSA*/printf("searching for "); print(e); printf(" :\n");
   while (0 <= n--) //對於p的最近的n個前驅,從右向左逐個比較
               /*DSA*/{ printf("  <%4d>", p->pred->data);
      if (((p = p->pred)->data) <= e) break; //直至命中、數值越界或範圍越界
               /*DSA*/} printf("\n");
// assert: 至此位置p必符合輸出語義約定——儘管此前最後一次關鍵碼比較可能沒有意義(等效於與-inf比較)
   return p; //返回查找終止的位置
} //失敗時,返回區間左邊界的前驅(可能是header)——調用者可通過valid()判斷成功與否

插入排序

template <typename T> //列表的插入排序算法:對起始於位置p的n個元素排序
void List<T>::insertionSort(ListNodePosi(T) p, int n) { //valid(p) && rank(p) + n <= size
/*DSA*/printf("InsertionSort ...\n");
   for (int r = 0; r < n; r++) { //逐一爲各節點
      insertAfter(search(p->data, r, p), p->data); //查找適當的位置並插入
      p = p->succ; remove(p->pred); //轉向下一節點
   }
}

先來看看列表找最大結點的算法:

template <typename T> static bool lt(T & a, T & b) { return a < b; } //less than
template <typename T> //從起始於位置p的n個元素中選出最大者
ListNodePosi(T) List<T>::selectMax(ListNodePosi(T) p, int n) {
   ListNodePosi(T) max = p; //最大者暫定爲首節點p
   for (ListNodePosi(T) cur = p; 1 < n; n--) //從首節點p出發,將後續節點逐一與max比較
      if (!lt((cur = cur->succ)->data, max->data)) //若當前元素不小於max,則
         max = cur; //更新最大元素位置記錄
   return max; //返回最大節點位置
}

選擇排序:

template <typename T> //列表的選擇排序算法:對起始於位置p的n個元素排序
void List<T>::selectionSort(ListNodePosi(T) p, int n) { //valid(p) && rank(p) + n <= size
   /*DSA*/printf("SelectionSort ...\n");
   ListNodePosi(T) head = p->pred; ListNodePosi(T) tail = p;
   for (int i = 0; i < n; i++) tail = tail->succ; //待排序區間爲(head, tail)
   while (1 < n) { //在至少還剩兩個節點之前,在待排序區間內
      ListNodePosi(T) max = selectMax(head->succ, n); //找出最大者(歧義時後者優先)
      insertBefore(tail, remove(max)); //將其移至無序區間末尾(作爲有序區間新的首元素)
      tail = tail->pred; n--;
   }
}

List歸併排序:

template <typename T> //有序列表的歸併:當前列表中自p起的n個元素,與列表L中自q起的m個元素歸併
void List<T>::merge(ListNodePosi(T)& p, int n, List<T>& L, ListNodePosi(T) q, int m) {
// assert:  this.valid(p) && rank(p) + n <= size && this.sorted(p, n)
//          L.valid(q) && rank(q) + m <= L._size && L.sorted(q, m)
// 注意:在歸併排序之類的場合,有可能 this == L && rank(p) + n = rank(q)
   ListNodePosi(T) pp = p->pred; //藉助前驅(可能是header),以便返回前 ...
   while (0 < m) //在q尚未移出區間之前
      if ((0 < n) && (p->data <= q->data)) //若p仍在區間內且v(p) <= v(q),則
         { if (q == (p = p->succ)) break; n--; } //將p替換爲其直接後繼(等效於將p歸入合併的列表)
      else //若p已超出右界或v(q) < v(p),則
         { insertBefore(p, L.remove((q = q->succ)->pred)); m--; } //將q轉移至p之前
   p = pp->succ; //確定歸併後區間的(新)起點
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章