第二章 数据结构(一)
文章目錄
- 鏈表和鄰接鏈表
- 單鏈表
- 826 單鏈表
- 雙鏈表
- 827 雙鏈表
- 棧與隊列
- 830 單調棧
- kmp
- 831 kmp字符串
鏈表和鄰接鏈表
數據模擬的速度會快很多,每次 new 一個新的節點,速度非常慢。
單鏈表
其中的領接表用的最多,主要是用來存儲圖和數。
每個點都存儲了 value 和 next
e[N], ne[N] 當前的數值和next指針空節點的位置是-1
826 單鏈表
實現一個單鏈表,鏈表初始為空,支持三種操作:
向鏈表頭插入一個數;
刪除第 k 個插入的數后面的數;
在第 k 個插入的數后插入一個數。
現在要對該鏈表進行 M 次操作,進行完所有操作后,從頭到尾輸出整個鏈表。
注意:題目中第 k 個插入的數并不是指當前鏈表的第 k 個數。例如操作過程中一共插入了 n 個數,則按照插入的時間順序,這 n 個數依次為:第 1 個插入的數,第 2 個插入的數,…第 n 個插入的數。
輸入格式
第一行包含整數 M,表示操作次數。
接下來 M 行,每行包含一個操作命令,操作命令可能為以下幾種:
H x,表示向鏈表頭插入一個數 x。
D k,表示刪除第 k 個插入的數后面的數(當 k 為 0 時,表示刪除頭結點)。
I k x,表示在第 k 個插入的數后面插入一個數 x(此操作中 k 均大于 0)。
輸出格式
共一行,將整個鏈表從頭到尾輸出。
數據范圍
1≤M≤100000
所有操作保證合法。
輸入樣例:
10 H 9 I 1 1 D 1 D 0 H 6 I 3 6 I 4 5 I 4 5 I 3 4 D 6輸出樣例:
6 4 6 5 #include <iostream>using namespace std;const int N = 100010;// head 是頭結點的下標 // e[i] 是節點 i 的值 // ne[i] 表示節點 i 的 next 指針是多少 // idx 表示最新用到了哪個位置,一直只會增加 int head, e[N], ne[N], idx;void init() {idx = 0;head = -1; }// 在頭部加入節點 void add_to_head(int x) {e[idx] = x;ne[idx] = head;head = idx;idx ++ ; }// x 這個點插入到下標為 k 的后面 void add(int k, int x) {e[idx] = x;ne[idx] = ne[k];ne[k] = idx;idx ++ ; }// 刪除下標為 k 的后面的點 void remove(int k) {ne[k] = ne[ne[k]]; // 刪除了就不管了,空間不用釋放 }int main() {int m;cin >> m;init();while (m -- ) {int k, x;char op;cin >> op;if (op == 'H') {cin >> x;add_to_head(x);} else if (op == 'D') {cin >> k;if (!k) {head = ne[head]; // 一定要做特判} else {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; }雙鏈表
核心
0 作為 head, 1 作為 tail
int l[N], r[N];
827 雙鏈表
實現一個雙鏈表,雙鏈表初始為空,支持 5 種操作:
在最左側插入一個數;
在最右側插入一個數;
將第 k 個插入的數刪除;
在第 k 個插入的數左側插入一個數;
在第 k 個插入的數右側插入一個數
現在要對該鏈表進行 M 次操作,進行完所有操作后,從左到右輸出整個鏈表。
注意:題目中第 k 個插入的數并不是指當前鏈表的第 k 個數。例如操作過程中一共插入了 n 個數,則按照插入的時間順序,這 n 個數依次為:第 1 個插入的數,第 2 個插入的數,…第 n 個插入的數。
輸入格式
第一行包含整數 M,表示操作次數。
接下來 M 行,每行包含一個操作命令,操作命令可能為以下幾種:
L x,表示在鏈表的最左端插入數 x。
R x,表示在鏈表的最右端插入數 x。
D k,表示將第 k 個插入的數刪除。
IL k x,表示在第 k 個插入的數左側插入一個數。
IR k x,表示在第 k 個插入的數右側插入一個數。
輸出格式
共一行,將整個鏈表從左到右輸出。
數據范圍
1≤M≤100000
所有操作保證合法。
輸入樣例:
10 R 7 D 1 L 3 IL 2 10 D 3 IL 2 7 L 8 R 9 IL 4 7 IR 2 2輸出樣例:
8 7 7 3 2 9初始狀態
棧與隊列
棧就是先進后出
隊列就是先進先出
模擬棧
#include <iostream>using namespace N = 100010;// stk[N] 棧 // tt 棧頂, 已經有數據 int stk[N], tt;// 插入 stk[++ t] = x; // 彈出 tt -- ;// 判斷棧是否為空 if (tt > 0) not empty else empty// 棧頂 stk[tt];隊列
// **************** 隊列// q[N] 隊列 // hh 隊頭 // tt 隊尾,tt 位置上是原有的數據 // 隊尾插入,隊頭彈出 int q[N], hh, tt = -1;// 插入 q[++ tt] = x;// 彈出 hh ++ ;// 判斷空 if (hh << tt) not empty else empty// 取出隊頭元素 q[hh]單調棧
找到每個數左邊滿足某個條件的最近的數
830 單調棧
給定一個長度為 N 的整數數列,輸出每個數左邊第一個比它小的數,如果不存在則輸出 ?1。
輸入格式
第一行包含整數 N,表示數列長度。
第二行包含 N 個整數,表示整數數列。
輸出格式
共一行,包含 N 個整數,其中第 i 個數表示第 i 個數的左邊第一個比它小的數,如果不存在則輸出 ?1。
數據范圍
1≤N≤105
1≤數列中元素≤109
輸入樣例:
5
輸出樣例:
-1 3 -1 2 2 #include <iostream>using namespace std;const int N = 100010;int n; int stk[N], hh, tt;int main() {cin >> n;while (n -- ) {int x;cin >> x;while (tt && stk[tt] >= x) tt -- ;if (tt) cout << stk[tt] <<' ';else cout << "-1 ";stk[++ tt] = x;}return 0; }這里的 tt 初始數值不能是 -1
kmp
831 kmp字符串
給定一個模式串 S,以及一個模板串 P,所有字符串中只包含大小寫英文字母以及阿拉伯數字。
模板串 P 在模式串 S 中多次作為子串出現。
求出模板串 P 在模式串 S 中所有出現的位置的起始下標。
輸入格式
第一行輸入整數 N,表示字符串 P 的長度。
第二行輸入字符串 P。
第三行輸入整數 M,表示字符串 S 的長度。
第四行輸入字符串 S。
輸出格式
共一行,輸出所有出現位置的起始下標(下標從 0 開始計數),整數之間用空格隔開。
數據范圍
1≤N≤105
1≤M≤106
輸入樣例:
輸出樣例:
0 2 S[N], p[M]for (int i = 1; i <= n; i ++ ) {bool flag = true;for (int j = 1; j <= m; j ++ ) {if (s[i] != p[j]) {flag = false;break;}} }
主串的某一個子串等于模式串的某一個前綴
匹配成功的時候 j = ne[j] 是為了最快的開始下一個匹配
總結
以上是生活随笔為你收集整理的第二章 数据结构(一)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python爬虫高考成绩
- 下一篇: 第二章 数据结构(二)