棧(鏈式棧)----C語言


鏈式棧:就是一種操作受限的單向鏈表,對單向鏈表還不了解的可先看一下之前的一篇關於單向鏈表的隨筆,鏈表(單向鏈表的建立、刪除、插入、打印),理解了單向鏈表后再來看鏈式棧就比較輕松了

鏈式棧的操作一般含有:出棧、入棧、棧的初始化、判斷棧是否為空、清空棧,下面先上聲明部分代碼

 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 #define Empty 0        /* 棧空 */
 4 #define Avail 1        /* 棧可用 */
 5 
 6 typedef struct SNode  7 {  8     int data;  9     struct SNode *next; 10 }StackNode; 11 typedef struct LStack 12 { 13     StackNode *top;        /* 棧頂指針 */
14     StackNode *bottom;    /* 棧底指針 */
15     int height;            /* 鏈式棧高度 */
16 }LinkStack; 17 
18 LinkStack InitStack (LinkStack pStack);    /* 棧頂指針、棧底指針、棧高度初始化*/
19 LinkStack Push (LinkStack pStack);        /* 入棧 */
20 LinkStack Pop (LinkStack pStack);        /* 出棧 */
21 int StackEmpty (LinkStack pStack);        /* 判斷棧是否為空 */
22 LinkStack DeletStack (LinkStack pStack);/* 清空棧 */
23 void DisplyStack (LinkStack pStack);    /* 遍歷棧----自頂至底*/

 

一、節點的聲明

1 typedef struct SNode 2 { 3     int data; 4     struct SNode *next; 5 }StackNode;

鏈式棧節點的聲明與單向鏈表的聲明相同,都是由數據域和指針域組成,這里不再贅述

 

二、棧頂、棧底、棧高度的聲明

1 typedef struct LStack 2 { 3     StackNode *top;        /* 棧頂指針 */
4     StackNode *bottom;    /* 棧底指針 */
5     int height;            /* 鏈式棧高度 */
6 }LinkStack;

 

三、函數聲明

1 LinkStack InitStack (LinkStack pStack);    /* 棧頂指針、棧底指針、棧高度初始化*/
2 LinkStack Push (LinkStack pStack);        /* 入棧 */
3 LinkStack Pop (LinkStack pStack);        /* 出棧 */
4 int StackEmpty (LinkStack pStack);        /* 判斷棧是否為空 */
5 LinkStack DeletStack (LinkStack pStack);/* 清空棧 */
6 void DisplyStack (LinkStack pStack);    /* 遍歷棧----自頂至底*/

 

鏈式棧和單向鏈表的區別

上面已經提到的是鏈式棧是一種操作受限的單向鏈表(廢話··),先來回顧一下單向鏈表的建立過程(不清楚單向鏈表的可以先之前的另一篇隨筆鏈表(單向鏈表的建立、刪除、插入、打印)),單向鏈表在添加新的節點的時候是將原鏈表最后一個節點的

指針域指向新建的節點,然后新建節點指針域置為NULL作為鏈表的最后一個節點,而鏈式棧在添加新的節點的時候操作就不太一樣了,先來分析下棧的操作,棧只是棧頂來做插入和刪除操作,那么棧頂放在鏈表的頭部還是尾部呢?由於單向鏈表有頭指針

而棧頂指針也是必須的,那么就把棧頂指針當作頭指針來使用,比較好的辦法是把棧頂放到單鏈表的頭部。另外棧頂在頭部了,那么單鏈表的頭結點也就失去了意義,通常對於鏈式棧來說,是不需要頭結點的,現在來說鏈式棧添加新節點的操作

鏈式棧:新一個節點->將新建節點的指針域指向原棧頂節點->將棧頂指針移動到新建節點

單向鏈表:新建一個節點->將原鏈表最后的一個節點的指針域指向新建節點->新建節點的指針域置為NULL作為新鏈表的最后一個節點

為了方便讀者更加直觀了解這個過程下面上圖:

 

鏈式棧操作部分

一、入棧

 1 /* Function: 入棧 */
 2 LinkStack Push (LinkStack pStack)  3 {  4     int data;  5     StackNode *temp;  6 
 7     if ((temp = (StackNode *)malloc(sizeof(StackNode))) == NULL)  8  {  9         printf("內存空間不足\n"); 10         return pStack; 11  } 12     if (StackEmpty(pStack) == Empty)    /* 如果棧為空 */
13  { 14         pStack.top = pStack.bottom = temp;    /* 棧頂、棧底指針都指向新建節點 */
15         temp->next = NULL;                /* 節點指針域為空 */
16         printf("Please input data"); 17         scanf("%d", &data); 18         pStack.top->data = data; 19         pStack.height++; 20 
21         return pStack; 22  } 23     else        /* 棧不為空 */
24  { 25         temp->next = pStack.top;/* 新建節點指向原來的棧頂 */
26         pStack.top = temp;        /* 棧頂指針指向新建節點 */
27         printf("Please input data"); 28         scanf("%d", &data); 29         pStack.top->data = data; 30         pStack.height++; 31 
32         return pStack; 33  } 34 }

 

 

