算法學習系列(十):用數組模擬鏈表、雙鏈表、棧、隊列、單調棧、單調隊列

目錄

  • 引言
  • 一、數組模擬鏈表
    • 1.模板
    • 2.例題
    • 3.測試
  • 二、數組模擬雙鏈表
    • 1.模板
    • 2.例題
    • 3.測試
  • 三、數組模擬棧
    • 1.模板
    • 2.例題
    • 3.測試
  • 四、數組模擬隊列
    • 1.模板
    • 2.例題
    • 3.測試
  • 五、數組模擬單調棧
    • 1.例題+模板
    • 2.測試
  • 六、數組模擬單調隊列
    • 1.例題+模板
    • 2.測試

引言

首先說一下為什么要拿數組來模擬,最主要的原因是為了快,因為如果用stl庫里的容器的話,在算法競賽中,一般是不會給你開O2優化或者臭氧優化的,然后所以在一些時間卡的非常緊的情況下,還是推薦用數組來模擬會比較好,然后開始吧。

一、數組模擬鏈表

1.模板

const int N = 100010;//head為頭節點所在的下標,e[i]代表下標為i的值,ne[i]代表下標為i的下一個下標,idx代表當前可用的下標
int head, e[N], ne[N], idx;void init()
{head = -1;idx = 0;
}void add_to_head(int x)
{e[idx] = x;ne[idx] = head, head = idx++;
}void add(int k, int x)  //插到下標為k的后面
{e[idx] = x;ne[idx] = ne[k], ne[k] = idx++;
}void remove(int k)  //刪掉下標為k的后一個元素
{ne[k] = ne[ne[k]];
}

2.例題

實現一個單鏈表,鏈表初始為空,支持三種操作:向鏈表頭插入一個數;
刪除第 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;int m;
int head, e[N], ne[N], idx;void init()
{head = -1;idx = 0;
}void add_to_head(int x)
{e[idx] = x;ne[idx] = head, head = idx++;
}void add(int k, int x)  //插到下標為k的后面
{e[idx] = x;ne[idx] = ne[k], ne[k] = idx++;
}void remove(int k)  //刪掉下標為k的后一個元素
{ne[k] = ne[ne[k]];
}int main()
{init();cin >> m;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;
}

3.測試

可以看出是正確的
在這里插入圖片描述

二、數組模擬雙鏈表

1.模板

const int N = 100010;int e[N], l[N], r[N], idx;void init()  //0代表左端點 1代表右端點
{r[0] = 1, l[1] = 0, idx = 2;  
}void insert(int k, int x)  //在結點k的右邊插入一個數x
{e[idx] = x;r[idx] = r[k], l[idx] = k;l[r[k]] = idx, r[k] = idx++;
}void remove(int k)  //刪除結點k
{r[l[k]] = r[k];l[r[k]] = l[k];
}

2.例題

