详解C语言实现链栈~😎
- 前言🙌
- 整体实现内容分析💞
- 1.头文件编码实现🙌
- 2.功能文件编码实现🙌
- 3.测试函数功能代码🙌
- 总结撒花💞
😎博客昵称:博客小梦
😊最喜欢的座右铭:全神贯注的上吧!!!
😊作者简介:一名热爱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。用动态实现,相对于静态实现还比较灵活,也能对空间有很大的节省。
😘如果我写的有什么不好之处,请在文章下方给出你宝贵的意见😊。如果觉得我写的好的话请点个赞赞和关注哦~😘😘😘