二、出棧

 1 /* Function: 出棧 */
 2 LinkStack Pop (LinkStack pStack)  3 {  4     StackNode *Second;  5 
 6     
 7     if (StackEmpty(pStack) == Empty)    /* 判斷棧是否為空 */
 8  {  9         printf("棧為空,無法出棧\n"); 10         return pStack; 11  } 12     if (pStack.top == pStack.bottom)    /* 如果出棧的元素為最后一個元素 */
13  { 14         printf("出棧元素為%d\n", pStack.top->data); 15         free(pStack.top); 16         pStack.top = pStack.bottom = NULL; /* 棧頂、棧底都指針都置為空 */
17         pStack.height--; 18 
19         return pStack; 20  } 21     printf("出棧元素為%d\n", pStack.top->data); 22     Second = pStack.top->next;    /* 指向棧頂的前一個元素*/
23 
24     free(pStack.top);    /* 釋放棧頂節點 */
25     pStack.top = Second;/* 將頭指針移動到新的棧頂節點 */
26     pStack.height--; 27 
28     return pStack; 29 }

 

出棧時需要判斷三種情況,第一種情況:棧為空、第二種情況:棧中只有一個元素、第三種情況:棧中元素大於等於兩個

 

三、判斷棧是否為空 

 1 /* Function: 判斷棧是否為空 */
 2 int StackEmpty (LinkStack pStack)  3 {  4     if (pStack.top == NULL && pStack.bottom == NULL)  5  {  6         return Empty;  7  }  8     else
 9  { 10         return Avail; 11  } 12 }

 

 

四、遍歷棧

 1 /* Function: 遍歷棧 自頂到底*/
 2 void DisplyStack (LinkStack pStack)  3 {  4     if (StackEmpty(pStack) == Empty)  5  {  6         printf("棧為空,無法遍歷\n");  7         return ;  8  }  9     printf("棧中元素["); 10     while (pStack.top != NULL) 11  { 12         printf("%d->", pStack.top->data); 13         pStack.top = pStack.top->next; 14  } 15     printf("]\n"); 16 }

 

 

五、清空棧

 1 /* Function: 清空棧 */
 2 LinkStack DeletStack (LinkStack pStack)  3 {  4     StackNode *del;  5 
 6     while (pStack.top != NULL)  7  {  8         del = pStack.top->next;    /* 棧頂節點的前一個節點 */
 9         free(pStack.top);        /* 釋放節點 */
10         pStack.top = del;        /* 棧頂指針移動到新棧頂 */
11  } 12 
13     return pStack; 14 }

 

 

六、初始化棧頂、棧底指針和棧高度

1 /* Function: 初始化棧頂、棧底、棧高度*/
2 LinkStack InitStack (LinkStack pStack) 3 { 4     pStack.top = pStack.bottom = NULL; 5     pStack.height = 0; 6 
7     return pStack; 8 }

 

 

