C語(yǔ)言?棧與數(shù)組的實(shí)現(xiàn)詳解
棧的實(shí)現(xiàn)
首先我們思考一個(gè)問題,什么是棧?
棧是數(shù)據(jù)結(jié)構(gòu)的一種,棧在我們?nèi)粘>幋a中遇到的非常多,很多人對(duì)棧的接觸可能僅僅局限在 遞歸使用的是棧 和 StackOverflowException,棧是一種后進(jìn)先出的數(shù)據(jù)結(jié)構(gòu)(可以想象生化金字塔的牢房和生化角斗場(chǎng)的狗洞)。
棧的定義
棧(stack)又名堆棧,它是一種運(yùn)算受限的線性表。限定僅在表尾進(jìn)行插入和刪除操作的線性表。這一端被稱為棧頂,相對(duì)地,把另一端稱為棧底。向一個(gè)棧插入新元素又稱作進(jìn)棧、入?;驂簵?,它是把新元素放到棧頂元素的上面,使之成為新的棧頂元素;從一個(gè)棧刪除元素又稱作出?;蛲藯?,它是把棧頂元素刪除掉,使其相鄰的元素成為新的棧頂元素
棧的應(yīng)用廣泛,比如你的程序執(zhí)行查看調(diào)用堆棧、計(jì)算機(jī)四則加減運(yùn)算、算法的非遞歸形式、括號(hào)匹配問題等等。所以棧也是必須掌握的一門數(shù)據(jù)結(jié)構(gòu)。最簡(jiǎn)單大家都經(jīng)歷過,你拿一本書上下疊在一起,就是一個(gè)后進(jìn)先出的過程,你可以把它看成一個(gè)棧。下面我們介紹數(shù)組實(shí)現(xiàn)的棧兩種形式。
數(shù)組實(shí)現(xiàn)
靜態(tài)棧
一般不推薦使用這種方法,因?yàn)楫?dāng)空間不夠用時(shí),增容會(huì)有點(diǎn)麻煩,不實(shí)用。
typedef struct Stack { STDataType _a[]; //STDataType 為int宏定義,當(dāng)然你也可以將它定義為其他類型,宏定義是為了換棧類型的時(shí)候方便一點(diǎn) int _top; // 棧頂 int _capacity; // 容量 }Stack;
動(dòng)態(tài)棧
相比靜態(tài)棧,動(dòng)態(tài)??臻g不夠時(shí)可以直接時(shí)用realloc動(dòng)態(tài)擴(kuò)容,但是動(dòng)態(tài)擴(kuò)會(huì)有一定程度的消耗,我們會(huì)直接擴(kuò)容一倍,當(dāng)使用不完時(shí)會(huì)造成一定程度的空間浪費(fèi)。
typedef struct Stack { STDataType* _a;//指向一塊開辟出來的連續(xù)空間的指針 int _top; // 棧頂 int _capacity; // 容量 }Stack;
棧要實(shí)現(xiàn)的操作
// 初始化棧 void StackInit(Stack* ps); // 入棧 void StackPush(Stack* ps, STDataType data); // 出棧 void StackPop(Stack* ps); // 獲取棧頂元素 STDataType StackTop(Stack* ps); // 獲取棧中有效元素個(gè)數(shù) int StackSize(Stack* ps); // 檢測(cè)棧是否為空,如果為空返回非零結(jié)果,如果不為空返回0 bool StackEmpty(Stack* ps); // 銷毀棧 void StackDestroy(Stack* ps);
棧的初始化
void StackInit(Stack* ps) { ps->_a = NULL; //初始化時(shí)將指針指向空,此時(shí)沒有開辟空間 //這里可以將top賦值為0,也可以賦值為-1。 ps->_top = -1; //賦值為0時(shí)表示top為棧頂元素的下一個(gè)位置的下標(biāo),賦值為-1時(shí)top為棧頂元素的下標(biāo) ps->_capacity = 0; //棧的容量 }
入棧
void StackPush(Stack* ps, STDataType data) { assert(ps); //考慮要不要增容 //當(dāng)top為0時(shí)判斷條件為 //if(ps->top==ps->_capacity) if (ps->_top+1 == ps->_capacity)//當(dāng)棧滿時(shí)進(jìn)入 { //判斷當(dāng)前棧的容量是否為0,為0的話開辟4個(gè)空間,不為0時(shí)擴(kuò)容一倍 int newcapacity = ps->_capacity == 0 ? 4 : ps->_capacity * 2; STDataType* tmp = realloc(ps->_a, sizeof(STDataType) * newcapacity); if (tmp == NULL) { exit(-1); } ps->_a = tmp; ps->_capacity = newcapacity; } //擴(kuò)容完成,或者不用擴(kuò)容,開始插入 ps->_top++; ps->_a[ps->_top] = data; //當(dāng)top為0時(shí)插入操作 //ps->_a[ps->_top] = data; //ps->_top++; }
出棧
void StackPop(Stack* ps) { assert(ps); //判斷是否為空 assert(!StackEmpty(ps));//暴力判斷 //if (top==-1)//溫柔判斷 //{ // printf("棧已經(jīng)空了!\n"); // exit(-1); //甩出異常 //} ps->_top--; }
取棧頂元素
STDataType StackTop(Stack* ps) { assert(ps); //判斷是否為空,為空甩出異常。 assert(!StackEmpty(ps)); //if (!StackEmpty(ps)) { // printf("棧為空!\n"); // exit(-1); //} return ps->_a[ps->_top]; //返回棧頂元素 }
判斷棧中有幾個(gè)有效數(shù)據(jù)
//取出棧里有效元素個(gè)數(shù)。 int StackSize(Stack* ps) { assert(ps); return ps->_top+1; }
判斷棧是否為空
bool StackEmpty(Stack* ps) { assert(ps); return ps->_top == -1; //ps->_top為-1返回true,否則返回false. ? }
銷毀棧
銷毀棧是必不可少的的一步,如果沒有銷毀的話會(huì)造成內(nèi)存泄露
void StackDestroy(Stack* ps)
{
assert(ps);
free(ps->_a);
ps->_a = NULL;
ps->_top = -1;
ps->_capacity = 0;
}
鏈棧
最后介紹一下鏈棧,這里就不實(shí)現(xiàn)了有興趣的話可以自己實(shí)現(xiàn)一下。
鏈棧和鏈表一樣的,也是通指針將各個(gè)數(shù)據(jù)塊鏈接起來的
設(shè)計(jì)鏈棧是最好設(shè)計(jì)為雙向鏈表,否則當(dāng)你設(shè)計(jì)為用尾作棧頂是出棧效率低。
用頭做棧頂時(shí),頭插頭刪,可以設(shè)計(jì)為單鏈表。
到此這篇關(guān)于C語(yǔ)言 棧與數(shù)組的實(shí)現(xiàn)詳解的文章就介紹到這了,更多相關(guān)C語(yǔ)言 棧與數(shù)組內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
基于Qt實(shí)現(xiàn)簡(jiǎn)單的計(jì)算器
這篇文章主要介紹了如何使用Qt框架實(shí)現(xiàn)一個(gè)簡(jiǎn)單的計(jì)算器應(yīng)用,我們將使用C++編程語(yǔ)言和Qt的圖形用戶界面庫(kù)來開發(fā)這個(gè)應(yīng)用,并展示如何實(shí)現(xiàn)基本的算術(shù)操作,希望對(duì)大家有所幫助2023-11-11C++實(shí)現(xiàn)兩個(gè)有序數(shù)組的合并
這篇文章主要為大家詳細(xì)介紹了C++實(shí)現(xiàn)兩個(gè)有序數(shù)組的合并,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-02-02C++實(shí)現(xiàn)編碼轉(zhuǎn)換的示例代碼
這篇文章主要介紹了C++實(shí)現(xiàn)編碼轉(zhuǎn)換的示例代碼,幫助大家快捷的實(shí)現(xiàn)編碼轉(zhuǎn)換,感興趣的朋友可以了解下2020-08-08C++使用new和delete進(jìn)行動(dòng)態(tài)內(nèi)存分配與數(shù)組封裝
這篇文章主要介紹了C++使用new和delete進(jìn)行動(dòng)態(tài)內(nèi)存分配與數(shù)組封裝,運(yùn)行期間才能確定所需內(nèi)存大小,此時(shí)應(yīng)該使用new申請(qǐng)內(nèi)存,下面我們就進(jìn)入文章學(xué)習(xí)具體的操作方法,需要的小伙伴可以參考一下2022-03-03利用C語(yǔ)言編輯畫圖程序的實(shí)現(xiàn)方法(推薦)
下面小編就為大家?guī)硪黄肅語(yǔ)言編輯畫圖程序的實(shí)現(xiàn)方法(推薦)。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-06-06C/C++實(shí)現(xiàn)Windows注冊(cè)表的基本操作
Windows注冊(cè)表(Registry)是Windows操作系統(tǒng)中用于存儲(chǔ)系統(tǒng)配置信息、用戶設(shè)置和應(yīng)用程序數(shù)據(jù)的一個(gè)集中式數(shù)據(jù)庫(kù),本文主要為大家介紹了C++對(duì)注冊(cè)表的基本操作,感興趣的小伙伴可以了解下2023-11-11C++實(shí)現(xiàn)查找二叉樹中和為某一值的所有路徑的示例
這篇文章主要介紹了C++實(shí)現(xiàn)查找二叉樹中和為某一值的所有路徑的示例,文中的方法是根據(jù)數(shù)組生成二叉排序樹并進(jìn)行遍歷,需要的朋友可以參考下2016-02-02