一、棧的定義
在我們軟件應用中,棧這種後進先出數據結構的應用是非常普遍的。比如你用瀏覽器上網時,不管什麼瀏覽器都有一一個“後退”鍵,你點擊後可以按訪問順序的逆序加載瀏覽過的網頁。這就是棧的一個實際運用。
棧(stack)是僅限在表尾進行插入和刪除的線性表
二、棧的順序存儲結構及代碼實現
首先來看,棧的定義,這裏是用數組實現棧,實際上用鏈表也可以實現,稱爲鏈式棧。
個人認爲棧這部分重點在於看懂源碼,動手實現起來是十分容易的。
#define datatype int
#define maxsize 1024
struct stack
{
datatype data[maxsize];
int top; //棧頂指針,1個元素就是0,2個就是1,以此類推
};
棧的初始化
首先要對這個結構體申請空間,然後傳回該結構體的指針。
stack* init_stack() //返回類型爲結構體指針的函數,初始化棧
{
stack* s;
s = (stack*)malloc(sizeof(stack));
if (!s)
{
cout << "空間不足,申請失敗" << endl;
return NULL;
}
else
{
s->top = -1;//定義棧底爲-1
return s;
}
}
入棧
要判斷是否爲棧滿,然後將該元素壓入。
int push(stack* s, datatype x) //入棧
{
if (s->top == maxsize - 1)
{
cout << "棧滿,無法入棧" << endl;
return 0;
}
else
{
s->data[++s->top] = x;
return 1;
}
}
出棧
要判斷是否爲空棧,然後將該元素的值傳給指針。(改變函數,返回該值也可以)。
int pop(stack* s, datatype* e) //出棧一個元素,並且用e返回其值
{
if (empty_stack(s))
{
cout << "棧空,無法出棧" << endl;
return 0;
}
else
{
*e = s->data[s->top--];
return 1;
}
}
判斷空棧
這個很簡單,看top值是否爲-1即可。
int empty_stack(stack* s) //判斷空棧
{
if (s->top == -1)
return 1; //爲空
else
return 0;
}
獲得棧頂元素
datatype gettop(stack* s)
{
if (empty_stack(s))
{
cout << "棧空,無棧頂元素" << endl;
return 0;
}
else
return s->data[s->top]; //返回棧頂
}
顯示棧中所有元素,自上而下
void print_stack(stack* s) //顯示所有元素
{
if (empty_stack(s))
{
cout << "棧空,無元素" << endl;
return;
}
else
{
for (int i = s->top; i >= 0; i--)
cout << s->data[i] << endl;
return;
}
}
至於返回棧中元素數量,這個可以定義一個函數返回top+1的值,即爲元素個數。同理,刪除這個棧中所有元素,只需要把top的值修改爲-1即可。銷燬棧,釋放棧空間即可。在此不多贅述。
三、STL中的<stack>
這就十分簡單了,函數都封裝好了。C++中stl的stack(棧)以其他容器(deque默認,vector,list)作爲底層數據結構而形成,只是修改了接口以滿足棧的特性。
#include<stack>//棧
stack<int> s;//參數也是數據類型,這是棧的定義方式
s.empty()//如果棧爲空返回true,否則返回false
s.size()//返回棧中元素的個數
s.pop()//刪除棧頂元素但不返回其值
s.top()//返回棧頂的元素,但不刪除該元素
s.push(X)//在棧頂壓入新元素 ,參數X爲要壓入的元素
四、兩棧共享空間
數組有兩個端點,兩個棧有兩個棧底,讓一個棧的棧底爲0,另一個爲棧的棧末端,即爲數組大小的n-1處。這樣,兩個棧都增加元素都是往中間處靠攏。
棧1爲空時,就是top1等於-1時,而當top2等於n時,即是棧2爲空時,那什麼時候棧滿呢?
若棧2是空棧,棧1的top1等於n-1時,就是棧1滿了。反之,當棧1爲空棧時,top2 等於0時,爲棧2滿。但更多的情況,其實就是,兩個指針之間相差1時,即top1 + 1 == top2 爲棧滿。
事實上,使用這樣的數據結構,通常都是當兩個棧的空間需求有相反關係時,也就是一個棧增長時另一個棧在縮短的情況。當然,這只是針對兩個具有相同數據類型的棧的一一個設計上的技巧,如果是不相同數據類型的棧,這種辦法不但不能更好地處理問題,反而會使問題變得更復雜。
定義
#define datatype int
#define maxsize 1024
typedef struct
{
datatype data[maxsize];
int top1;
int top2;
}doublestack;
壓入元素
在壓入和刪除時,就只是需要判斷一下對哪個棧操作而已。
int double_stack_push(doublestack* s, int stacknumber, datatype x)
//結構體指針,要操作的棧,要壓入的元素
{
if (s->top1 + 1 == s->top2)
return 0; //棧滿
else
{
if (stacknumber == 1)
s->data[++s->top1] = x; //先自加再賦值
else if(stacknumber==2)
s->data[--s->top2] = x;
return 1;
}
}
刪除元素
int double_stack_pop(doublestack* s, int stacknumber,datatype* e)
{
if (stacknumber == 1)
{
if (s->top1 == -1)
return 0; //棧1爲空
else
*e = s->data[s->top1--];//先出棧再自減
}
else if (stacknumber == 2)
{
if (s->top1 == maxsize)
return 0; //棧1爲空
else
*e = s->data[s->top2++];//先出棧再自加
}
return 1;
}