鏈式棧實現完整代碼 

 

 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 #define Empty 0        /* 棧空 */
 4 #define Avail 1        /* 棧可用 */
 5 
 6 typedef struct SNode  7 {  8     int data;  9     struct SNode *next;  10 }StackNode;  11 typedef struct LStack  12 {  13     StackNode *top;        /* 棧頂指針 */
 14     StackNode *bottom;    /* 棧底指針 */
 15     int height;            /* 鏈式棧高度 */
 16 }LinkStack;  17 
 18 LinkStack InitStack (LinkStack pStack);    /* 棧頂指針、棧底指針、棧高度初始化*/
 19 LinkStack Push (LinkStack pStack);        /* 入棧 */
 20 LinkStack Pop (LinkStack pStack);        /* 出棧 */
 21 int StackEmpty (LinkStack pStack);        /* 判斷棧是否為空 */
 22 LinkStack DeletStack (LinkStack pStack);/* 清空棧 */
 23 void DisplyStack (LinkStack pStack);    /* 遍歷棧----自頂至底*/
 24 
 25 int main()  26 {  27  LinkStack p;  28     char ch;  29 
 30     p.height = 0;        /* 棧高度初始化為零 */
 31     p = InitStack (p); /* 棧初始化 */
 32     printf("Do you want to push stack(Y/N)?");  33     scanf(" %c", &ch);  34     while (ch == 'Y' || ch == 'y')  35  {  36         p = Push(p);    /* 入棧 */
 37         DisplyStack(p);    /* 遍歷棧 */
 38         printf("Do you want to push stack(Y/N)?");  39         scanf(" %c", &ch);  40  }  41     printf("Do you want to pop stack(Y/N)?");  42     scanf(" %c", &ch);  43     while (ch == 'Y' || ch == 'y')  44  {  45         p = Pop(p);        /* 出棧 */
 46         DisplyStack(p);    /* 遍歷棧 */
 47         printf("Do you want to pop stack(Y/N)?");  48         scanf(" %c", &ch);  49  }  50 
 51     return 0;  52 }  53 /* Function: 初始化棧頂、棧底、棧高度*/
 54 LinkStack InitStack (LinkStack pStack)  55 {  56     pStack.top = pStack.bottom = NULL;  57     pStack.height = 0;  58 
 59     return pStack;  60 }  61 
 62 /* Function: 判斷棧是否為空 */
 63 int StackEmpty (LinkStack pStack)  64 {  65     if (pStack.top == NULL && pStack.bottom == NULL)  66  {  67         return Empty;  68  }  69     else
 70  {  71         return Avail;  72  }  73 }  74 
 75 /* Function: 入棧 */
 76 LinkStack Push (LinkStack pStack)  77 {  78     int data;  79     StackNode *temp;  80 
 81     if ((temp = (StackNode *)malloc(sizeof(StackNode))) == NULL)  82  {  83         printf("內存空間不足\n");  84         return pStack;  85  }  86     if (StackEmpty(pStack) == Empty)    /* 如果棧為空 */
 87  {  88         pStack.top = pStack.bottom = temp;    /* 棧頂、棧底指針都指向新建節點 */
 89         temp->next = NULL;                /* 節點指針域為空 */
 90         printf("Please input data");  91         scanf("%d", &data);  92         pStack.top->data = data;  93         pStack.height++;  94 
 95         return pStack;  96  }  97     else        /* 棧不為空 */
 98  {  99         temp->next = pStack.top;/* 新建節點指向原來的棧頂 */
100         pStack.top = temp;        /* 棧頂指針指向新建節點 */
101         printf("Please input data"); 102         scanf("%d", &data); 103         pStack.top->data = data; 104         pStack.height++; 105 
106         return pStack; 107  } 108 } 109 
110 /* Function: 出棧 */
111 LinkStack Pop (LinkStack pStack) 112 { 113     StackNode *Second; 114 
115     
116     if (StackEmpty(pStack) == Empty)    /* 判斷棧是否為空 */
117  { 118         printf("棧為空,無法出棧\n"); 119         return pStack; 120  } 121     if (pStack.top == pStack.bottom)    /* 如果出棧的元素為最后一個元素 */
122  { 123         printf("出棧元素為%d\n", pStack.top->data); 124         free(pStack.top); 125         pStack.top = pStack.bottom = NULL; /* 棧頂、棧底都指針都置為空 */
126         pStack.height--; 127 
128         return pStack; 129  } 130     printf("出棧元素為%d\n", pStack.top->data); 131     Second = pStack.top->next;    /* 指向棧頂的前一個元素*/
132 
133     free(pStack.top);    /* 釋放棧頂節點 */
134     pStack.top = Second;/* 將頭指針移動到新的棧頂節點 */
135     pStack.height--; 136 
137     return pStack; 138 } 139 
140 /* Function: 遍歷棧 自頂到底*/
141 void DisplyStack (LinkStack pStack) 142 { 143     if (StackEmpty(pStack) == Empty) 144  { 145         printf("棧為空,無法遍歷\n"); 146         return ; 147  } 148     printf("棧中元素["); 149     while (pStack.top != NULL) 150  { 151         printf("%d->", pStack.top->data); 152         pStack.top = pStack.top->next; 153  } 154     printf("]\n"); 155 } 156 
157 /* Function: 清空棧 */
158 LinkStack DeletStack (LinkStack pStack) 159 { 160     StackNode *del; 161 
162     while (pStack.top != NULL) 163  { 164         del = pStack.top->next;    /* 棧頂節點的前一個節點 */
165         free(pStack.top);        /* 釋放節點 */
166         pStack.top = del;        /* 棧頂指針移動到新棧頂 */
167  } 168 
169     return pStack; 170 }

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM