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; //確定歸併後區間的(新)起點
}