1. 程式人生 > >棧(鏈式棧)----C語言

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

logs links htm mil 等於 sizeof 回顧 ont efi

技術分享圖片

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

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

 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語言