首页 > 其他分享 >使用C语言实现链式栈

使用C语言实现链式栈

时间:2024-06-05 17:00:50浏览次数:25  
标签:结点 实现 元素 栈顶 head stk 链式 C语言 size

一、栈的基本概念

        栈(Stack)是一种数据结构,它遵循“后进先出”(LIFO, Last In First Out)的原则。这意味着最后一个插入栈的元素最先被删除,你可以理解成一堆盘子,每次只能取最上面的盘子,删除的时候也只能删除最上面的盘子。这样是不是更容易理解了呢?栈的基本操作包括:

  1. 入栈(Push):将一个元素压入栈顶。
  2. 出栈(Pop):将栈顶元素弹出并返回该元素。
  3. 查看栈顶元素(Top):返回栈顶元素的值,但不弹出该元素。
  4. 获取栈的大小(Size):返回栈中元素的个数。
  5. 栈的创建和销毁:创建一个新的空栈并初始化,销毁栈时释放所有元素的内存。

栈有两种主要的实现方式:数组(顺序栈)和链表(链式栈)。本文将重点介绍链式栈的实现方式。

二、链式栈的实现

        链式栈利用链表实现,栈顶对应链表的头结点。每个结点包含一个数据域和一个指向下一个结点的指针。栈的操作在链表的头部进行,具体来说:

  • 入栈操作:每次添加新元素时,新元素成为链表的头结点。新的头结点指向原来的头结点。
  • 出栈操作:每次删除元素时,删除的是链表的头结点。删除后,原头结点的下一个结点成为新的头结点。

三、栈的结构定义

我们首先定义栈中元素的类型,以及链表结点和栈的结构体。

#include <stdio.h>
#include <stdlib.h>

// 定义栈中元素的类型
#define eleType int

// 定义链表结点的结构体
typedef struct Node 
{	
    eleType data;        // 数据域
    struct Node* next;   // 指针域
} Node;

// 定义栈的结构体
typedef struct
{
    Node* head;          // 栈顶指针
    size_t size;         // 栈的大小
} stack;
  • eleType 定义了栈中元素的类型,这里我们定义为 int 类型。你可以根据需要修改为其他类型。
  • Node 结构体表示链表的结点,每个结点包含一个数据域和一个指向下一个结点的指针。
  • stack 结构体表示栈,包含一个指向栈顶结点的指针 head 和栈的大小 size

四、栈的创建

栈的创建函数用于初始化栈,使其处于空状态。

// 栈的创建函数
void StackCreate(stack* stk)
{
    stk->head = NULL;    // 初始化栈顶指针为NULL
    stk->size = 0;       // 初始化栈的大小为0
}
  • StackCreate 函数接收一个指向 stack 结构体的指针 stk,将 stkhead 初始化为 NULL,表示栈为空。
  • 同时,将 stksize 初始化为 0,表示栈的元素个数为零。

五、栈的销毁

栈的销毁函数用于释放栈中所有结点的内存,并将栈重置为初始状态。

// 栈的销毁函数
void StackDestroy(stack* stk)
{
    while (stk->head)    // 从头结点开始遍历,直到空结点
    {
        Node* next = stk->head->next; // 将头结点的后继结点存入到next变量中
        free(stk->head);              // 释放头结点所占空间
        stk->head = next;             // 将栈的头结点更新为next
    }
    stk->size = 0;       // 重置栈的大小为0
}
  • StackDestroy 函数接收一个指向 stack 结构体的指针 stk,循环遍历栈中的每个结点。
  • 在循环中,保存当前结点的下一个结点指针,释放当前结点的内存,然后将栈顶指针 head 更新为下一个结点。
  • 最后,将 size 重置为 0,表示栈已被清空。

六、入栈操作

入栈操作将一个新元素添加到栈顶。(一盘碟子上面加碟子doge~)

// 入栈函数
void StackPush(stack* stk, eleType element)
{
    Node* newNode = (Node*)malloc(sizeof(Node)); // 创建动态链表结点
    newNode->data = element;  // 将元素element赋值给data成员变量
    newNode->next = stk->head; // 将next结点指向栈当前的头结点
    stk->head = newNode;       // 更新头结点为newNode
    stk->size++;               // 更新栈的大小加1
}
  • StackPush 函数接收一个指向 stack 结构体的指针 stk 和一个元素 element
  • 创建一个新的结点 newNode,将 element 赋值给 newNode 的数据域 data
  • newNode 的指针域 next 指向当前的栈顶结点 head
  • stkhead 更新为 newNode,表示新结点成为栈顶。
  • size 加1,更新栈的大小。

