之前寫了陣列實現單鏈表,提到了陣列實現鍊錶比指標實現最大的優點就是快,可以隨機訪問,而且不用new節點。
在圖論的題目裡用到鄰接表,往往都是用陣列實現。
陣列實現雙鏈錶比單鏈表就多了一些對於左指標的操作。
為了實現的方便,不像在單鏈表實現裡用乙個額外的變數head
去記錄鍊錶的頭節點。
而是直接用兩個哨兵節點固定為雙鏈表的頭節點和尾節點。
我們可以固定頭節點為0,尾節點為1.
也就是說,0的right指標
指向鍊錶的第乙個節點,1的left指標
指向鍊錶的第乙個節點。
這樣,0和1就被固定為頭節點和尾節點了。我們如果要插入節點,初始下標就得從2開始。
模擬單鏈表的陣列實現,要實現雙鏈表,就得開三個陣列val
,l
,r
。
val[i]表示下標為i的節點的值,l[i]表示下標為i的節點的前驅節點,r[i]表示下標為i的節點的後繼結點。
另外還需要有乙個變數idx
記錄當前插入的節點的下標。由於0和1已經被占用了,所以idx從2開始。
雙鏈表具體的操作,可以根據題目來確定。來看一道題:
原題鏈結在這
這道題的題意是要我們實現乙個雙鏈表,雙鏈表支援五個操作:
(1)在鍊錶的第乙個節點之前(最左側)插入乙個數
(2)在鍊錶的最後乙個節點之後(最右側)插入乙個數
(3)刪除第k個插入的數
(4)在第k個插入的數左側插入乙個數
(5)在第k個插入的數右側插入乙個數
實現操作之前,先初始化雙鏈表。
void init()
這三行**的作用是初始化乙個空的雙鏈表,頭節點0的right指標指向尾節點1,尾節點1的left指標指向頭節點0,要插入的數的下標初始化為2(因為0,1已經被占用了)。
再看其他操作,看起來要實現很多操作,實際上這五個操作可以分為兩類:插入和刪除。
五個操作中有四個是插入操作,所以可以在乙個函式裡實現。
比如要在下標為k的點右側插入乙個數x。
首先需要建立乙個含有值x的節點:val[idx] = x;
然後這個點的右指標要指向下標為k的點的右指標指向的節點,這個點的左指標要指向下標為k的點:
r[idx] = r[k]; //r[k]表示下標為k的節點的後繼結點。 注意:下標為k的節點,不是第k個插入的節點,而是第k - 1個插入的節點,因為idx是從2開始的,所以第乙個插入的節點下標為2...第k個插入的節點的下標為k + 1 !
l[idx] = k; //新插入的節點的左指標指向下標k
然後還要修改原來的兩個節點,下標為k的節點的右指標指向這個新插入的節點,還有原來是下標為k的節點的下乙個節點的左指標要指向新插入的節點。
l[r[k]] = idx;
r[k] = idx;
上面兩行**的順序不能反,否則如果提前修改了r[k],那麼未插入新節點前下標為k的節點的下乙個節點就找不到了,更沒辦法修改它的左指標。
修改了指標之後,下標idx要增加,以便之後插入新的節點。
++idx;
這樣,我們就得到了在下標為k的節點之後插入x的函式:
void insert(int k, int x)
這是在下標為k的節點的右邊插入x,題目還要求在左邊插入。
實際上在左邊插入,可以直接呼叫insert(l[k], x)
也就是在下標為k的節點的前驅節點的右邊插入。
這樣就不用再寫乙個函式了。
這樣還剩下兩個插入操作,在最左側插入,和在最右側插入。
實際上,由於固定了兩個哨兵節點0和1.
0的右指標指向第乙個節點,所以要在最左側插入,可以直接呼叫insert(0, x)。
1的左指標指向最後乙個節點,所以要在最右側插入,可以直接呼叫insert(l[1], x)。
所以實際上乙個insert函式就解決了題目要求的四個插入操作。
這樣就只剩下乙個刪除操作了。
要刪除下標為k的節點,只需要讓它的前驅節點的右指標指向它的後繼結點,它的後繼結點的左指標指向它的前驅節點。
void delete(int k)
下面是完整**:
#includeusing namespace std;
const int n = 1e5 + 5;
int val[n], l[n], r[n], idx;
void init()
void insert(int k, int x)
void delete(int k)
int main() else if(op == "r") else if(op == "d") else if(op == "il") else if(op == "ir")
}for(int i = r[0]; i != 1; i = r[i])
cout << endl;
}
雙鏈表實現
一 實驗目的 鞏固線性表的資料結構的儲存方法和相關操作,學會針對具體應用,使用線性表的相關知識來解決具體問題。二 實驗內容 建立乙個由n個學生成績的順序表,n的大小由自己確定,每乙個學生的成績資訊由自己確定,實現資料的對錶進行插入 刪除 查詢等操作。分別輸出結果。三 源 includeconst i...
雙鏈表實現
以前寫的不帶頭的單鏈表實現,當時也啥也沒學,好多東西不知道,加上一心想壓縮 減少情況,所以寫得不太好。請教了老師,首先是命名問題和 緊湊性等的改進。還有可讀性方面的改進,多寫了一些注釋。並且因為帶頭的比較好寫,好操作,所以標準寫法也不是很長,繁瑣。下面貼 include include includ...
陣列模擬雙鏈表
雙鏈表 實現乙個雙鏈表,雙鏈表初始為空,支援5種操作 1 在最左側插入乙個數 2 在最右側插入乙個數 3 將第k個插入的數刪除 4 在第k個插入的數左側插入乙個數 5 在第k個插入的數右側插入乙個數 雙鏈表,需要開三個陣列。e存放該節點的數值,l 陣列存放該節點左邊的節點,r陣列存放該節點右邊的節點...