您好,登錄后才能下訂單哦!
這篇文章的內容主要圍繞C++怎么用數組模擬鏈表進行講述,文章內容清晰易懂,條理清晰,非常適合新手學習,值得大家去閱讀。感興趣的朋友可以跟隨小編一起閱讀吧。希望大家通過這篇文章有所收獲!
鏈表是指由一系列儲存在非連續儲存空間 結點組成的儲存結構。每個結點由兩部分組成:一是儲存元素的數據域,一是儲存下一個節點地址的指針域。用數組模擬鏈表可以十分清晰明了地理解這一定義。
在這里,我們簡單地介紹一下單鏈表和雙鏈表兩種鏈表以及用數組模擬實現它們的方式。
單鏈表是指針方向單向的鏈表,即a結點的指針域儲存著b結點的地址,而b結點的指針域內沒有儲存a結點的地址。在訪問時,可以由a到b訪問,而不能由b到a訪問。
如圖可以清晰地看到,各個結點的指向都是單向的。
Q: 那么,如何用數組來實現它呢?
A: 方法如下
在k結點右側插入元素x。先將x賦值給該節點的數據域(e[idx]),然后將k結點的指針域賦值給該結點的指針域,最后將k結點的指針域儲存的地址改為該節點的地址。
void add(int k, int x) { e[idx] = x; ne[idx] = ne[k]; ne[k] = idx++; }
刪除k結點指向的結點。這里所指的刪除,是將k的指向改為該結點的指向。原本為a -> b -> c,改為a -> c,b結點依然存在,只是沒有其他結點指向它,也就無法通過鏈表訪問它,我們認為它就再鏈表上被刪除了。
void remove(int k) { ne[k] = ne[ne[k]]; }
讀取鏈表。讀取鏈表只用注意一點,在用單指針掃描時不是將指針位置右移,而是將指針移動到該結點指向的位置。
for (int i = head; i != -1; i = ne[i]) cout << e[i] << ' '; cout << endl;
主要的操作就是如此,下邊看看完整代碼:
這是較為經典的寫法,我個人認為有些麻煩,head不必單獨拿出來寫一個函數。但是有助于理解。
#include<iostream> using namespace std; const int M = 1e5 + 10; int m, k, x, idx, head; int e[M], ne[M]; void init() { head = -1, idx = 0; } void add_head(int x) { e[idx] = x; ne[idx] = head; head = idx++; } void remove(int k) { ne[k] = ne[ne[k]]; } void add(int k, int x) { e[idx] = x; ne[idx] = ne[k]; ne[k] = idx++; } int main() { init(); cin >> m; while (m--) { char op; cin >> op; if (op == 'H') { cin >> x; add_head(x); } else if (op == 'D') { cin >> k; if (!k) head = ne[head]; remove(k - 1); } else { cin >> k >> x; add(k - 1, x); } } for (int i = head; i != -1; i = ne[i]) cout << e[i] << ' '; cout << endl; return 0; }
這種寫法稍微簡便一些,用a[0]替代head。
#include<iostream> using namespace std; const int M = 1e5 + 10; int m, k, x, idx, head; int e[M], ne[M]; void init() { ne[0] = -1, idx = 1; } void remove(int k) { ne[k] = ne[ne[k]]; } void add(int k, int x) { e[idx] = x; ne[idx] = ne[k]; ne[k] = idx++; } int main() { init(); cin >> m; while (m--) { char op; cin >> op; if (op == 'H') { cin >> x; add(0, x); } else if (op == 'D') { cin >> k; if (!k) head = ne[head]; remove(k); } else { cin >> k >> x; add(k, x); } } for (int i = ne[0]; i != -1; i = ne[i]) cout << e[i] << ' '; cout << endl; return 0; }
雙鏈表顧名思義就是指針方向雙向的鏈表。
可以看到除了頭尾他們的指針都是雙向的。
它的實現方法如下:
創建開始和結束結點。0表示開始,1表示結束,互相指向,在插入時直接往中間插入即可。
void init() { r[0] = 1, l[1] = 0; idx = 2; }
插入結點。雙鏈表插入結點的方法與單鏈表相同,但是操作要稍微復雜一些,這是在k結點右邊插入一結點的代碼。它要顧及結點左右的結點指向,對于兩邊都要操作。面臨在k結點左邊插入一結點時,不必單獨在寫一個函數,而改成在l[k]結點的右邊插入一個結點。
void add(int k, int x) { a[idx] = x; r[idx] = r[k], l[idx] = l[r[k]]; l[r[k]] = idx, r[k] = idx; idx++; }
刪除節點。刪除結點與插入結點同理,我就不多贅述了。
void remove(int k) { r[l[k]] = r[k]; l[r[k]] = l[k]; }
輸出鏈表。可以選擇輸出方向,這里是從左往右輸出。
for (int i = r[0]; i != 1; i = r[i])cout << a[i] << ' '; cout << endl;
以下是完整代碼:
#include<iostream> using namespace std; const int N = 1e5 + 10; int a[N], l[N], r[N]; int idx; int m; void init() { r[0] = 1, l[1] = 0; idx = 2; } void add(int k, int x) { a[idx] = x; r[idx] = r[k], l[idx] = l[r[k]]; l[r[k]] = idx, r[k] = idx; idx++; } void remove(int k) { r[l[k]] = r[k]; l[r[k]] = l[k]; } int main() { init(); cin >> m; while (m--) { int k, x; string op; cin >> op; if (op == "L") { cin >> x; add(0, x); } else if (op == "R") { cin >> x; add(l[1], x); } else if (op == "D") { cin >> k; remove(k + 1); } else if (op == "IL") { cin >> k >> x; add(l[k + 1], x); } else if (op == "IR") { cin >> k >> x; add(k + 1, x); } } for (int i = r[0]; i != 1; i = r[i])cout << a[i] << ' '; cout << endl; return 0; }
感謝你的閱讀,相信你對“C++怎么用數組模擬鏈表”這一問題有一定的了解,快去動手實踐吧,如果想了解更多相關知識點,可以關注億速云網站!小編會繼續為大家帶來更好的文章!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。