【數(shù)據(jù)結(jié)構(gòu)】棧

本文更新于個(gè)人博客Burnside Blog

總的來(lái)說(shuō)玩徊,棧(Stack)是一種應(yīng)用十分廣泛的線性數(shù)據(jù)結(jié)構(gòu)哪替,我們大多數(shù)時(shí)候可以把它理解成一個(gè)杯子红氯,杯子只有一個(gè)口泣懊,它既是進(jìn)入的入口躺彬,也是退出的出口煤墙。的確如此,棧是一種先入后出(LIFO)的數(shù)據(jù)結(jié)構(gòu)宪拥,它支持插入與刪除兩種操作仿野,且兩個(gè)操作僅可以在一端進(jìn)行。

為了方便起見(jiàn)她君,我們不使用動(dòng)態(tài)方式生成一個(gè)棧脚作,或銷毀一個(gè)棧,我們只考慮一個(gè)靜態(tài)的棧的功能實(shí)現(xiàn)缔刹。棧中的元素可以是任何的用戶自定義類型球涛,為了方便起見(jiàn),我們假設(shè)元素的類型為int桨螺,如需要?jiǎng)e的類型宾符,只需要靈活處理即可。接下來(lái)我們申請(qǐng)一塊長(zhǎng)度為MaxSize的連續(xù)內(nèi)存來(lái)存儲(chǔ)這個(gè)棧灭翔,這時(shí)它又被稱為順序棧魏烫。

int Stack[MaxSize];

這樣我們就成功獲得了一個(gè)自己的棧「蜗洌考慮往棧中插入元素或刪除元素哄褒,所改變的只有最頂部的元素距棧底的距離,這里的距離表示的是元素個(gè)數(shù)煌张,我們把這個(gè)頂部稱為棧頂呐赡,可以用一個(gè)變量top來(lái)維護(hù),最頂部的元素為棧頂元素骏融,不難發(fā)現(xiàn)链嘀,每一次的刪除操作,總是刪除的棧頂元素档玻。

因此怀泊,我們會(huì)得到棧的幾個(gè)操作:

1、插入元素

int push(int x){

? ? Stack[++top]=x;

? ? return top;

}

插入一個(gè)元素很簡(jiǎn)單误趴,只需要將棧頂指向數(shù)組內(nèi)的下一個(gè)位置霹琼,然后把該位置賦值為要插入的值即可,函數(shù)中的變量x即為需要插入的值,top為棧頂枣申,此函數(shù)返回值為插入后的棧頂售葡。注意,當(dāng)棧為空的時(shí)候忠藤,變量top應(yīng)當(dāng)?shù)扔?1挟伙。

2、刪除元素

int pop(){

? ? return --top;

}

刪除一個(gè)元素更簡(jiǎn)單熄驼,只需要將棧頂下移一個(gè)就可以像寒。注意,原來(lái)的棧頂元素不需要做任何的改變瓜贾,因?yàn)橹灰迦氲竭@個(gè)位置诺祸,這個(gè)位置就會(huì)立馬被賦值上被插入的新的元素,所以只需要讓棧頂下移即可祭芦,而并不需要改變棧頂元素的值筷笨。此函數(shù)返回的是刪除后的棧頂。要注意龟劲,這里有一個(gè)潛在的問(wèn)題胃夏,如果這個(gè)時(shí)候棧已空,但仍然調(diào)用了pop()昌跌,可能會(huì)使以后的操作訪問(wèn)到非法位置仰禀,因此,請(qǐng)務(wù)必確保棧是非空的蚕愤,再使用pop()答恶,為了方便確保棧是否為空,我們引入一個(gè)新的函數(shù)萍诱。

3悬嗓、查詢棧是否為空

bool empty(){

? ? return top==-1?true:false;

}

很簡(jiǎn)單,棧為空的標(biāo)志為top等于-1裕坊,直接調(diào)用即可包竹。

4、查詢椉現(xiàn)在的大兄芟埂(size)

int size(){

? ? return top+1;

}

也很簡(jiǎn)單,棧的大小為top+1饵蒂。

5声诸、查詢棧頂元素

int top(){

? ? return Stack[top];

}

請(qǐng)注意,請(qǐng)務(wù)必在棧非空的情況下使用該命令苹享。

6双絮、刪除棧內(nèi)的所有元素

void clear(){

? ? while(!empty()) pop();

}

很自然的實(shí)現(xiàn),當(dāng)棧為非空時(shí)得问,一直刪除元素就可以了囤攀。

以上為棧的所有操作,部分書(shū)中還介紹了鏈?zhǔn)綏9常疚闹胁辉偕婕胺倌樱唧w的實(shí)現(xiàn)思想與上述六個(gè)函數(shù)一樣。

棧有很多實(shí)際的應(yīng)用漓骚,其中常見(jiàn)的有:把一個(gè)十進(jìn)制數(shù)拆分為二進(jìn)制蝌衔,查詢一個(gè)括號(hào)序列是否能夠匹配,計(jì)算表達(dá)式的值等蝌蹂。我們主要來(lái)寫(xiě)查詢括號(hào)序列是否匹配噩斟,剩下兩個(gè)常見(jiàn)功能讀者可以自行完成。

