棧是一種特別的線性表。在棧中,只能在數據的一端(即棧頂)進行操作。最經典的解釋這個策略的例子就是疊盤子。盤子只能一個一個不斷放在之前的盤子堆上,拿盤子的時候也只能從上往下一個一個拿。這兩個操作,在stack中分別對於push和pop,即壓棧和出棧。這體現了棧的後進先出(LIFO)特性。
2. 棧的實現
stack的實現分爲兩種,一種是使用數組來模擬棧,另外一種是使用鏈表來模擬棧。
2 .1 數組實現(array stack)
首先,先來看使用數組的方法。
棧的結構爲
#define MAX_SIZE 20 //棧內最多有幾個元素
typedef int StackEntry;
typedef struct stack {
StackEntry entry[MAX_SIZE];
int top;
} Stack ;
用數組實現的棧使用連續的內存地址,爲了能夠知道棧頂位置,需要使用一個變量標記。
看起來,數組的實現方式十分的簡單!So easy!當向棧中壓入數據時,需要將top的值加1;出棧時,top的值減1。Too young,too naive!考慮兩個極端的情況:在棧滿時壓棧,在棧空時出棧。因此在進行push和pop操作之前需要檢查棧的情況,避免溢出。
int IsFull(Stack *s) {
return (s->top >= MAX_SIZE);
}
int IsEmpty(Stack *s) {
return (s->top <= 0);
}
void Push(StackEntry item, Stack* s) {
if(IsFull(s))
return;
else
s->entry[s->top++] = item;
}
void Pop(Stack* s) {
if(IsEmpty(s))
return;
else
s->top--;
}
StackEntry Top(Stack* s) {
if(!IsEmpty(s))
return s->entry[s->top-1];
else
return -1;
}
2.2. 鏈式實現(linked stack)
鏈式棧使用鏈表的存儲形式實現,其存儲是不連續的。我們首先定義stack的結構如下:
typedef struct node {
StackEntry val;
struct node *next;
} Node;
一般來說,很多人會自然而然的想到在stack中將心的元素加入到linked stack的末尾。但是要考慮到,對於stack,我們經常在其末尾進行操作,如果將元素插入到link的末尾,那麼每次操作都要先從頭到達末尾才能操作,所以我們需要換另外一種方法,採用前插的方式,將新的元素插入到列表的前面。這樣每次進行push和pop操作的時候就可以直接通過top指針操作。
//push a new node onto the top of the stack (the front of the list),
//and return whether successful
int Push (int val, Node* stack) {
Node* addNode = (Node*)malloc(sizeof(Node));
if (addNode == NULL) {
printf("out of memory!\n");
return 0;
}
addNode->val = val;
addNode->next = stack->next;
stack->next = addNode;
return 1;
}
//pop the top node from the stack
int Pop (Node* stack) {
if (IsEmpty(stack)) {
printf("the stack is empty!\n");
return 0;
}
Node *tmpNode = stack->next;
stack->next = tmpNode->next;
free(tmpNode);
return 1;
}
//check whether the stack is empty
int IsEmpty (Node* stack) {
return (stack->next == NULL);
}
//get the top value of the stack
int Top (Node* stack) {
if (IsEmpty(stack)) {
printf("the stack is empty!\n");
return -1;
}
return (stack->next->val);
}
綜合所有操作
數組實現
#include <stdio.h>
#include <stdlib.h>
#define MAX_SIZE 20 //棧內最多有幾個元素
typedef int StackEntry;
typedef struct stack {
StackEntry entry[MAX_SIZE];
int top;
} Stack;
int IsFull(Stack *s) {
return (s->top >= MAX_SIZE);
}
int IsEmpty(Stack *s) {
return (s->top <= 0);
}
void Push(StackEntry item, Stack* s) {
if (IsFull(s))
return;
else
s->entry[s->top++] = item;
}
void Pop(Stack* s) {
if (IsEmpty(s))
return;
else
s->top--;
}
StackEntry Top(Stack* s) {
if (!IsEmpty(s))
return s->entry[s->top-1];
else
return -1;
}
int main () {
Stack *s = (Stack*)malloc(sizeof(Stack));
s->top = 0;
Push(1, s);
Push(2, s);
Push(3, s);
//get 3
int temp = Top(s);
printf("%d ", temp);
//pop 3
Pop(s);
temp = Top(s);
printf("%d ", temp);
Push(4, s);
temp = Top(s);
printf("%d ", temp);
//pop 4
Pop(s);
temp = Top(s); // top is 2
printf("%d ", temp);
//pop 2
Pop(s);
temp = Top(s); //top is 1
printf("%d ", temp);
//pop 1
Pop(s);
temp = Top(s); //error get top element from empty stack
printf("%d ", temp);
return 0;
}
輸出:3 2 4 2 1 -1
鏈式實現
#include <stdio.h>
#include <stdlib.h>
typedef struct node
{
int val;
struct node *next;
} Node;
Node* CreateEmptyStack ();
int Push (int val, Node* stack);
int Pop (Node* stack);
int IsEmpty (Node* stack);
int Top (Node* stack);
int main () {
Node *s = CreateEmptyStack();
Push(1, s);
Push(2, s);
Push(3, s);
int temp = Top(s); //top is 3
printf("%d ", temp);
Pop(s); //pop 3
temp = Top(s); //top is 2
printf("%d ", temp);
Push(4, s);
temp = Top(s); //top is 4
printf("%d ", temp);
Pop(s); //pop 4
temp = Top(s); //top is 2
printf("%d ", temp);
Pop(s); //pop 2
temp = Top(s); //top is 1
printf("%d ", temp);
Pop(s); //pop 1
temp = Top(s); //error, get top element from empty stack
printf("%d ", temp);
return 0;
}
//create a empty stack and return the address
Node* CreateEmptyStack () {
Node* stack = (Node*)malloc(sizeof(Node));
if (stack == NULL) {
printf("out of memory!\n");
return NULL;
}
stack->val = 0;
stack->next = NULL;
return stack;
}
//push a new node onto the top of the stack (the front of the list),
//and return whether successful
int Push (int val, Node* stack) {
Node* addNode = (Node*)malloc(sizeof(Node));
if (addNode == NULL) {
printf("out of memory!\n");
return 0;
}
addNode->val = val;
addNode->next = stack->next;
stack->next = addNode;
return 1;
}
//pop the top node from the stack
int Pop (Node* stack) {
if (IsEmpty(stack)) {
printf("the stack is empty!\n");
return 0;
}
Node *tmpNode = stack->next;
stack->next = tmpNode->next;
free(tmpNode);
return 1;
}
//check whether the stack is empty
int IsEmpty (Node* stack) {
return (stack->next == NULL);
}
//get the top value of the stack
int Top (Node* stack) {
if (IsEmpty(stack)) {
printf("the stack is empty!\n");
return -1;
}
return (stack->next->val);
}
輸出:3 2 4 2 1 the stack is empty!
-1