链栈(链式栈) 超详细实现(C 语言 + 逐行精讲)

前言

栈(Stack) 是一种后进先出(LIFO)的线性数据结构。** ****前面我们学习了顺序栈** (数组实现),今天我们学习它的兄弟 ------链栈(链式栈)

链栈 = 用单链表实现的栈 它完美解决了顺序栈容量固定、需要扩容的缺点。


一、链栈是什么?

链栈 = 采用链式存储结构实现的栈 本质就是一个只能在表头进行插入、删除操作的单链表

特点:

  • 不需要预先分配空间,想用多少申请多少

  • 不存在栈满溢出问题(除非内存耗尽)

  • 不用扩容

  • 入栈、出栈都在表头完成,效率 O (1)

  • 每个节点包含:数据域 + 指针域


二、链栈结构体设计(核心)

链栈采用 "头结点辅助管理" 模式,结构非常清晰:

cpp 复制代码
#pragma once
typedef char ELEM_TYPE;

// 链栈节点结构体
typedef struct Stack_Node
{
    ELEM_TYPE data;        // 数据域
    struct Stack_Node* next;// 指针域
}Stack_Node, *PStack_Node;

// 链栈辅助结构体(管理栈顶 + 长度)
typedef struct
{
    PStack_Node top;   // 栈顶指针
    int count;         // 节点个数(有效长度)
}LinkStack;

结构说明

  • Stack_Node:真正存储数据的节点

  • LinkStack:辅助管理结构

    • top:永远指向栈顶节点

    • count:记录栈中元素个数,获取长度 O (1)


三、链栈支持的操作(全覆盖)

cpp 复制代码
// 1. 初始化
void Init_Stack(LinkStack* ls);
// 2. 入栈(头插)
bool Push(LinkStack* ls, ELEM_TYPE val);
// 3. 出栈(头删)
bool Pop(LinkStack* ls);
// 4. 获取栈顶元素
ELEM_TYPE Top(LinkStack* ls);
// 5. 判空
bool Is_Empty(LinkStack* ls);
// 6. 获取有效长度
int Get_Length(LinkStack* ls);
// 7. 清空
void Clear(LinkStack* ls);
// 8. 销毁(释放内存)
void Destroy(LinkStack* ls);
// 9. 打印
void Show(LinkStack* ls);

四、核心函数逐行精讲(最关键)

1. 初始化

cpp 复制代码
void Init_Stack(LinkStack* ls)
{
    assert(ls != NULL);
    ls->count = 0;    // 元素个数为0
    ls->top = NULL;   // 栈顶为空
}

作用:栈一开始是空的,栈顶指针为 NULL,长度为 0。


2. 入栈 Push(核心:头插法)

链栈入栈 = 单链表头插 时间复杂度 O(1)

cpp 复制代码
bool Push(LinkStack* ls, ELEM_TYPE val)
{
    assert(ls != NULL);
    // 申请新节点
    Stack_Node* p = (Stack_Node*)malloc(sizeof(Stack_Node));
    if (p == NULL)
        return false;

    p->data = val;
    p->next = ls->top;  // 新节点指向原来栈顶
    ls->top = p;        // 更新栈顶
    ls->count++;        // 长度+1
    return true;
}

3. 出栈 Pop(核心:头删法)

链栈出栈 = 删除链表第一个节点 时间复杂度 O(1)

cpp 复制代码
bool Pop(LinkStack* ls)
{
    assert(ls != NULL);
    if (Is_Empty(ls))
        return false;

    Stack_Node* p = ls->top;
    ls->top = p->next;  // 栈顶后移
    free(p);            // 释放旧栈顶
    ls->count--;        // 长度-1
    return true;
}

4. 获取栈顶元素 Top

cpp 复制代码
ELEM_TYPE Top(LinkStack* ls)
{
	assert(ls != NULL);
	if (Is_Empty(ls))
		exit(1);
	return ls->top->data;
}

