栈的链性表的c语言实现方式 linkstack.h 和 linkstack.c

2023-11-06

linkstack.h 文件

#ifndef _LINK_STACK_H_
#define _LINK_STACK_H_
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//用线性表的链式存储模拟栈的链式存储,在头部插入删除元素不会涉及大量元素移动
typedef void Stack;

//把业务节点弄到底层,只需传入业务数据指针,在底层函数中
//把业务数据整合到链表一格中,void* item中,不用用户自己搞链表的业务节点了
typedef struct _tag_LinkStackNode{
    LinkListConnectedNode node;  //关系节点
    void* item;         //存业务数据
}LinkStackNode; 

#ifndef bool
#define bool int
#define true 1
#define false 0
#endif

Stack* LinkStack_Create();
bool LinkStack_Destory(Stack* stack);
bool LinkStack_Clear(Stack* stack);
bool LinkStack_Push(Stack* stack, void* item);
void* LinkStack_Pop(Stack* stack);
void* LinkStack_Top(Stack* stack);
int LinkStack_GetSize(Stack* stack);
#endif

linkstack.c 文件

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "linklist.h"
#include "linkstack.h"
//注意栈的业务节点嵌套在链表一格的节点中的
//通过底层函数把用户的业务数据通过指针整合到栈的业务节点中
//实际栈只是链表一格业务节点的一个域而已


//创建一个栈的链式存储相当于创建一个线性表的链式存储
Stack* LinkStack_Create()
{
    return LinkList_Create();
}

//销毁栈相当于销毁链表
bool LinkStack_Destory(Stack* stack)
{
    bool ret;
    //先清空栈
    ret = LinkStack_Clear(stack);
    if (ret == false)
    {
        return false;
    }
    //销毁链表
    ret = LinkList_Destory(stack);
    if (ret == false)
    {
        return false;
    }
    return true;
}

//清空栈的时候涉及到栈元素生命周期的管理
//注意所有栈的元素都是malloc出来的
//要把所有元素弹出,并且释放内存
bool LinkStack_Clear(Stack* stack)
{
    if (stack == NULL)
    {
        return false;
    }
    while(LinkStack_GetSize(stack) > 0)
    {
        LinkStack_Pop(stack);   //在这个函数中释放内存了
    }
    return true;
}

//向栈添加元素相当于向链表头部插入元素
//栈的业务节点void* item转化为链表的业务节点ListNode* listnode
bool LinkStack_Push(Stack* stack, void* item)
{
    LinkStackNode* linkstackdata = NULL;
    bool ret;
    linkstackdata = (LinkStackNode*)malloc(sizeof(LinkStackNode));
    if (linkstackdata == NULL)
    {
        return false;
    }
    memset(linkstackdata,0,sizeof(LinkStackNode));
    //先创建出链表一格,链表一格里添加栈的业务节点
    //栈的业务节点赋值
    linkstackdata->item = item;
    //stackdata 的首地址等于 stackdata->node 的地址  连接链表关系的节点
    //链表头部插入链表格,0号位置
    ret =  LinkList_InsertOneNode(stack ,linkstackdata, 0);
    //插入失败,释放内存
    if (ret == false)
    {
        if (linkstackdata != NULL)
        {
            free(linkstackdata);
            linkstackdata = NULL;
            return false;
        }
    }
    return true;
}
//从栈顶弹出元素相当于从链表头部删除元素
void* LinkStack_Pop(Stack* stack)
{
    void* ret = NULL;   //栈的业务节点
    LinkStackNode* linkstackdata = NULL; //链表的业务节点包含了栈的业务节点
    if (LinkStack_GetSize(stack) <= 0)
    {
        return NULL;
    }
    linkstackdata = (LinkStackNode* )LinkList_DeleteOneNode(stack,0);
    if (linkstackdata == NULL)
    {
        return NULL;
    }
    ret = (void*)linkstackdata->item;
    //因为push中 LinkList_InsertOneNode之前分配了内存
    //所以在Pop中 LinkList_DeleteOneNode之后释放内存
    free(linkstackdata);
    linkstackdata = NULL;
    return ret;
}

