原地排序與鍊錶翻轉

2021-09-01 05:10:01 字數 870 閱讀 3611

有這樣乙個問題:

有個長度為 n 的 (key,val) 陣列 a,其中 key 是 int 型別,並且其值在 [0, n) 之間(前閉後開,包括 0 不包括 n),該陣列按 key 是亂序的,但沒有重複 key。

要求:對 a 原地按 key 排序,可以使用常數個臨時變數,不允許使用其它額外空間,時間複雜度必須是o(n)

我曾經寫過另外乙個問題:排列的分解(必須看),與此有點類似:但其實不同。

本質的不同在於:那個問題是對迴圈鍊錶逆時針旋轉1個單位,而該問題是要對迴圈鍊錶順時針旋轉1個單位。逆時針旋轉很容易,因為是 forward copy。但是順時針旋轉需要 backward copy,對陣列(更 general 一點,是 bidirectional iterator)的 backward copy 很容易,但是對單鏈表的 backward copy,就比較困難了。

為了解決 backward copy 的問題,我們可以把這個迴圈鍊錶先進行翻轉,然後再 forward copy,思路有了,**如下:

#include #include #include struct a ; void reorder(a* a, int n) while (k != i); a[i].key = j; int tmp = a[i].val; do while (j != i); a[k].key = k; a[k].val = tmp; } } int main()

void reorder(a* a, int n) while (k != i); a[j].key = j; a[i].val = t; } }

在最壞情況下,這個版本對 val 的拷貝次數是上個版本的3倍,但是因為避免了翻轉鍊錶,也就減少了多乙個迴圈的開銷,這樣的迴圈開銷也許會造成大量的cpu cache 失效…… 各有利弊

鍊錶翻轉和排序

鍊錶的翻轉 鍊錶的節點由資料域與指標域構成,針對鍊錶的翻轉採用三個指標p,q,r,p指向頭結點,q指向p的下乙個節點,r指向q的下乙個節點,p,q,r三個指標遍歷整個鍊錶,將q p next 寫成q next p 因此就將p指向q的指標反轉成q指向p。如下 include include inclu...

鍊錶的翻轉

如何快速的實現鍊錶的翻轉,比如鍊錶a資料為 str1,str2,str3,str4,str5,str6 翻轉後則變為 str6,str5,str4,str3,str2,str1 針對上述問題我能想到的一種辦法就是以壓棧的方式來實現,其實現思路相對較為簡單,通過定義乙個鍊錶資料結構的資料棧,遍歷鍊錶,...

分析鍊錶翻轉

鍊錶翻轉分兩部分,鍊錶整表翻轉和鍊錶部分翻轉。下面討論非遞迴的做法,遞迴的做法以後有空再說。先說鍊錶整表翻轉,核心四句話 next p.next p.next pre pre p p next 顧名思義,pre是p前面的節點,next是p後面的節點。舉個例子,下圖是乙個鍊錶節點翻轉前的狀態 上面的 ...