七、出栈操作

出栈操作将栈顶元素移除,并返回该元素的值。(把最上面的碟子取下来doge~)

// 出栈函数
eleType StackPop(stack* stk)
{
    if (stk->size == 0)
    {
        printf("Stack underflow!\n");
        exit(1);    // 判断栈是否为空,如果为空,退出程序
    }
    
    eleType result = stk->head->data;  // 获取栈顶元素
    Node* next = stk->head->next;      // 保存下一个结点
    free(stk->head);                   // 释放当前栈顶结点
    stk->head = next;                  // 更新栈顶指针
    stk->size--;                       // 栈的大小减1
    return result;                     // 返回栈顶元素
}
  • StackPop 函数接收一个指向 stack 结构体的指针 stk
  • 首先检查栈是否为空,如果 size0,打印错误信息并退出程序。
  • 获取当前栈顶元素的数据域 data 并保存到 result
  • 保存当前栈顶结点的下一个结点指针 next
  • 释放当前栈顶结点的内存。
  • stkhead 更新为 next,即栈顶指针指向下一个结点。
  • size 减1,更新栈的大小。
  • 返回保存的栈顶元素 result

八、获取栈顶元素

该函数用于返回栈顶元素的值,但不移除该元素。

// 获取栈顶元素函数
eleType StackTop(stack* stk)
{
    if (stk->size == 0)
    {
        printf("Stack is empty!\n");
        exit(1);    // 判断栈是否为空,如果为空,退出程序
    }
    return stk->head->data;   // 返回栈顶元素
}
  • StackTop 函数接收一个指向 stack 结构体的指针 stk
  • 首先检查栈是否为空,如果 size0,打印错误信息并退出程序。
  • 返回当前栈顶结点的数据域 data

九、获取栈的大小

该函数用于返回栈中元素的个数。

// 获取栈的大小函数
int StackSize(stack* stk)
{
    return stk->size;    // 返回栈的大小
}
  • StackSize 函数接收一个指向 stack 结构体的指针 stk
  • 返回栈的大小 size

十、示例代码

我们通过一个示例来展示如何使用上述函数来操作栈。

int main() 
{
    stack stk;
    StackCreate(&stk);

    StackPush(&stk, 10);
    StackPush(&stk, 20);
    StackPush(&stk, 30);

    printf("Stack top element: %d\n", StackTop(&stk));
    printf("Stack size: %d\n", StackSize(&stk));

    printf("Popped element: %d\n", StackPop(&stk));
    printf("Stack top element: %d\n", StackTop(&stk));
    printf("Stack size: %d\n", StackSize(&stk));

    StackDestroy(&stk);
    printf("Stack size after destroy: %d\n", StackSize(&stk));

    return 0;
}
  • 创建一个栈 stk 并初始化。
  • 10, 20, 30 三个元素依次压入栈。
  • 获取并打印栈顶元素和栈的大小。
  • 弹出一个元素并打印弹出的元素、当前栈顶元素和栈的大小。
  • 销毁栈并打印销毁后的栈的大小。

输出结果:

Stack top element: 30
Stack size: 3
Popped element: 30
Stack top element: 20
Stack size: 2
Stack size after destroy: 0

总结 

        通过定义链表结点和栈结构体,我们能够创建、销毁、入栈、出栈、查看栈顶元素以及获取栈的大小。使用链表实现栈的关键在于对头结点的操作:

  • 入栈:每次添加新元素时,我们创建一个新的结点并将其设为新的头结点,新结点指向原来的头结点。
  • 出栈:每次删除元素时,我们删除当前的头结点,更新头结点为下一个结点。

这种实现方式充分利用了链表的动态内存分配特性,使得栈操作简单且高效。

希望对大家有所帮助,求赞支持一下~

标签:结点,实现,元素,栈顶,head,stk,链式,C语言,size
From: https://blog.csdn.net/Broken_x/article/details/139476146