括號(hào)序列孤个,是僅由(與)構(gòu)成的序列剃允,匹配的定義如下:

1. ()是一個(gè)合法匹配。

2. 如果A是一個(gè)合法匹配齐鲤,則(A)是一個(gè)合法匹配斥废。

3. 如果A和B都是合法匹配,則AB是一個(gè)合法匹配给郊。

不難發(fā)現(xiàn)牡肉,()()(())((())())是一個(gè)合法匹配,而(()不是一個(gè)合法匹配淆九。

判斷的過(guò)程也很輕松统锤,我們只需要模擬這個(gè)匹配的過(guò)程就可以了,具體操作步驟如下:

1. 如果當(dāng)前讀取到一個(gè)(吩屹,進(jìn)棧跪另,讀取下一位。

2. 如果當(dāng)前讀取到一個(gè))煤搜,如果棧非空免绿,取棧頂?shù)挠依ㄌ?hào)與之匹配,讀取下一位擦盾;如果棾凹荩空,則找不到括號(hào)與之匹配迹卢,證明其不合法辽故。

3. 如果讀完了整個(gè)括號(hào)序列棧空腐碱,則整個(gè)括號(hào)序列合法誊垢,否則不合法掉弛。

正確性顯然,不過(guò)多贅述喂走,代碼如下:

#include<iostream>

#include<cstdio>

const int MaxSize=1000;

char Stack[MaxSize];

int top=-1,flag=true;

int main(){

? ? char c;

? ? while((c=getchar())!=EOF){

? ? ? ? if(c=='(') Stack[++top]='(';

? ? ? ? else{

? ? ? ? ? ? if(top==-1){

? ? ? ? ? ? ? ? flag=false;

? ? ? ? ? ? ? ? break;

? ? ? ? ? ? }

? ? ? ? ? ? top--;

? ? ? ? }

? ? }

? ? if(top!=-1) flag=false;

? ? printf(flag?"legal":"illegal");

? ? return 0;

}

可能會(huì)有人表示輸出總是illegal殃饿,因?yàn)樵谝婚_(kāi)始讀的時(shí)候把回車(chē)也讀進(jìn)去了,可以使用文件輸入輸出芋肠,最后不換行就可以了乎芳,或者可以采用其他的輸入方式。

在某些特殊應(yīng)用中帖池,還會(huì)使用到單調(diào)棧奈惑,因?yàn)閮H在競(jìng)賽中常用,因此不在本文中描述睡汹。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末肴甸,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子囚巴,更是在濱河造成了極大的恐慌雷滋,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,817評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件文兢,死亡現(xiàn)場(chǎng)離奇詭異晤斩,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)姆坚,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,329評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門(mén)澳泵,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人兼呵,你說(shuō)我怎么就攤上這事兔辅。” “怎么了击喂?”我有些...
    開(kāi)封第一講書(shū)人閱讀 157,354評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵维苔,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我懂昂,道長(zhǎng)介时,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,498評(píng)論 1 284
  • 正文 為了忘掉前任凌彬,我火速辦了婚禮沸柔,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘铲敛。我一直安慰自己褐澎,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,600評(píng)論 6 386
  • 文/花漫 我一把揭開(kāi)白布伐蒋。 她就那樣靜靜地躺著工三,像睡著了一般迁酸。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上俭正,一...
    開(kāi)封第一講書(shū)人閱讀 49,829評(píng)論 1 290
  • 那天胁出,我揣著相機(jī)與錄音,去河邊找鬼段审。 笑死,一個(gè)胖子當(dāng)著我的面吹牛闹蒜,可吹牛的內(nèi)容都是我干的寺枉。 我是一名探鬼主播,決...
    沈念sama閱讀 38,979評(píng)論 3 408
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼绷落,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼姥闪!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起砌烁,我...
    開(kāi)封第一講書(shū)人閱讀 37,722評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤筐喳,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后函喉,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體避归,經(jīng)...
    沈念sama閱讀 44,189評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,519評(píng)論 2 327
  • 正文 我和宋清朗相戀三年管呵,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了梳毙。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,654評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡捐下,死狀恐怖账锹,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情坷襟,我是刑警寧澤奸柬,帶...
    沈念sama閱讀 34,329評(píng)論 4 330
  • 正文 年R本政府宣布,位于F島的核電站婴程,受9級(jí)特大地震影響廓奕,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜档叔,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,940評(píng)論 3 313
  • 文/蒙蒙 一懂从、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧蹲蒲,春花似錦番甩、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,762評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)窍育。三九已至,卻和暖如春宴胧,著一層夾襖步出監(jiān)牢的瞬間漱抓,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,993評(píng)論 1 266
  • 我被黑心中介騙來(lái)泰國(guó)打工恕齐, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留乞娄,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,382評(píng)論 2 360
  • 正文 我出身青樓显歧,卻偏偏與公主長(zhǎng)得像仪或,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子士骤,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,543評(píng)論 2 349

推薦閱讀更多精彩內(nèi)容