5. 判空

cpp 复制代码
bool Is_Empty(LinkStack* ls)
{
	assert(ls != NULL);
	//return ls->top == NULL;//2选1
	return ls->count == 0;
}

6. 获取长度

cpp 复制代码
int Get_Length(LinkStack* ls)
{
    assert(ls != NULL);
    return ls->count; // O(1) 直接返回,不用遍历!
}

用 count 记录长度,不用遍历链表,效率极高!


7. 销毁栈(重要!防止内存泄漏)

cpp 复制代码
void Destroy(LinkStack* ls)
{
    PStack_Node p = ls->top;
    PStack_Node q = NULL;
    while (p != NULL)
    {
        q = p->next;
        free(p);
        p = q;
    }
    ls->count = 0;
    ls->top = NULL;
}

8. 清空

cpp 复制代码
void Clear(LinkStack* ls)
{
	Destroy(ls);
}

9. 打印栈

cpp 复制代码
void Show(LinkStack* ls)
{
    Stack_Node* p = ls->top;
    for (; p != NULL; p = p->next)
    {
        printf("%c ", p->data);
    }
    printf("\n");
}

五、测试主函数(可直接运行)

cpp 复制代码
int main()
{
    LinkStack head;
    Init_Stack(&head);

    Push(&head, 'A');
    Push(&head, 'B');
    Push(&head, 'C');

    Show(&head);      // 输出:C B A
    Pop(&head);
    Show(&head);      // 输出:B A
    printf("%c \n", Top(&head)); // 输出:B

    Destroy(&head);
    return 0;
}

运行结果


六、链栈 VS 顺序栈

特性 顺序栈 链栈
存储结构 连续数组 链式节点
容量 固定 / 需扩容 无限(不溢出)
入栈出栈 O(1) O(1)
内存分配 静态 / 动态 动态
访问速度 快(缓存友好) 较慢
适用场景 已知最大容量 无法预估容量

七、高频考点(必背)

  1. 链栈为什么用头插法? 因为栈只能在栈顶操作,头插 = 栈顶入栈,时间复杂度 O (1)。

  2. 链栈有没有栈满? 一般认为没有,只有内存不足时才会申请失败。

  3. 链栈的栈顶在链表头还是尾? 链表头部

  4. 链栈如何获取长度?count 变量记录,O(1) 返回,不用遍历。

  5. 链栈和顺序栈最大区别? 顺序栈需要扩容,链栈不需要扩容


相关推荐
hold?fish:palm8 小时前
24 回文链表
数据结构·c++·链表
库玛西11 小时前
现代 C++ 智能指针全景指南:从 RAII 思想到工业级实践
c语言·开发语言·c++·笔记·面试
AC赳赳老秦11 小时前
风控岗应用:OpenClaw 采集公开司法与经营异常数据,自动生成企业风险评估报告
大数据·c语言·数据库·人工智能·python·php·openclaw
caimouse12 小时前
ReactOS 图形系统分析(19):颜色转换对象 — XLATEOBJ(xlateobj.c/h)
c语言·开发语言
qeen8712 小时前
【数据结构】自平衡二叉搜索树各种旋转算法原理解析及AVL树的C++实现
数据结构·c++·算法
程序员与背包客_CoderZ13 小时前
Linux D-Bus通信协议详解:从入门到C/C++编码实战
linux·服务器·c语言·c++·嵌入式硬件·嵌入式软件·dbus
冻柠檬飞冰走茶13 小时前
PTA基础编程题目集 7-35有理数均值(C++语言实现)
开发语言·数据结构·c++·算法·均值算法
嵌入式阿蔡14 小时前
HAL库 vs LL库 vs 寄存器:到底用哪个?
c语言·stm32·单片机·嵌入式硬件·嵌入式实时数据库
Yyyyyy~14 小时前
【C】C语言常见概念
c语言
Nil20814 小时前
leetcode 189轮转数组
数据结构·算法·leetcode