• 栈(链式栈)----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("内存空间不足
    ");
    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("栈为空,无法出栈
    ");
    10         return pStack;
    11     }
    12     if (pStack.top == pStack.bottom)    /* 如果出栈的元素为最后一个元素 */
    13     {
    14         printf("出栈元素为%d
    ", pStack.top->data);
    15         free(pStack.top);
    16         pStack.top = pStack.bottom = NULL; /* 栈顶、栈底都指针都置为空 */
    17         pStack.height--;
    18 
    19         return pStack;
    20     }
    21     printf("出栈元素为%d
    ", 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("栈为空,无法遍历
    ");
     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("]
    ");
    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("内存空间不足
    ");
     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("栈为空,无法出栈
    ");
    119         return pStack;
    120     }
    121     if (pStack.top == pStack.bottom)    /* 如果出栈的元素为最后一个元素 */
    122     {
    123         printf("出栈元素为%d
    ", pStack.top->data);
    124         free(pStack.top);
    125         pStack.top = pStack.bottom = NULL; /* 栈顶、栈底都指针都置为空 */
    126         pStack.height--;
    127 
    128         return pStack;
    129     }
    130     printf("出栈元素为%d
    ", 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("栈为空,无法遍历
    ");
    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("]
    ");
    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 }

     

  • 相关阅读:
    Spring面试,IoC和AOP的理解
    WEB打印(jsp版)
    Spring事务管理机制的实现原理-动态代理
    spring面试题
    oracle PLSQL基础学习
    oracle创建表空间
    WM_CONCAT字符超过4000的处理办法
    Oracle 数据泵使用详解
    Oracle 数据泵详解
    linux下启动oracle
  • 原文地址:https://www.cnblogs.com/lanhaicode/p/10463156.html
Copyright © 2020-2023  润新知