相关文章

  • C++PrimerPlus第十一章类的使用 :练习7 复数类的实现和重载运算符对复数做运算----本
    复数有两个部分组成:实数部分和虚数部分。复数的一种书写方式是:(3.0,4.0),其中,3.0是实数部分,4.0是虚数部分。假设a=(A,Bi),c=(C,Di),则下面是一些复数运算。加法:a+c=(A+C,(B+D)i)。减法:a-c=(A-C,(B-D)i)。乘法:ac=(AC-BD,(AD+B*C)i)。乘法::xc=(xC,x*Di),其中x为实数。......
  • 接上篇,客户端实现,图形界面编程,利用socket和UCP/TCP编写,客户端和服务器端程序可以进行
     1.项目结构 1.1基本架构本项目采用基于Java的`Swing`库进行图形界面开发,并使用`Socket`进行网络通信。项目包名为`org.example.tcp`。 1.2模块划分项目主要分为以下几个模块:图形用户界面(GUI)模块网络通信模块线程处理模块 2.GUI设计 2.1主窗口设计 2.1.1......
  • 【C语言】文件操作强化
    【C语言】文件操作强化文章目录【C语言】文件操作强化前言一、文件打开关闭文件打开(fopen)文件关闭(fclose)二、文件读写函数字符读写函数行读写函数块读写函数格式化读写函数随机读写函数三、文件读写注意事项四、配置文件读写案例总结前言本篇文章我们将详细......
  • sqlserver 通过压缩bak文件实现从服务器还原数据库《数据差异数个小时》
    十年河东,十年河西,莫欺少年穷学无止境,精益求精1、备份主服务器数据库并压缩publicvoidDbBack(){varbakname=@"ChargeDB_"+DateTime.Now.ToString("yyyyMMdd")+".bak";stringfilepath=@"D:\dbback\"+bakna......
  • Java基于SSM的医院医患管理系统设计实现
    21世纪的今天,随着社会的不断发展与进步,人们对于信息科学化的认识,已由低层次向高层次发展,由原来的感性认识向理性认识提高,管理工作的重要性已逐渐被人们所认识,科学化的管理,使信息存储达到准确、快速、完善,并能提高工作管理效率,促进其发展。论文主要是对医院医患管......
  • Java基于SSM的员工信息管理系统设计实现
    现代经济快节奏发展以及不断完善升级的信息化技术,让传统数据信息的管理升级为软件存储,归纳,集中处理数据信息的管理方式。本龙腾公司员工信息管理系统就是在这样的大环境下诞生,其可以帮助管理者在短时间内处理完毕庞大的数据信息,使用这种软件工具可以帮助管理人员提高......
  • Java基于SSM的图书管理系统设计实现
    现代经济快节奏发展以及不断完善升级的信息化技术,让传统数据信息的管理升级为软件存储,归纳,集中处理数据信息的管理方式。本图书管理系统就是在这样的大环境下诞生,其可以帮助管理者在短时间内处理完毕庞大的数据信息,使用这种软件工具可以帮助管理人员提高事务处理效率,......
  • Java基于SSM的在线购物系统设计实现
    随着科学技术的飞速发展,各行各业都在努力与现代先进技术接轨,通过科技手段提高自身的优势:对于在线购物系统当然也不能排除在外,随着网络技术的不断成熟,带动了在线购物系统,它彻底改变了过去传统的管理方式,不仅使服务管理难度变低了,还提升了管理的灵活性。这种个性化的平......
  • (手把手实现)Comsol如何调用MATLAB函数
    运行comsol仿真时,有时为了让某一个量按照自己设置的规则变化,可能需要用到自己编写的MATLAB函数。如何在comsol里调用MATLAB函数呢?解决措施:0️⃣确保comsol软件的“文件”——>首选项——>安全性——>允许外部MATLAB®函数为“是”。1️⃣成功在MATLAB里编写函数,有函数名称、输入......
  • 基于Android的校园自由贸易系统设计与实现
    临近毕业,许多毕业生都要在离校之前清理自己的物品。以前大多数学生会选择丢弃,造成了资源的大量浪费。而近几年,二手交易市场在校园中如雨后春笋般发展,书籍和某些耐用品一般通过二手交易市场或二手群交易。前者流程繁琐,耗时耗力。后者商品质量,售后得不到保障,还容易因为交涉不清引......