日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

第二章 数据结构(一)

發布時間:2025/3/21 编程问答 17 豆豆
生活随笔 收集整理的這篇文章主要介紹了 第二章 数据结构(一) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文章目錄

  • 鏈表和鄰接鏈表
    • 單鏈表
      • 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 std;const int N = 100010;int m; // idx 是最新的數值下標位置 // e[N] 是當前位置的數值是多少 // l[N] 是某個節點左邊的位置 // r[N] 是某個節點右邊的位置 int l[N], r[N], e[N], idx;// 默認 0 是頭的位置, 1 是尾的位置 void init() {r[0] = 1;l[1] = 0;idx = 2; // idx 從2開始 }// 在 k 后面加上節點 x void add(int k, int x) {e[idx] = x;l[idx] = k;r[idx] = r[k];l[r[k]] = idx; // 先左后右邊,保證 k 的有效性r[k] = idx;idx ++ ; }// 刪除第 k 個點 void remove(int k) {r[l[k]] = r[k];l[r[k]] = l[k] }

棧與隊列

棧就是先進后出
隊列就是先進先出

模擬棧

#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

3 4 2 7 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
輸入樣例:

3 aba 5 ababa

輸出樣例:

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;}} }


主串的某一個子串等于模式串的某一個前綴

#include <iostream>using namespace std;const int N = 10010, M = 100010;int n, m; char p[N], s[M]; int ne[N];int main() {cin >> n >> p + 1 >> m >> s + 1;// 求 next 數組// ne[0] ne[1] 自動全局設置為 0, 因此第 3 個字母不匹配才會有回退的選擇for (int i = 2, j = 0; i <= n; i ++ ) {while (j && p[i] != p[j + 1]) j = ne[j];if (p[i] == p[j + 1]) j ++ ;ne[i] = j;}for (int i = 1, j = 0; i <= m; i ++ ) {while (j && s[i] != p[j + 1]) j = ne[j];if (s[i] == p[j + 1]) j ++ ;if (j == n) {// 匹配成功printf("%d ", i - n);j = ne[j];}} }

匹配成功的時候 j = ne[j] 是為了最快的開始下一個匹配

總結

以上是生活随笔為你收集整理的第二章 数据结构(一)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。