棧:一種特殊的線性表,其只允許在固定的一端進行插入和刪除操作,進行數據插入和刪除操作的一端被稱爲棧頂,另一端稱爲棧底。不含任何元素的棧稱爲空棧,內存中的“棧區”也是通過這樣的棧結構實現的,即通常所說的數據先進先出
動態順序棧
我們通過一個簡單的數組來進行數據的存儲,我們規定只能從數組的尾部插入與刪除數據,這樣就實現了一個簡易的棧結構,靜態數組實現的棧是由存儲上限的,數組存儲滿元素後,就不能再進行插入操作了,這就是靜態棧的不足。而靜態棧實現較簡單,所以我這裏就不再細比較了。
而動態棧是通過在堆上申請內存來實現的,所以根本不用擔心數據存滿的情況,除非你自己作死,比如把malloc寫到死循環裏。
我們定義一個無符號長整形變量”size”來控制有效元素的個數,用一個結構體把數組和“size”包含進去。
順序棧所有的操作時間複雜度爲O(1),因爲是直接通過數組下標來進行數據訪問。
我們先定義一個結構體來存放一個動態數組和控制有效元素個數的變量
- 結構體聲明
typedef char SeqStackType;
typedef struct SeqStack{
SeqStackType* data;//長度到了最大值時就malloc一段新的內存,所以用指針指向的內存空間來存儲順序表中的數據
size_t size;//有效長度
size_t capacity;//原有的內存可容納的最大長度
}SeqStack;
- 具體操作函數聲明
//初始化棧
void SeqStackInit(SeqStack* seq);
//銷燬棧
void SeqStackDestroy(SeqStack* seq);
//擴容函數
//1.malloc一塊更大的內存空間
//2.將原內存空間裏的數據拷貝到新的內存空間中
//3.釋放掉原內存空間,將指針指向新的內存
SeqStackType* SeqStackExpand(SeqStack* seq);
//往棧中插入數據
void SeqStackPush(SeqStack* seq,SeqStackType value);
//刪除數據
void SeqStackPop(SeqStack* seq);
//取出棧頂元素
//1.通過一個輸出型參數 value 實現,將棧頂元素的值賦給value,因爲是地址傳遞,所以外部實參的值也被修改了
//2.成功返回1,失敗返回0
int SeqStackFindTop(SeqStack* Seq,SeqStackType* value);
- 具體函數實現
初始化和銷燬
//初始化
void SeqStackInit(SeqStack* seq)
{
seq->capacity = 1000;
seq->data = (SeqStackType*)malloc(seq->capacity*sizeof(SeqStackType));
seq->size = 0;
}
//清空棧
void SeqStackDestroy(SeqStack* seq)
{
free(seq->data);
seq->size = 0;
seq->capacity = 1000;
}
插入數據,記得判斷是否當前內存已到最大容量,如果是,就要先進行擴容,再進行插入新數據
//如果當前棧已經滿了,就要動態擴容
SeqStackType* SeqStackExpand(SeqStack* seq)
{
if(seq==NULL){
//非法輸入
return NULL;
}
SeqStackType* newseq = (SeqStackType*)malloc(2*(seq->capacity)+1);
size_t i = 0;
for(;i<seq->size;i++){
newseq[i] = seq->data[i];
}
seq->capacity = 2*(seq->capacity)+1;
free(seq->data);
return newseq;
}
//入棧
void SeqStackPush(SeqStack* seq,SeqStackType value)
{
if(seq==NULL){
//非法輸入
return;
}
if(seq->size>=seq->capacity){
seq->data = SeqStackExpand(seq);
}
seq->data[seq->size] = value;
seq->size++;
}
刪除數據,注意如果是空棧就直接退出
void SeqStackPop(SeqStack* seq)
{
if(seq==NULL){
//非法輸入
return;
}
if(seq->size==0){
//空棧
return;
}
seq->size--;
}
取棧頂元素,通過輸出型參數 value 取到棧頂元素值的複製,並不是把元素本體取出來,棧結構並未發生改變
//取棧頂元素
int SeqStackFindTop(SeqStack* Seq,SeqStackType* value)
{
if(Seq==NULL)
{
//非法輸入
return 0;
}
if(Seq->size==0){
//空棧
return 0;
}
*value = Seq->data[Seq->size-1];
return 1;
}
鏈表實現棧結構的博客,點這裏->鏈式棧實現