棧(鏈式棧)----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 }
棧(鏈式棧)----C語言