c 鍊錶歸併排序的迭代版本

2022-05-17 14:59:20 字數 1525 閱讀 6431

之前用js寫了個歸併排序非遞迴版,而這一次,c++封裝鍊錶的時候也遇到了乙個歸併排序的介面。鄧老師實現了遞迴版本的歸併排序,但是遞迴的呼叫函式棧的累積是很佔記憶體空間的。於是乎,那試試在鍊錶結構上實現以下歸併排序吧。但是一旦開始,就遇到難題了,在鍊錶下,我們無法按索引訪問,所以,在迭代過程中,左右序列就無法很好的用o(1)時間就解決。先看看我實現的**吧,初步測試沒問題,如果有什麼問題,希望大神指出,不知為何,用c++寫東西總覺得**有問題,即使程式可以執行。

templatevoid list::mergesort(posi(t) p, int

n)

if (r_p ==trailer)

if (count*2>n)

p =merge(p, i, r_p, r_len);

r_p =p;}}

}

這是主幹程式,大體思路是從一開始的乙個乙個歸併並,到四個四個合併,到最後二路歸併,一開始,因為這個介面是在給定位置的p點已經後面的n-1個元素進行排序,所以我無法直接使用header,於是,用p點的前乙個左右目前頭結點,為什麼這麼做呢,一開始的時候,我是打算用p左右每次迭代的開始,如果你對迭代版歸併熟悉的話,那麼應該很容易理解,每一次合併完所有鍊錶上的分列表,都需要重新從第乙個結點開始,然後繼續合併下乙個迴圈,而因為鍊錶是動態的,很有可能,一次合併後,你的p就不是現在的第乙個結點了,這是h變數的含義,他是乙個頭結點,當然,按照這個介面,尾結點也需要重新定義,然而定義尾結點需要n時間複雜度,所以這裡,我的**是假設n個的下乙個剛好是尾結點。之後是需要合併的右鍊錶的位置,一開始是和左鍊錶重合,然後通過迴圈來達到它的位置,count變數是r_p走的步數,這個步數兩倍是可能超過長度n的,一旦超過,說明了r_p時間上已經到達了末尾,這時候乙個級數的合併已經完成,可以進入下乙個迭代歸併。

而r_len = n%i;的意義是如果越界,那麼需要取得餘數,是正好等於尾巴的長度。

如果不這麼做,那麼merge函式可能鍊錶越界,接下來看看別的部件。

template//

包括p在內的n個元素

posi(t) list::merge(posi(t) left_p, int left_len,posi(t) right_p, int

right_len)

else

}while (right_len-->0

)

return

right_p;

}

template//

重寫介面,以至於可以插入已有節點,同乙個鍊錶的節點

posi(t) list::insertaspre(posi(t) p, posi(t) n)

現在可以分析下這個演算法的時間複雜度了。

最外層的for迴圈應該是logn,這個很好理解,而為了得到左指標的while迴圈必然是n/2,merge函式花費是n,while和merge同級,所以花費是3n/2.

如果算上這個介面尾指標。應該是o(3n/2*logn+n),整體是比陣列的歸併要慢一點,但是還是在同乙個數量級的,這是值得開心的。

鍊錶歸併排序

include include include include include using namespace std typedef int type typedef struct nodetag node node build type a,int n pnode pnext null retu...

鍊錶歸併排序

主要思路 1 如果為null或者只有乙個節點那麼直接返回 2 將鍊錶分成兩部分,分別進行排序,形成兩個有序鍊錶 3 將兩個有序鍊錶合併 void merge sort struct node list void split struct node head,struct node lista,str...

鍊錶 歸併排序

時間複雜度o nlogn 空間複雜度o 1 include include 定義鍊錶 typedef struct listnode linklist linklist head null 建立鍊錶 linklist createlist int arr,int len rear next null...