棧即後進先出(LIFO)的線性表。
棧的常用算法有置棧空、判棧空、進棧、出棧、取棧頂等。
1.順序棧
結構如下:
typedef struct
{
DataType data[MAXSIZE];
int top;
}SeqStack;
即,它需要一個棧頂top。
相關算法的關鍵步驟如下
//置棧空
void Initial(SeqStack *S)
{ S->top=-1; }
//判棧空
int IsEmpty(SeqStack *S)
{ return S->top==-1; }
//進棧
void Push(SeqStack *S,DataType x)
{ S->data[++S->top]=x; }
//出棧
DataType Pop(SeqStack *S)
{ return S->data[S->top--]; } //棧頂減1,返回已經出棧的元素
2. 鏈棧
結構如下:
typedef struct node
{
DataType data;
struct node *next; //知道結構名稱的作用了吧,這裏就要用到node
}LinkStack;
typedef struct
{
LinkStack *top;
}TopNode;
我們需要一個專門指向棧頂的指針(注意不是棧頂指針,而是指向棧頂的指針)。所以我們定義一個結構體TopNode,T.top就是指向棧頂的指針。或者我們用一個數組也行:
LinkStack * TopNode[1];
那麼TopNode[0]就用來作指向棧頂的指針,函數的形參寫成LinkStack * TopNode[],傳實參的時候用數組名TopNode,在函數內部就可以使用TopNode[0]。這種方面類似於函數形參是一個結構體TopNode *T,那麼傳實參的時候傳&T,在函數內部使用T->top。
至於用數組和用結構哪個好,我覺得用結構還要用typedef定義類型,效率可能稍低。所以,用結構含義清楚,用數組效率更高。
/*頭插法特點:無頭結點,top指針始終指向最後插入的那個元素*/
LinkStack *CreListTou()
{ int x; LinkStack *S; TopNode T;
T.top=NULL;
scanf("%d",&x);
while(x!=-1) //輸入-1代表結束
{
S=malloc(sizeof(LinkStack));
S->data=x;
/*關鍵代碼: S->next等於T.top ,然後T.top反轉來等於S*/
S->next=T.top;
T.top=S; //修改top指向
scanf("%d",&x);
}
return T.top;
}
//置棧空
void Initial(TopNode *T)
{ T->top=NULL; }
//進棧
void Push(TopNode *T,DataType x)
{
LinkStack *S;
S=malloc(sizeof(LinkStack));
S->data=x;
//與建棧時相同,將S的後繼設置爲原棧頂,S成爲新的棧頂
S->next=T->top;
T->top=S;
}
//出棧
DataType Pop(TopNode *T)
{
LinkStack *p;
DataType x;
/*關鍵算法:先把T.top指向原棧頂的next,然後free掉原棧頂*/
p=T->top;
x=p->data;
T->top=p->next;// T.top指向原棧頂的next
free(p);
return x;
}
注意上面列出的只是算法的關鍵部分,並不完整,刪減了一些“棧空”“棧滿”的判斷。