栈(链式栈)----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 }

 

 

 

 

posted @ 2019-03-05 22:16  Luv3  阅读(9518)  评论(3编辑  收藏  举报