追梦之旅【数据结构篇】——详解C语言实现链栈

简介: 详解C语言实现链栈~😎前言🙌整体实现内容分析💞1.头文件编码实现🙌2.功能文件编码实现🙌3.测试函数功能代码🙌总结撒花💞

微信图片_20230427214238.gif

😎博客昵称:博客小梦

😊最喜欢的座右铭:全神贯注的上吧!!!

😊作者简介:一名热爱C/C++,算法等技术、喜爱运动、热爱K歌、敢于追梦的小博主!

😘博主小留言:哈喽!😄各位CSDN的uu们,我是你的博客好友小梦,希望我的文章可以给您带来一定的帮助,话不多说,文章推上!欢迎大家在评论区唠嗑指正,觉得好的话别忘了一键三连哦!😘

微信图片_20230427160707.gif


前言🙌



   哈喽各位友友们😊,我今天又学到了很多有趣的知识,现在迫不及待的想和大家分享一下!😘我仅已此文,手把手带领大家详解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;
}


功能测试结果展示图:

微信图片_20230427215609.png


总结撒花💞


本篇文章旨在分享详解C语言实现链栈。希望大家通过阅读此文有所收获!本次关于栈的实现相对于之前链表的实现简单一点,指针的指向没有那么复杂,主要是对入栈和出栈的功能实现。但也有很多地方需要注意的。比如说,野指针的问题,动态开辟的空间一定要free掉,并且把指针置为NULL。用动态实现,相对于静态实现还比较灵活,也能对空间有很大的节省。

  😘如果我写的有什么不好之处,请在文章下方给出你宝贵的意见😊。如果觉得我写的好的话请点个赞赞和关注哦~😘😘😘


相关文章
|
18天前
|
C语言
【数据结构】栈和队列(c语言实现)(附源码)
本文介绍了栈和队列两种数据结构。栈是一种只能在一端进行插入和删除操作的线性表,遵循“先进后出”原则;队列则在一端插入、另一端删除,遵循“先进先出”原则。文章详细讲解了栈和队列的结构定义、方法声明及实现,并提供了完整的代码示例。栈和队列在实际应用中非常广泛,如二叉树的层序遍历和快速排序的非递归实现等。
95 9
|
18天前
|
存储 搜索推荐 算法
【数据结构】树型结构详解 + 堆的实现(c语言)(附源码)
本文介绍了树和二叉树的基本概念及结构,重点讲解了堆这一重要的数据结构。堆是一种特殊的完全二叉树,常用于实现优先队列和高效的排序算法(如堆排序)。文章详细描述了堆的性质、存储方式及其实现方法,包括插入、删除和取堆顶数据等操作的具体实现。通过这些内容,读者可以全面了解堆的原理和应用。
60 16
|
17天前
|
C语言
【数据结构】二叉树(c语言)(附源码)
本文介绍了如何使用链式结构实现二叉树的基本功能,包括前序、中序、后序和层序遍历,统计节点个数和树的高度,查找节点,判断是否为完全二叉树,以及销毁二叉树。通过手动创建一棵二叉树,详细讲解了每个功能的实现方法和代码示例,帮助读者深入理解递归和数据结构的应用。
66 8
|
20天前
|
存储 C语言
【数据结构】手把手教你单链表(c语言)(附源码)
本文介绍了单链表的基本概念、结构定义及其实现方法。单链表是一种内存地址不连续但逻辑顺序连续的数据结构,每个节点包含数据域和指针域。文章详细讲解了单链表的常见操作,如头插、尾插、头删、尾删、查找、指定位置插入和删除等,并提供了完整的C语言代码示例。通过学习单链表,可以更好地理解数据结构的底层逻辑,提高编程能力。
48 4
|
21天前
|
存储 C语言
【数据结构】顺序表(c语言实现)(附源码)
本文介绍了线性表和顺序表的基本概念及其实现。线性表是一种有限序列,常见的线性表有顺序表、链表、栈、队列等。顺序表是一种基于连续内存地址存储数据的数据结构,其底层逻辑是数组。文章详细讲解了静态顺序表和动态顺序表的区别,并重点介绍了动态顺序表的实现,包括初始化、销毁、打印、增删查改等操作。最后,文章总结了顺序表的时间复杂度和局限性,并预告了后续关于链表的内容。
56 3
|
22天前
|
存储 算法 C语言
C语言数据结构(2)
【10月更文挑战第21天】
|
20天前
|
C语言
【数据结构】双向带头循环链表(c语言)(附源码)
本文介绍了双向带头循环链表的概念和实现。双向带头循环链表具有三个关键点:双向、带头和循环。与单链表相比,它的头插、尾插、头删、尾删等操作的时间复杂度均为O(1),提高了运行效率。文章详细讲解了链表的结构定义、方法声明和实现,包括创建新节点、初始化、打印、判断是否为空、插入和删除节点等操作。最后提供了完整的代码示例。
39 0
|
存储 缓存 C语言
数据结构——双链表(C语言)
数据结构——双链表(C语言)
|
5月前
|
存储
数据结构——双向链表(C语言版)
数据结构——双向链表(C语言版)
31 2
|
5月前
|
算法 C语言
数据结构——单向链表(C语言版)
数据结构——单向链表(C语言版)
46 2