当前位置: 首页 > news >正文

数据结构(七)---链式栈

#### 链式栈实现

##### linkstack.h

#ifndef _LINKSTACK_H
#define _LINKSTACK_H


// 引入相关的库文件
#include <stdio.h>
#include <stdlib.h>
#include <string.h>


// 定义元素类型的别名
typedef int DATA;


//定义链式栈节点
typedef struct node
{
    DATA data;
    struct node *next;
}NODE;


//定义链式栈结构体
typedef struct 
{
    NODE *top;     //栈顶指针,其实就是链表中的头节点
    int size;     //当前元素数量
    int capacity;     //栈容量
}LinkStack;


/**
 * 初始化链式栈
 * @param s 栈结构体指针(需由调用者提前分配内存)
 * @param num 栈容量的大小
 * @return 初始化成功返回0,否则返回-1
 */
extern int lstack_init(LinkStack *s, int num);


/**
 * 判断栈是否已满
 * @param s 栈结构体指针(需由调用者提前分配内存)
 * @return 栈已满返回1
 */
extern int lstack_isfull(LinkStack *s);


/**
 * 入栈
 * @param s 栈结构体指针(需由调用者提前分配内存)
 * @param data 待入栈的数据
 * @return 成功返回0,否则返回-1
 */
extern int lstack_push(LinkStack *s, DATA data);


/**
 * 判断栈是否为空
 * @param s 栈结构体指针(需由调用者提前分配内存)
 * @return 栈为空返回1
 */
extern int lstack_isempty(LinkStack *s);


/**
 * 出栈
 * @param s 栈结构体指针(需由调用者提前分配内存)
 * @param data 接收出栈的数据指针
 * @return 成功返回0,否则返回-1
 */
extern int lstack_pop(LinkStack *s, DATA *data);


/**
 * 销毁栈
 */
extern void lstack_destroy(LinkStack *s);


#endif //_LINKSTACK_H
```

##### linkstack.c

#include "linkstack.h"


/**
 * 初始化链式栈
 * @param s 栈结构体指针(需由调用者提前分配内存)
 * @param num 栈容量的大小
 * @return 初始化成功返回0,否则返回-1
 */
int lstack_init(LinkStack *s, int num)
{
    //空指针检查
    if(!s)
    {
        perror("创建失败!");
        return -1;
    }
    
    //num的检查
    if(num <= 0)
    {
        perror("容量有误,创建失败!");
        return -1;
    }
    
    //初始化栈属性
    s->top = NULL;     //栈顶指针置空,表示空栈
    s->size = 0;     //当前元素数量为0 
    s->capacity = num;     //设置容量限制(需后续操作中校验)
    
    return 0;
}


/**
 * 判断栈是否已满
 * @param s 栈结构体指针(需由调用者提前分配内存)
 * @return 栈已满返回1
 */
int lstack_isfull(LinkStack *s)
{
    return s->size >= s->capacity;
}


/**
 * 入栈
 * @param s 栈结构体指针(需由调用者提前分配内存)
 * @param data 待入栈的数据
 * @return 成功返回0,否则返回-1
 */
int lstack_push(LinkStack *s, DATA data)
{
    //判断栈是否已满
    if(lstack_isfull(s))
    {
        perror("栈已满,数据无法入栈!");
        return -1;
    }
    
    //创建新节点
    NODE *p = (NODE*)malloc(sizeof(NODE));
    if(!p)
    {
        perror("Memory allocation failed!");
        return -1;
    }
    
    //初始化
    p->data = data;     //存储数据
    p->next = s->top;     //新节点指向原栈顶
    s->top = p;     //更新栈顶指针为新节点
    s->size++;     //元素计数增加
    
    return 0;
}


/**
 * 判断栈是否为空
 * @param s 栈结构体指针(需由调用者提前分配内存)
 * @return 栈为空返回1
 */
int lstack_isempty(LinkStack *s)
{
    if(!s)
        return 1;     //空指针视为空栈
    
    return s->size == 0;
    //return s->top = NULL;
}


/**
 * 出栈
 * @param s 栈结构体指针(需由调用者提前分配内存)
 * @param data 接收出栈的数据指针
 * @return 成功返回0,否则返回-1
 */
int lstack_pop(LinkStack *s, DATA *data)
{
    if(!s || !data)
    {
        perror("Stack is empty!");
        return -1;
    }
    
    //判断栈是否为空
    if(lstack_isempty(s))
    {
        perror("警告!试图从空栈弹出数据!");
        return -1;
    }
    
    NODE *p = s->top;     //保存栈顶节点
    *data = p->data;     //获取弹出栈的数据
    s->top = p->next;     //更新栈顶指针
    free(p);     //释放原栈顶节点
    s->size--;
    
    return 0;
}


/**
 * 销毁栈
 */
void lstack_destroy(LinkStack *s)
{
    if(!s) 
        return;     //空指针保护
    
    DATA temp;     //临时存储弹出数据
    
    //释放所有节点
    while(!lstack_isempty(s))
    {
        lstack_pop(s, &temp);     //弹出数据存入temp
    }
    return;
}
```

