對單向鍊錶的排序有2種形式,只改變節點的值和只改變鏈結
// 節點
struct listnode
};
歸併排序是最適合單鏈表排序的演算法,因為兩個鍊錶的歸併比較簡單,和陣列的歸併過程思路相同。
需要注意的是:如何找到鍊錶的中點?
通過2個快慢指標,快指標每一步走2個節點,慢指標每一步走1個節點,當快指標到達鍊錶尾部時,慢指標到達鍊錶的中間節點。
class mergesort
pfast = pslow;
pslow = pslow->next; // 分割成2段
pfast->next =
null;
phead = listmergesort(phead);
pslow = listmergesort(pslow);
phead = merge(phead, pslow);
return phead;
};private:
static listnode* merge(listnode* phead1, listnode* phead2)
// 找出合併後的煉表頭
listnode* phead =
null;
if (phead1->val > phead2->val) else
// 將2個鍊錶中值較小的節點依次鏈結到結果鍊錶中
listnode* phead_orgin = phead;
while (phead1 !=
null
&& phead2 !=
null) else
phead = phead->next;
}if (phead1 ==
null)
phead->next = phead2;
else
phead->next = phead1;
return phead_orgin;
};};
只改變鏈結的指向。
將比基元(第乙個節點)小的值,鏈結到乙個左煉表中;比基元大的值,鏈結到乙個右煉表中;
將左鍊錶,基元,右鍊錶鏈結起來。
對一段鍊錶執行劃分過程時,頭節點可能發生改變以及終止節點可能是非空的,因此對一段鍊錶的劃分過程需要給出:
前驅節點(指向頭節點)和終止節點(標誌結束)。
故對傳入劃分函式的一次鍊錶劃分處理是不包括第乙個節點和最後乙個節點的。(雙開區間)
class quicksort
private:
static void listquicksort(listnode* pheadprev, listnode* phead, listnode* ptail) ;
static listnode* partation(listnode* pheadprev, listnode* phead, listnode* ptail) else
}prightprev->next = ptail; // 保證子鍊錶繼續和後面的相連
pleftprev->next = phead; // 基元節點鏈結
phead->next = noder.next;
pheadprev->next = nodel.next; // 煉表頭節點
return phead;
};};
由於鍊錶只能順序索引,故不能使用陣列劃分的方法。
將比基元小的節點的值,依次和基元後的節點的值交換。
如 5->3->6->4->7->2
則5 為基元
3 < 5: swap(3, 3) ,(起始交換位置為基元的下乙個節點,即第2個節點)
6 > 5: continue;
4 < 5: swap(6, 4) (交換位置後移,交換4和第3個節點的值)
7 > 5: continue
2 < 5: swap(4, 2) (交換位置後移,交換2和第4個節點的值)
迴圈結束swap(5, 2) (交換基元值和第4個節點的值)
最後得到:2->3->4->5->6->7
class quicksortvalue
private:
static void quicksort(listnode* phead, listnode* ptail)
static listnode* partation(listnode* phead, listnode* ptail)
}swap(phead, ppivot);
return ppivot;
}static void swap(listnode* pa, listnode* pb)
};
#include
#include
#include
using namespace std;
struct listnode
};void printlist(listnode* phead)
cout << endl;
return;
}class mergesort
pfast = pslow;
pslow = pslow->next; // 分割成2段
pfast->next =
null;
phead = listmergesort(phead);
pslow = listmergesort(pslow);
phead = merge(phead, pslow);
return phead;
};private:
static listnode* merge(listnode* phead1, listnode* phead2)
// 找出合併後的煉表頭
listnode* phead =
null;
if (phead1->val > phead2->val) else
listnode* phead_orgin = phead;
while (phead1 !=
null
&& phead2 !=
null) else
phead = phead->next;
}if (phead1 ==
null)
phead->next = phead2;
else
phead->next = phead1;
return phead_orgin;
};};class quicksort
private:
static void listquicksort(listnode* pheadprev, listnode* phead, listnode* ptail) ;
static listnode* partation(listnode* pheadprev, listnode* phead, listnode* ptail) else
}prightprev->next = ptail; // 保證子鍊錶繼續和後面的相連
pleftprev->next = phead; // 基元節點鏈結
phead->next = noder.next;
pheadprev->next = nodel.next;
return phead;
};};class quicksortvalue
private:
static void quicksort(listnode* phead, listnode* ptail)
static listnode* partation(listnode* phead, listnode* ptail)
}swap(phead, ppivot);
return ppivot;
}static void swap(listnode* pa, listnode* pb)
};int main()
else
}printlist(phead);
phead = mergesort::listmergesort(phead); // merge-sort
// phead = quicksort::listquicksort(phead); // quick-sort-swap-node
//quicksortvalue::quicksort(phead); // quick-sort-swap-value
printlist(phead);
}
鍊錶排序 歸併排序
要求在空間複雜度為o 1 的情況下對鍊錶進行排序,在不考慮時間複雜度的情況下可以考慮氣泡排序,只對鍊錶中的值進行操作,這樣時間複雜度為o n 2 用歸併排序,時間複雜度為o nlogn 以下為歸併排序 實現 public listnode sortlist listnode head private...
排序 歸併排序和快速排序
1,歸併排序的基本思想 1,將兩個或兩個以上的有序序列合併成乙個新的有序序列,比如有序序列 v 0 v m 和 v m 1 v n 1 合併為 v 0 v n 1 這種歸併方法稱為 2 路歸併 1,必須大於 1 個有序序列 2,必須有序 2,歸併的套路 1,將 3 個有序序列歸併為乙個新的有序序列,...
歸併排序和快速排序
歸併排序 先將問題分解為小問題即乙個個子序列,再將子串行按順序合併。class mergesort mergesort a,0 a.length 1 for int t a public static void mergesort int a,int m,int n public static vo...