//获取栈顶元素相当于获得链表0号位置元素中的iten域的数据
void* LinkStack_Top(Stack* stack)
{
    void* ret = NULL;
    LinkStackNode* linkstackdata = NULL; 
    if (LinkStack_GetSize(stack) <= 0)
    {
        return NULL;
    }
    linkstackdata = (LinkStackNode* )LinkList_GetOneNode(stack,0);
    if (linkstackdata == NULL)
    {
        return NULL;
    }
    ret = (void*)linkstackdata->item;
    return ret;
}
//求栈的大小相当于求线性表的length
int LinkStack_GetSize(Stack* stack)
{
    int ret = 0;
    ret = LinkList_GetLength(stack);
    return ret;
}



/*********************************测试代码*******************/

/*
void main()
{
    int i = 0;
    int aa[10] = {0};
    Stack* stack = NULL;
    stack = LinkStack_Create();
    if (stack == NULL)
    {
        printf("创建链式栈失败");
    }
    for (i = 0; i < 5; i++)
    {
        aa[i] = aa[i] + i +1;
        LinkStack_Push(stack,&aa[i]);
    }
    printf("栈的大小是:%d \n",LinkStack_GetSize(stack));
    printf("栈顶元素是:%d \n",*((int*)LinkStack_Top(stack)));
    //一次弹出元素
    while(LinkStack_GetSize(stack) > 0)
    {
        printf("栈一次弹出元素:%d \n",*((int*)LinkStack_Pop(stack)));
    }
    //
    LinkStack_Destory(stack);
    system("pause");
}
*/

可能会调用其它头文件或源文件,如果调用,请翻看我的其它博客,对其头文件或源文件的实现方式。
good luck !

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

栈的链性表的c语言实现方式 linkstack.h 和 linkstack.c 的相关文章

  • 【Qt】d_ptr指针、p_ptr指针详解

    此文章可以参考 Pimpl技术的基本应用 PImpl机制以及Qt的D Pointer实现 Qt的d ptr本质上使用了pimp技术 D指针 保持一个库中的所有公有类的大小恒定的问题可以通过单独的私有指针给予解决 这个指针指向一个包含所有数据
  • Terrain Splatting

    Terrain Splatting 标签 网格优化2010 2011 05 16 16 17 1157人阅读 评论 0 收藏 举报 分类 OGRE 541 图形图像 746 游戏引擎 1651 图形引擎 1594 技术理论 1005 引擎开
  • Windows git 命令行通过token进行验证

    背景 从8月13日开始 github不再支持密码方式的身份验证 要求使用基于令牌的身份验证方式 现象 获取 token 后 需要改变原有的账号密码验证 所以需要使用生成的 token 进行更新凭证 但 git 官网针对的 mac 的操作up
  • pid是滞后超前校正_超前校正,滞后校正,超前滞后校正三种校正方法的比较

    展开全部 1 超前校正的目的是改善系统的动态性能 实现62616964757a686964616fe59b9ee7ad9431333431353332在系统静态性能不受损的前提下 提高系统的动态性能 通过加入超前校正环节 利用其相位超前特性