##### app.c

#include "linkstack.h"

int main(int argc, char const *argv[])
{
    LinkStack s;
    DATA temp;

    // 1. 初始化容量为10的链式栈
    lstack_init(&s, 10);

    // 2. 入栈测试
    printf("入栈顺序:");
    for (int i = 0; i < 10; i++)
    {
        lstack_push(&s, i + 10); // 压入10~19
        printf("%d ", i + 10);
    }
    printf("\n");

    // 测试栈满
    if (lstack_push(&s, 20) == -1)
        printf("栈已满,插入20失败\n");

    // 3. 出栈测试
    printf("出栈顺序:");
    while (!lstack_isempty(&s))
    {
        lstack_pop(&s, &temp);
        printf("%d ", temp);
    }
    printf("\n");

    // 测试栈空
    if (lstack_pop(&s, &temp) == -1)
        printf("栈已空,无法弹出\n");

    // 4. 销毁栈
    lstack_destroy(&s);
    return 0;
}

http://www.xdnf.cn/news/184537.html

相关文章:

  • AI看论文自动生成代码库:Paper2Code如何革新科研复现?
  • 函数式链表:Python编程的非常规 “链” 接
  • QT6 源(53)篇三:存储 c 语言字符串的类 QByteArray 的使用举例,
  • 移除生产环境所有console.log
  • 给视频自动打字幕:从Humanoid-X、UH-1到首个人形VLA Humanoid-VLA:迈向整合第一人称视角的通用人形控制
  • 基于STM32、HAL库的AD7616BSTZ模数转换器ADC驱动程序设计
  • Linux操作系统学习---进程地址空间
  • 【LaTex】8.1 文档类与层级
  • 前端权限管理
  • 小刚说C语言刷题——1320时钟旋转
  • 生成式人工智能认证(GAI认证)要学哪些知识?
  • google chrome 中 fcitx5 候选框不跟随光标
  • 【SpringCloudAlibaba】Dubbo 和 Spring Cloud OpenFeign 在服务治理能力上的差异
  • 生成式人工智能认证(GAI认证)考试难吗?
  • SpringBoot的自动扫描特性-笔记
  • Vue初步总结-摘自 黑马程序员
  • 浅谈 MySQL 日志的原理
  • 新增 29 个专业,科技成为关键赛道!
  • 互联网的下一代脉搏:深入理解 QUIC 协议
  • Day23-Web开发——Linux
  • 基于深度学习的图像压缩技术(二)
  • AI时代下如何实现财务自由?
  • 江达、安托、凯思软件这几家达索代理商,哪家好?
  • 算法备案批量咨询问题解答第二期
  • NdrpPointerUnmarshallInternal函数分析之pFormatPointee指针的确定
  • deepspeed 滴 ZERO 介绍
  • Python中的win32包介绍
  • MIME 类型是个什么东西?
  • JavaScript 解构赋值(下):对象解构与高级应用
  • 复盘笔记1