實現一個雙鏈表,雙鏈表初始為空,支持 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 e[N], l[N], r[N], idx;void init()  //0代表左端點 1代表右端點
{r[0] = 1, l[1] = 0, idx = 2;  
}void insert(int k, int x)  //在結點k的右邊插入一個數x
{e[idx] = x;r[idx] = r[k], l[idx] = k;l[r[k]] = idx, r[k] = idx++;
}void remove(int k)  //刪除結點k
{r[l[k]] = r[k];l[r[k]] = l[k];
}int main()
{init();int m;cin >> m;while(m--){int k, x;string op;cin >> op;if(op == "L"){cin >> x;insert(0,x);}else if(op == "R"){cin >> x;insert(l[1],x);}else if(op == "D"){cin >> k;remove(k+1);  //因為k是從2開始的}else if(op == "IL"){cin >> k >> x;insert(l[k+1],x);}else{cin >> k >> x;insert(k+1,x);}}for(int i = r[0]; i != 1; i = r[i]) cout << e[i] << " ";return 0;
}

3.測試

可以看出是正確的
在這里插入圖片描述

三、數組模擬棧

1.模板

const int N = 100010;int stk[N], tt;void push(int x)
{stk[++tt] = x;
}bool empty()
{return tt > 0 ? false : true;
}void pop()
{tt--;
}int top()
{return stk[tt]; 
}

2.例題

實現一個棧,棧初始為空,支持四種操作:push x – 向棧頂插入一個數 x;
pop – 從棧頂彈出一個數;
empty – 判斷棧是否為空;
query – 查詢棧頂元素。現在要對棧進行 M 個操作,其中的每個操作 3 和操作 4 都要輸出相應的結果。輸入格式
第一行包含整數 M,表示操作次數。接下來 M 行,每行包含一個操作命令,操作命令為 push x,pop,empty,query 中的一種。輸出格式
對于每個 empty 和 query 操作都要輸出一個查詢結果,每個結果占一行。其中,empty 操作的查詢結果為 YES 或 NO,query 操作的查詢結果為一個整數,表示棧頂元素的值。數據范圍
1≤M≤100000,1≤x≤109所有操作保證合法。輸入樣例:
10
push 5
query
push 6
pop
query
pop
empty
push 4
query
empty輸出樣例:
5
5
YES
4
NO
#include <iostream>using namespace std;const int N = 100010;int stk[N], tt;void push(int x)
{stk[++tt] = x;
}bool empty()
{return tt > 0 ? false : true;
}void pop()
{tt--;
}int top()
{return stk[tt]; 
}int main()
{int m;cin >> m;while(m--){string op;int x;cin >> op;if(op == "push"){cin >> x;push(x);}else if(op == "pop"){pop();}else if(op == "empty"){if(empty()) cout << "YES" << endl;else cout << "NO" << endl;}else{cout << top() << endl;}}return 0;
}

3.測試

在這里插入圖片描述

四、數組模擬隊列

1.模板

const int N = 100010;int q[N], hh, tt = -1;void push(int x)
{q[++tt] = x;
}int front()
{return q[hh]; 
}void pop()
{hh++;
}bool empty()
{return hh <= tt ? false : true;
}

2.例題

實現一個隊列,隊列初始為空,支持四種操作:push x – 向隊尾插入一個數 x;
pop – 從隊頭彈出一個數;
empty – 判斷隊列是否為空;
query – 查詢隊頭元素。現在要對隊列進行 M 個操作,其中的每個操作 3 和操作 4 都要輸出相應的結果。輸入格式
第一行包含整數 M,表示操作次數。接下來 M 行,每行包含一個操作命令,操作命令為 push x,pop,empty,query 中的一種。輸出格式
對于每個 empty 和 query 操作都要輸出一個查詢結果,每個結果占一行。其中,empty 操作的查詢結果為 YES 或 NO,query 操作的查詢結果為一個整數,表示隊頭元素的值。數據范圍
1≤M≤100000,1≤x≤109,所有操作保證合法。輸入樣例:
10
push 6
empty
query
pop
empty
push 3
push 4
pop
query
push 6輸出樣例:
NO
6
YES
4
#include <iostream>using namespace std;const int N = 100010;int q[N], hh, tt = -1;void push(int x)
{q[++tt] = x;
}int front()
{return q[hh]; 
}void pop()
{hh++;
}bool empty()
{return hh <= tt ? false : true;
}int main()
{int m;cin >> m;while(m--){int x;string op;cin >> op;if(op == "push"){cin >> x;push(x);}else if(op == "pop"){pop();}else if(op == "empty"){if(empty()) cout << "YES" << endl;else cout << "NO" << endl;}else {cout << front() << endl;}}return 0;
}

3.測試

在這里插入圖片描述

五、數組模擬單調棧

單調棧就是用來快速找當前下標左邊第一個小于該數的數

1.例題+模板

給定一個長度為 N 的整數數列,輸出每個數左邊第一個比它小的數,如果不存在則輸出 ?1。輸入格式
第一行包含整數 N,表示數列長度。第二行包含 N 個整數,表示整數數列。輸出格式
共一行,包含 N 個整數,其中第 i 個數表示第 i 個數的左邊第一個比它小的數,如果不存在則輸出 ?1。數據范圍
1≤N≤1051≤數列中元素≤109輸入樣例:
5
3 4 2 7 5輸出樣例:
-1 3 -1 2 2
#include <iostream>using namespace std;const int N = 100010;int stk[N], tt;int main()
{int n;cin >> n;while(n--){int x;cin >> x;while(tt && stk[tt] >= x) tt--;if(tt) printf("%d ", stk[tt]);else printf("-1 ");stk[++tt] = x;}return 0;
}

2.測試

在這里插入圖片描述

六、數組模擬單調隊列

1.例題+模板

給定一個大小為 n≤106的數組。有一個大小為 k 的滑動窗口,它從數組的最左邊移動到最右邊。你只能在窗口中看到 k 個數字。每次滑動窗口向右移動一個位置。以下是一個例子:
該數組為 [1 3 -1 -3 5 3 6 7],k 為 3。窗口位置	       最小值	最大值
[1 3 -1] -3 5 3 6 7	    -1	      3
1 [3 -1 -3] 5 3 6 7	    -3	      3
1 3 [-1 -3 5] 3 6 7		-3	      5
1 3 -1 [-3 5 3] 6 7		-3	      5
1 3 -1 -3 [5 3 6] 7	     3	      6
1 3 -1 -3 5 [3 6 7]	     3	      7
你的任務是確定滑動窗口位于每個位置時,窗口中的最大值和最小值。輸入格式
輸入包含兩行。第一行包含兩個整數 n 和 k,分別代表數組長度和滑動窗口的長度。第二行有 n 個整數,代表數組的具體數值。同行數據之間用空格隔開。輸出格式
輸出包含兩個。第一行輸出,從左至右,每個位置滑動窗口中的最小值。第二行輸出,從左至右,每個位置滑動窗口中的最大值。輸入樣例:
8 3
1 3 -1 -3 5 3 6 7輸出樣例:
-1 -3 -3 -3 3 3
3 3 5 5 6 7
#include <cstdio>
#include <iostream>using namespace std;const int N = 1000010;int a[N], q[N];
int n, k, hh, tt = -1;int main()
{scanf("%d%d", &n, &k);for(int i = 0; i < n; ++i) scanf("%d", &a[i]);for(int i = 0; i < n; ++i){//但因為這個每次只會進一個,所以用if就可以了if(hh <= tt && i - k + 1 > q[hh]) hh++;  //因為如果上一次滿了,然后上一次再入進去就會導致隊頭滑出窗口while(hh <= tt && a[q[tt]] >= a[i]) tt--;q[++tt] = i;if(i >= k - 1) printf("%d ", a[q[hh]]);}puts("");hh = 0, tt = -1;for(int i = 0; i < n; ++i){if(hh <= tt && i - k + 1 > q[hh]) hh++;  //因為如果上一次滿了,然后上一次再入進去就會導致隊頭滑出窗口while(hh <= tt && a[q[tt]] <= a[i]) tt--;q[++tt] = i;if(i >= k - 1) printf("%d ", a[q[hh]]);}puts("");return 0;
}

2.測試

在這里插入圖片描述

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/455547.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/455547.shtml
英文地址,請注明出處:http://en.pswp.cn/news/455547.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

為什么你的路由器穿墻能力差?看完秒懂

1、信號弱賴我咯? 不管你承認與否&#xff0c;只要有墻家中就會存有信號死角&#xff0c;不要小看一墻之隔。如何讓路由器的信號增強? 網上一搜旁門左道真不少&#xff0c;什么調整天線尋找合理角度&#xff0c;又或是用易拉罐DIY一個信號放大器&#xff0c;然鵝并非簡單的將…

fish工具_Python程序員使用哪些開發工具

Python程序員使用哪些開發工具?很多Python學習者想必都會有如下感悟&#xff1a;最開始學習Python的時候&#xff0c;因為沒有去探索好用的工具&#xff0c;吃了很多苦頭。后來工作中深刻體會到&#xff0c;合理使用開發的工具的便利和高效。今天&#xff0c;北京學佳澳小編總…

[shiro學習筆記]第二節 shiro與web融合實現一個簡單的授權認證

本文地址&#xff1a;http://blog.csdn.net/sushengmiyan/article/details/39933993shiro官網: http://shiro.apache.org/shiro中文手冊&#xff1a;http://wenku.baidu.com/link?urlZnnwOHFP20LTyX5ILKpd_P94hICe9Ga154KLj_3cCDXpJWhw5Evxt7sfr0B5QSZYXOKqG_FtHeD-RwQvI5ozyT…

Web安全之Cookie劫持

1.Cookie是什么? 2.竊取的原理是什么? 3.系統如何防Cookie劫持呢? 看完這三個回答&#xff0c;你就明白哪位傳奇大俠是如何成功的!!! Cookie: HTTP天然是無狀態的協議&#xff0c;為了維持和跟蹤用戶的狀態&#xff0c;引入了Cookie和Session。Cookie包含了瀏覽器客戶端的用…

python中關于深拷貝和淺拷貝的詳解

python中關于深拷貝和淺拷貝的詳解 概述 在python的語法中,有兩種變量的拷貝方式 一種是深拷貝,一種是淺拷貝 我們先說深拷貝 語法 這里需要通過導入系統的copy模塊中的deepcopy才可以 import copy 新的對象 copy.deepcopy(被拷貝對象) 解釋 深拷貝是將操作對象整體復制…

運動估計簡介

運動估計( Motion Estimation) 維基百科鏈接&#xff1a;http://en.wikipedia.org/wiki/Motion_estimation運動估計的應用有很多&#xff0c;最初的應用的領域是視頻的編碼。運動估計算法一般分為: 像素遞歸法pel-recursive algorithm (PRA)和塊匹配法 block-matching algorith…

tutte定理證明hall定理_深入淺出|中心極限定理(Central Limit Theorem)及證明

在介紹統計學中最重要的定理之一-中心極限定理-之前&#xff0c;我們先來想一個問題&#xff1a;統計學的目的是什么&#xff1f;根據<Mathematical statistics with application 7th Edition>書中所寫的&#xff1a;統計學的目的是基于從總體中的樣本所獲得的信息&#…

讓數據中心變得更加友好

通常來說&#xff0c;數據中心是一個安全防護十分嚴密的地方&#xff0c;其安全功能的設計旨在阻止不速之客的訪問。但專家認為數據中心可以變得更加友好&#xff0c;因為數據中心需要在人類社會中發揮更大的作用。 數據中心的整體概念是一種可以通過云計算或其他方法進行遠程訪…

traceroute/tracert--獲取網絡路由路徑

traceroute 是用來檢測發出數據包的主機到目標主機之間所經過的網關數量的工具。traceroute 的原理是試圖以最小的TTL發出探測包來跟蹤數據包到達目標主機所經過的網關&#xff0c;然后監聽一個來自網關ICMP的應答。發送數據包的大小默認為 38個字節。 通過traceroute我們可以知…

使用Cygwin實現vlc 1.0.5的wince移植

本文完全參照了天將降的博客文章&#xff0c;寫于此以作來日備忘之用&#xff0c;原文地址&#xff1a;http://bk6.blog.163.com/blog/static/24498560201051193449196/ 第一步&#xff1a;下載安裝Cygwin。筆者建議大家不要安裝不完整的版本&#xff0c;以免出現不必要的錯誤…

andriod studio 運行 無結果_華為物聯網操作系統LiteOS內核教程01——IoT-Studio介紹及安裝...

1. 物聯網一站式開發工具 —— IoT StudioIoT Studio 是支持 LiteOS 嵌入式系統軟件開發的工具&#xff0c;提供了代碼編輯、編譯、燒錄 及調試等一站式開發體驗&#xff0c;支持 C、C、匯編等多種開發語言&#xff0c;讓您快速&#xff0c;高效地進 行物聯網開發。2. IoT Stud…

5G通信技術能否終結商用WiFi?

科技創新與體育發展可謂相生相伴&#xff0c;而如今科技在體育領域的應用也越來越廣泛。本周的話題關于5G技術與球場&#xff0c;作者為英國體育娛樂營銷咨詢公司Stadia Solutions的聯席首席執行官戈登坎貝爾。在坎貝爾先生看來&#xff0c;球場Wi-Fi賦予了俱樂部對數據的掌控力…

顏色轉換

以藍色為例&#xff0c;#0000FF應該被表示成rgb(0,0,255)。 我們將函數命名為getRGB() &#xff08;可以將字符串視為數組&#xff0c;這個數組的元素為字符&#xff09; function getRGB(color) {var rgb [parseInt(0xcolor.slice(1,3)),parseInt(0xcolor.slice(3,5)),parseI…

wince ./configure

CPPFLAGS"-I/usr/wince/include -D_WIN32_WCE0x0500" LDFLAGS"-L/usr/wince/lib" ./configure--hostarm-mingw32ce 指定軟件運行的系統平臺&#xff1b;host就是你編譯好的程序可以運行的平臺--target-osmingw32ce 指定軟件面向(target to)的系統平臺.這主…

android 按鍵會觸發ontouch嗎?_Android實現炫酷的拖拽浮動按鈕

IOS的Assistive Touch效果很炫酷&#xff0c;可以任意拖拽&#xff0c;同時點擊后會展開菜單欄。然而&#xff0c;這不只是IOS的特權&#xff0c;Android也可以實現。但是由于懸浮窗需要申請權限&#xff0c;所以本文僅在app內實現&#xff0c;可以任意拖拽&#xff0c;并可以響…

強名稱程序集(strong name assembly)——為程序集賦予強名稱

引言&#xff1a;在曾經的項目開發中&#xff0c;在程序集中見到過一個后綴為*.snk的文件。當時看這個文件的圖標。感覺可能是企業內部保護版權啥的一種方式。一&#xff0c;強程序集攻克了哪些問題&#xff1f;1&#xff0c;唯一標識一個程序集2&#xff0c;放置程序集被仿冒和…

如何成為一名合格的數據分析師

“21世紀什么最貴&#xff0c;人才”&#xff0c;在目前大數據時代下&#xff0c;什么最難找&#xff0c;什么最貴&#xff0c;實現數據價值的人&#xff0c;數據分析師。 但是對于數據分析師的認識&#xff0c;比較極端&#xff0c;但對數據分析師價值的認識正在回歸理性。很多…

【ffmpeg for wince】音視頻編解碼多平臺移植(for window/wince))ffmpeg

from: http://www.cnblogs.com/windwithlife/archive/2009/05/31/1492728.html 終于完成了了第二個Client side原型&#xff08;for Wince)&#xff0c;其中花掉我最多時間的就是ffmpeg的對WINCE的移植。其中有大半時間是由于網上的一些不完整及不正確信息所誤導&#xff0c;但…

Java 重寫(Override)與重載(Overload)

重寫(Override) 重寫是子類對父類的允許訪問的方法的實現過程進行重新編寫&#xff01;返回值和形參都不能改變。即外殼不變&#xff0c;核心重寫&#xff01; 重寫的好處在于子類可以根據需要&#xff0c;定義特定于自己的行為。也就是說子類能夠根據需要實現父類的方法。在面…

銀聯pos小票word模板_商家pos機刷卡必須知道的知識

相信很多卡友伙伴或者商鋪店家都裝有pos機&#xff0c;然后一般pos機都沒有使用說明書&#xff0c;更沒有結合刷卡方法在內的秘籍。今天我就分享下刷卡必須知道的一些知識。剛剛辦理pos機的當天一定要注意&#xff1a;使用之前呢&#xff0c;務必核對一下基本信息&#xff0c;例…