😎博客昵称:博客小梦
😊最喜欢的座右铭:全神贯注的上吧!!!
😊作者简介:一名热爱C/C++,算法等技术、喜爱运动、热爱K歌、敢于追梦的小博主!
😘博主小留言:哈喽!😄各位CSDN的uu们,我是你的博客好友小梦,希望我的文章可以给您带来一定的帮助,话不多说,文章推上!欢迎大家在评论区唠嗑指正,觉得好的话别忘了一键三连哦!😘
前言🙌
哈喽各位友友们😊,我今天又学到了很多有趣的知识,现在迫不及待的想和大家分享一下!😘我仅已此文,手把手带领大家详解C语言实现链栈~ 要是为了运用所学的链表的相关知识和算法。用代码来实现链栈,也就是用链表来实现栈。都是精华内容,可不要错过哟!!!😍😍😍
整体实现内容分析💞
在使用链表来实现链栈时,可以针对栈只在栈顶上后进先出的特点,找什么样的链表实现比较好。我通过比较后觉得采用单链表的结构,然后链表的首节点放在栈顶上。后面只需对首节点进行插入和删除即可。首先建立链表结构体,然后建立队列结构体,里面定义一个指向链表首节点的指head。然后依次实现栈的初始化,销毁,入栈,出栈,取栈顶元素,判断栈是否为空,栈上的元素个数,遍历栈上元素等这些基本功能。
1.头文件编码实现🙌
头文件的编写的整体思路分析:
这里是有关头文件的编写和各种功能函数的声明,首先用typedef关键字给存储数据类型取别名,这样做的好处是以后想要改变栈的数据类型只需修改typedef int StDatetype;里的int即可。定义两个结构体,一个是链表的,一个是栈的。
#pragma once #include<stdio.h> #include<stdlib.h> #include<assert.h> #include<stdbool.h> typedef int StDatetype; typedef struct StackNode { struct StackNode* next; StDatetype data; }ST; typedef struct Stack { ST* head; }Stack; //初始化 void StackInit(ST* ps); //销毁 void StackDestory(ST* ps); //入栈 void StackPush(ST* ps, StDatetype x); //出栈 void StackPop(ST* ps); //栈上的数据个数 int StackSize(ST* ps); //栈顶元素 StDatetype StackTop(ST* ps); //判空 bool StackEmpty(ST* ps);
2.功能文件编码实现🙌
功能文件的编写的整体思路分析:
这里是功能文件的编写,在涉及到指针的地方,我都用了assert确保指针有效性,在free掉指针时,需要把指针置为空指针,避免野指针的问题。第一个是初始化函数,第二个是销毁函数实现。其中需要注意的是入栈和出栈的编写。入栈时,先用malloc函数动态申请一个空间,然后判断以下有没有开辟成功。需要注意的是,需要把newnode置为NULL,防止野指针的问题出现。然后将newnode的next指针指向head,然后让head指向newnode,这样就把元素入栈了。还有一种特殊情况是本来就是空的栈,则新生成的newnode就是head。出栈函数实现,需要定义一个next指针指向head下一个,确保把栈顶元素删除后,还能找到后面的元素。Free掉记得把指针置为NULL。其他函数没什么难点,注意以上几个点即可实现以下函数。
#include"Stack.h" //初始化 void StackInit(Stack* ps) { assert(ps); ps->head = NULL; } //销毁 void StackDestory(Stack* ps) { assert(ps); ST* cur = ps->head; while (cur) { ST* next = cur->next; free(cur); cur = next; } ps->head = NULL; } //入栈 void StackPush(Stack* ps, StDatetype x) { assert(ps); ST* newnode = (ST*)malloc(sizeof(ST)); if (newnode ==NULL) { printf("malloc fail\n"); exit(-1); } newnode->data = x; newnode->next = NULL; if (ps->head == NULL) { ps->head = newnode; } else { newnode->next = ps->head; ps->head = newnode; } } //出栈 void StackPop(Stack* ps) { assert(ps); assert(!StackEmpty(ps)); if (ps->head->next == NULL) { free(ps->head); ps->head = NULL; } else { ST* next = ps->head->next; free(ps->head); ps->head = next; } } //栈上的数据个数 int StackSize(Stack * ps) { assert(ps); int size = 0; ST* cur = ps->head; while (cur) { size++; cur = cur->next; } return size; } //栈顶元素 StDatetype StackTop(Stack* ps) { assert(ps); assert(!StackEmpty(ps)); return ps->head->data; } bool StackEmpty(Stack* ps) { assert(ps); return ps->head == NULL; }
3.测试函数功能代码🙌
#include"Stack.h" void Test1() { Stack s; StackInit(&s); StackPush(&s, 1); StackPush(&s, 2); StackPush(&s, 3); StackPush(&s, 4); printf("栈上的元素个数:%d\n", StackSize(&s)); printf("栈顶元素:%d\n", StackTop(&s)); if (StackEmpty(&s)) { printf("栈空\n"); } else { printf("栈不为空\n"); } printf("入栈输入顺序为1234,出栈顺序输出:\n"); while (!StackEmpty(&s)) { printf("%d", StackTop(&s)); StackPop(&s); } printf("\n"); if (StackEmpty(&s)) { printf("栈空\n"); } else { printf("栈不为空\n"); } StackDestory(&s); printf("\n"); } int main() { Test1(); return 0; }
功能测试结果展示图:
总结撒花💞
本篇文章旨在分享详解C语言实现链栈。希望大家通过阅读此文有所收获!本次关于栈的实现相对于之前链表的实现简单一点,指针的指向没有那么复杂,主要是对入栈和出栈的功能实现。但也有很多地方需要注意的。比如说,野指针的问题,动态开辟的空间一定要free掉,并且把指针置为NULL。用动态实现,相对于静态实现还比较灵活,也能对空间有很大的节省。
😘如果我写的有什么不好之处,请在文章下方给出你宝贵的意见😊。如果觉得我写的好的话请点个赞赞和关注哦~😘😘😘