学科分类
目录
数据结构

栈的链式存储实现

栈的链式存储也称为链栈,它和链表的存储原理一样,都可以利用闲散空间来存储元素,用指针来建立各结点之间的逻辑关系。链栈也会设置一个栈顶元素的标识符top,称为栈顶指针。它和链表的区别是,只能在一端进行各种操作。如图1所示。

图1 链栈

链栈就是一个单端操作的链表,它的插入删除操作就是在链表的一端进行。接下来我们就来实现一个链栈,其功能如下:

● 创建一个链栈。

● 判断链栈是否为空。

● 压栈、弹栈。

● 获取栈顶元素。

● 销毁链栈。

然后在main.c文件中完成此链栈的测试,具体如例1所示。

例1

linkstack.h //头文件

 1    #ifndef _LINKSTACK_H_
 2    #define _LINKSTACK_H_
 3    
 4    typedef struct Node * pNode;
 5    typedef struct Stack * LinkStack;
 6    struct Node //数据结点
 7    {
 8        int data;                              //数据
 9        pNode next;                         //指针
 10    };
 11    
 12    struct Stack  //此结构记录栈的大小和栈顶元素指针
 13    {
 14        pNode top;                             //栈顶元素指针
 15        int size;                             //栈大小
 16    };
 17    
 18    LinkStack Create();                     //创建栈
 19    int IsEmpty(LinkStack lstack);             //判断栈是否为空
 20    int getSize(LinkStack lstack);             //获取栈的大小
 21    int Push(LinkStack lstack, int val);     //元素入栈
 22    pNode getTop(LinkStack lstack);         //获取栈顶元素
 23    pNode Pop(LinkStack lstack);             //弹出栈顶元素
 24    void Destory(LinkStack lstack);         //销毁栈
 25    
 26    #endif

linkstack.c //操作函数实现文件

 27    #include "linkstack.h"
 28    #include <stdio.h>
 29    #include <stdlib.h>
 30    
 31    LinkStack Create() //创建栈
 32    {
 33        LinkStack lstack = (LinkStack)malloc(sizeof(struct Stack)); 
 34        if (lstack != NULL)
 35        {
 36            lstack->top = NULL;
 37            lstack->size = 0;
 38        }
 39        return lstack;
 40    }
 41    
 42    int IsEmpty(LinkStack lstack) //判断栈是否为空
 43    {
 44        if (lstack->top == NULL || lstack->size == 0)
 45            return 1;
 46        return 0;
 47    }
 48    
 49    int getSize(LinkStack lstack) 
 50    {
 51        return lstack->size;                                 //获取栈的大小
 52    }
 53    
 54    int Push(LinkStack lstack, int val)
 55    {
 56        pNode node = (pNode)malloc(sizeof(struct Node));     //为元素val分配结点
 57        if (node != NULL)
 58        {
 59            node->data = val; 
 60            node->next = getTop(lstack);         //新元素结点指向下一个结点,链式实现
 61            lstack->top = node;                 //top指向新结点
 62            lstack->size++;
 63        }
 64        return 1;
 65    }
 66    
 67    pNode getTop(LinkStack lstack)                 //获取栈顶元素
 68    {
 69        if (lstack->size != 0)
 70            return lstack->top;
 71        return NULL;
 72    }
 73    
 74    pNode Pop(LinkStack lstack)                 //弹出栈顶元素
 75    {
 76        if (IsEmpty(lstack))
 77        {
 78            return NULL;
 79        }
 80        pNode node = lstack->top;                 //node指向栈顶元素
 81        lstack->top = lstack->top->next;         //top指向下一个元素
 82        lstack->size--;
 83        return node;
 84    }
 85    
 86    
 87    void Destory(LinkStack lstack)                 //销毁栈
 88    {
 89        if (IsEmpty(lstack))
 90        {
 91            free(lstack);
 92            printf("栈已为空,不必再行销毁!\n");
 93            return;
 94        }
 95        //如果栈不为空,需要把栈中的结点都删除释放
 96        do
 97        {
 98            pNode pTmp;
 99            pTmp = Pop(lstack);
 100            free(pTmp);
 101        }while (lstack->size > 0);
 102        printf("栈销毁成功!\n");
 103    }

main.c //测试文件

 104    #include <stdio.h>
 105    #include <stdlib.h>
 106    #include "linkstack.h"
 107    
 108    int main()
 109    {
 110        srand((unsigned)time(0));
 111        LinkStack lstack = NULL;
 112        lstack = Create();                     //创建一个栈
 113    
 114        //判断栈是否为空
 115        int ret;
 116        ret = IsEmpty(lstack);
 117        if (ret)
 118            printf("栈为空!\n");
 119        else
 120            printf("栈不为空!\n");
 121    
 122        //向栈中插入元素
 123        for (int i = 0; i < 10; i++)
 124        {
 125            Push(lstack, rand() % 100); //插入的是随机产生的数
 126        }
 127    
 128        //再次判断栈是否为空
 129        ret = IsEmpty(lstack);
 130        if (ret)
 131            printf("栈为空!\n");
 132        else
 133            printf("栈不为空!\n");
 134    
 135        //求栈的长度
 136        printf("栈的长度:%d\n", getSize(lstack));
 137    
 138        //获取栈顶元素
 139        //返回的是pNode结点类型,要转换为int类型
 140        printf("栈顶元素:%d\n", *((int*)getTop(lstack))); 
 141    
 142        //打印栈中的元素
 143        while (lstack->size > 0)
 144        {
 145             //Pop()返回的是pnode结点类型,也要转换为int类型
 146            printf("%d  ", *((int*)Pop(lstack))); 
 147        }
 148        printf("\n");
 149    
 150        //销毁栈
 151        Destory(lstack);
 152    
 153        system("pause");
 154        return 0;
 155    }

运行结果如图2所示。

图2 例1运行结果

在例1中,代码6-16行定义了链栈的数据结点与头结点,这与链表的定义方式相同,但有时在链栈的实现中,通常不定义头结点,而是直接把栈顶放在单链表的头部。

创建好栈之后,先调用IsEmpty()函数判断栈是否为空,结合代码,由图3-7中的代码执行结果可知:初始时栈为空;代码123-126行,向栈中存入元素,再次进行判断时,由图3-7可知,,此时栈不为空;代码136行中代码输出栈的长度为10;代码140行求栈顶元素,由图3-7可知此时栈顶元素为46;代码143-147行打印栈中的元素,即将元素逐一弹出。由代码可知,栈中的元素是随机产生的数,由图中输出结果可知,第一个元素为46,与求得的栈顶元素相同;代码151行销毁栈,因为在打印时已经将栈中元素全部弹出,所以在销毁之时栈已空,等同已经销毁。

点击此处
隐藏目录