随机推荐

  • VuePress

    sidebar auto VuePress Vue 驱动的静态网站生成器 1 4 目录结构 VuePress 遵循 约定优于配置 的原则 推荐的目录结构如下 docs vuepress 可选的 components 可选的 theme 可选
  • 微信小程序之实名认证人脸识别接口-wx.startFacialRecognitionVerify

    小程序前端使用人脸识别功能 绑定用户 开始实名认证的方法 调用摄像头 facialRecognitionVerify function userName userIdCard wx startFacialRecognitionVerify
  • Visual Studio 2017,C++MFC免注册调用大漠插件图文教程,详细版

    Visual Studio 2017 C MFC免注册调用大漠插件图文教程 详细版 前言 提示 这里可以添加本文要记录的大概内容 有很多人都在问C MFC怎么免注册调用 其实这些都有参考但是对于新手来说 编译器对新手的不友好 很多编程新手就
  • ElementUI按需引入各种组件

    ElementUI按需引入各种组件 一 首先按需引入前奏 安装element ui npm i element ui S 安装按需引入必要插件 npm install babel plugin component D 二 修改 babelr
  • VSCode汉化设置中文

    http efonfighting imwork net 欢迎关注微信公众号 一番码客 获取免费下载服务与源码 并及时接收最新文章推送 在VSCode中按下快捷键 Ctrl Shift P 显示命令面板 Show Command Palet
  • SQL Server辅助插件——SQL Prompt

    前言 当我们对某个程序进行维护或者完善时 必不可少的就是跟数据库或者以前开发人员写的sql语句打交道 当我们 对数据库表的结构不熟悉时 修改或者编写sql语句将是一件很痛苦的时间 而且sql server有没有像vs等软件可以提供 强大的智
  • 如何使用 wget 下载一个目录下的所有文件

    今天想要下载编译原理的 虎书 上的资料 使用wget但只是下载了一个index html 如下 于是我就参考资料 写此博客以记录 方法如下 wget r np nH R index html http url including files
  • npm和cnpm下载安装及VUE的创建

    npm和cnpm下载安装及VUE的创建 1 node js下载 node js官网 http nodejs cn download 下载安装后cmd输入以下命令查看版本 2 配置npm 打开node js的安装目录 我这里是D nodejs
  • 毕设-仓库管理的设计与实现

    package com ken wms common controller import com ken wms common service Interface CustomerManageService import com ken w
  • 用js来实现自定义弹框

    前言 个人作业上传 大家可参考但不可转载 实现将弹框的样式统一封装在一个对象中方便后续的修改
  • 开关电源环路稳定性分析(05)-传递函数

    大家好 这里是大话硬件 经过前面4篇文章的梳理 估计很多人已经等不及了 什么时候可以开始环路的分析 为了尽快进入到大家关心的部分 这一讲我们正式进入环路分析的第一部分 传递函数 传递函数 简单的理解就是输入和输出之间的关系 为了方便我们仅仅
  • 【linux】linux 基础正则表达式、字符串截取、比较、分支、while循环

    1 概述 正则表达式用来在文件中匹配符合条件的字符串 正则是包含匹配 grep awk sed等命令可以支持正则表达式 通配符用来匹配符合条件的文件名 通配符是完全匹配 ls find cp这些命令不支持正则表达式 所以只能使用shell自
  • IDEA中设置vue vue3+ts项目的@跳转

    网上基本都是这个方法但是试了对我不适用 idea vue项目通过 跳转 vue设置完 映射路径之后在IDEA中无法跳转 兜兜转转原来只需 在tsconfig json中加入如下配置就行 compilerOptions baseUrl pat
  • leetcode 5749. 邻位交换的最小次数

    邻位交换的最小次数 给你一个表示大整数的字符串 num 和一个整数 k 如果某个整数是 num 中各位数字的一个 排列 且它的 值大于 num 则称这个整数为 妙数 可能存在很多妙数 但是只需要关注 值最小 的那些 例如 num 54893
  • 使用stylecop 规范C#编码

    可直接在VS操作完成 简单易懂 第一步 打开VS 第二步 安装软件 第三步 规则修改 第四步 规则生效 stylecop 是代码静态检查分析的一大利器 可以自定义检查规则 安装操作使用方便 相信很多写C 的朋友都会使用的到 下面详细介绍安装
  • XP下采用DirectShow采集摄像头

    转载请标明是引用于 http blog csdn net chenyujing1234 欢迎大家提出意见 一起讨论 需要示例源码的请独自联系我 前提 摄像头能正常工作 摄像头有创建directshow filter 即 大家可以对比我的另一
  • 数据规约

    主成分的计算步骤 主成分的代码实现 设置工作空间 把 数据及程序 文件夹拷贝到F盘下 再用setwd设置工作空间 setwd F 数据及程序 chapter4 示例程序 数据读取 inputfile lt read csv data pri
  • z系列主板能装服务器系统吗,Intel Z390主板搭配8代酷睿现身:还能安装WIN7系统吗?...

    Intel今年为发烧友带来了最多18核心的Core X系列 搭配X299顶级主板 主流领域则有最多6核心的八代酷睿Coffee Lake S 搭配Z370主板 但坑爹的是 尽管八代和六七代酷睿都是LGA1151接口 但却被故意整成不兼容 因
  • 基于power bi上手业务数据可视化

    分析背景 偶然得到一份关于某连锁火锅品牌在2020年1月 8月的线上平台业务数据 如下图 心想正好利用这份数据 模拟实际业务中基于数据库与bi工具 实践开发可视化图表 一开始考虑用tableau 因为在大学跟刚工作的时候曾系统学习使用过 但
  • 栈的链性表的c语言实现方式 linkstack.h 和 linkstack.c

    linkstack h 文件 ifndef LINK STACK H define LINK STACK H include