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