跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客我的书AI学习GitHub 精选镜像AI 生图工具UI配色美学关于
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
C算法

数据结构:单向链表,顺序栈和链式栈

单向链表、顺序栈和链式栈三种数据结构。内容包括基本定义、结构体设计、核心特性及时间复杂度分析。重点对比了顺序栈的静态与动态实现,以及链式栈的单结构体头节点法与双结构体封装法。最后通过表格综合对比了三种结构在存储、操作及性能上的差异,为系统设计中选择合适的数据结构提供依据。

战神发布于 2026/3/23更新于 2026/9/362 浏览

一、单向链表(Singly Linked List)

1.1 基本定义

单向链表是一种线性数据结构,由一系列节点通过指针单向连接而成。每个节点包含数据域和指向下一个节点的指针域。

1.2 结构定义
// 单向链表节点结构
typedef struct ListNode {
    int data;           // 数据域
    struct ListNode *next; // 指针域
} ListNode;

// 单向链表管理结构(可选)
typedef struct LinkedList {
    ListNode *head;     // 头指针
    ListNode *tail;     // 尾指针
    int length;         // 链表长度
} LinkedList;
1.3 核心特性
  • 动态内存分配:节点按需分配,无需预知数据规模
  • 非连续存储:物理地址分散,通过指针建立逻辑联系
  • 灵活操作:支持任意位置插入和删除
  • 单向遍历:仅支持从头至尾的顺序访问
1.4 时间复杂度分析
操作时间复杂度备注
头插O(1)直接修改头指针
尾插O(1)/O(n)若有尾指针则为 O(1)
中间插入O(n)需遍历至指定位置
删除O(1)/O(n)头删除 O(1),其他需遍历
查找O(n)必须顺序遍历

二、顺序栈(Sequential Stack)

2.1 基本定义

顺序栈基于数组实现,通过固定偏移量维护栈顶位置,利用连续内存空间存储数据元素。

2.2 结构定义
// 静态顺序栈
#define MAX_SIZE 100
typedef struct {
    int data[MAX_SIZE]; // 存储数据的数组
    int top;            // 栈顶指针(数组下标)
} StaticSeqStack;

// 动态顺序栈
typedef struct {
    int *data;          // 动态数组指针
    int top;            // 栈顶指针
    int capacity;       // 栈容量
} DynamicSeqStack;
2.3 核心特性
  • 连续存储:数据在内存中连续存放
  • 大小固定:静态实现有固定上限,动态实现可扩容
  • 操作受限:仅允许在栈顶进行插入和删除
  • 高效访问:通过数组下标直接访问,缓存友好
2.4 关键操作实现
// 初始化动态顺序栈
DynamicSeqStack* InitDynamicStack(int initCapacity) {
    DynamicSeqStack *stack = (DynamicSeqStack*)malloc(sizeof(DynamicSeqStack));
    stack->data = (int*)malloc(initCapacity * sizeof(int));
    stack->top = -1;
    stack->capacity = initCapacity;
    return stack;
}

// 入栈操作
int Push(DynamicSeqStack *stack, int value) {
    if (stack->top == stack->capacity - 1) {
        // 栈满,需要扩容
        int newCapacity = stack->capacity * 2;
        int *newData = (int*)realloc(stack->data, newCapacity * sizeof(int));
        if (!newData) return 0;
        stack->data = newData;
        stack->capacity = newCapacity;
    }
    stack->data[++stack->top] = value;
    return 1;
}

// 出栈操作
int Pop(DynamicSeqStack *stack) {
    if (stack->top == -1) {
        // 栈空处理
        return INT_MIN;
    }
    return stack->data[stack->top--];
}

三、链式栈(Linked Stack)

3.1 基本定义

链式栈基于链表实现栈结构,具备链表的动态特性与栈的操作限制。其设计存在两种主要模式:单结构体头节点法和双结构体封装法。

3.2 设计模式一:单结构体头节点法

该方法采用单一节点结构,使用头节点作为栈的标识,栈顶位于头节点之后。

结构定义
// 单结构体定义
typedef struct StackNode {
    int data;           // 数据域
    struct StackNode *next; // 指针域
} StackNode;

// 栈节点同时也是栈标识
实现特点
  • 头节点作为栈标识:头节点不存储有效数据,其 next 指针指向栈顶
  • 统一节点类型:仅需一种结构体类型
  • 头插法操作:入栈采用头插法,出栈删除头节点后继
  • 函数参数简单:函数直接接收头节点指针
核心操作示例
// 创建空栈
StackNode* CreateStack() {
    StackNode *head = (StackNode*)malloc(sizeof(StackNode));
    head->next = NULL; // 空栈,头节点 next 为 NULL
    return head;
}

// 入栈操作
void Push(StackNode *head, int value) {
    StackNode *newNode = (StackNode*)malloc(sizeof(StackNode));
    newNode->data = value;
    newNode->next = head->next; // 新节点指向原栈顶
    head->next = newNode;       // 头节点指向新栈顶
}

// 出栈操作
int Pop(StackNode *head) {
    if (head->next == NULL) {
        return INT_MIN; // 栈空处理
    }
    StackNode *top = head->next;
    int value = top->data;
    head->next = top->next;
    free(top);
    return value;
}
3.3 设计模式二:双结构体封装法

该方法采用两个结构体,分别定义节点和栈管理结构,实现逻辑与数据分离。

结构定义
// 节点结构
typedef struct LinkedStackNode {
    int data;           // 数据域
    struct LinkedStackNode *next; // 指针域
} LinkedStackNode;

// 栈管理结构
typedef struct {
    LinkedStackNode *top; // 栈顶指针
    int size;             // 栈大小
} LinkedStack;
实现特点
  • 逻辑与数据分离:栈管理结构与节点结构分离
  • 状态信息明确:可维护栈大小等状态信息
  • 无头节点开销:栈顶指针直接指向栈顶元素
  • 面向对象思想:更符合现代编程封装理念
核心操作示例
// 创建空栈
LinkedStack* CreateLinkedStack() {
    LinkedStack *stack = (LinkedStack*)malloc(sizeof(LinkedStack));
    stack->top = NULL;
    stack->size = 0;
    return stack;
}

// 入栈操作
void PushLinkedStack(LinkedStack *stack, int value) {
    LinkedStackNode *newNode = (LinkedStackNode*)malloc(sizeof(LinkedStackNode));
    newNode->data = value;
    newNode->next = stack->top; // 新节点指向原栈顶
    stack->top = newNode;       // 更新栈顶指针
    stack->size++;              // 更新栈大小
}

// 出栈操作
int PopLinkedStack(LinkedStack *stack) {
    if (stack->top == NULL) {
        return INT_MIN; // 栈空处理
    }
    LinkedStackNode *topNode = stack->top;
    int value = topNode->data;
    stack->top = topNode->next; // 更新栈顶指针
    free(topNode);
    stack->size--;              // 更新栈大小
    return value;
}
3.4 两种设计模式对比
对比维度单结构体头节点法双结构体封装法
结构复杂度简单,一种结构体复杂,两种结构体
内存开销有头节点额外开销无头节点开销
状态维护需遍历计算栈大小可直接获取栈大小
代码清晰度逻辑相对简单职责分离清晰
扩展性扩展性有限易于扩展功能
适用场景简单栈操作需要状态维护的复杂栈

四、三项结构综合对比

4.1 存储结构对比
特性单向链表顺序栈链式栈
物理结构非连续存储连续存储非连续存储
内存分配动态节点分配静态数组或动态数组动态节点分配
指针开销每个节点含指针无指针开销每个节点含指针
内存连续性不连续,碎片化连续,无碎片不连续,碎片化
4.2 操作特性对比
特性单向链表顺序栈链式栈
插入位置任意位置仅栈顶仅栈顶
删除位置任意位置仅栈顶仅栈顶
访问方式顺序访问随机访问(数组下标)顺序访问
遍历方向单向遍历双向(理论上)单向遍历
扩容机制自然扩展需要显式扩容自然扩展
4.3 性能指标对比
指标单向链表顺序栈链式栈
头插/入栈O(1)O(1)(平摊)O(1)
尾插O(1)/O(n)不支持不支持
中间插入O(n)不支持不支持
头删/出栈O(1)O(1)O(1)
查找访问O(n)O(1)(通过下标)O(n)
缓存效率差好差
空间利用率较低(含指针)高较低(含指针)

五、结论

单向链表、顺序栈和链式栈代表了三种不同的线性数据组织策略。单向链表强调操作灵活性,顺序栈注重访问效率,链式栈则结合了动态扩展与操作约束。

链式栈的两种设计模式体现了不同的工程权衡:单结构体头节点法以简洁性见长,双结构体封装法则以扩展性取胜。实际选择应基于具体需求,权衡性能、内存、扩展性和实现复杂度等因素。

在系统设计中,理解这些基础结构的本质特性及其实现差异,对于选择合适的数据结构、优化算法性能、构建稳定可靠的软件系统具有重要意义。每种结构都有其适用场景,优秀的系统设计者应根据具体约束条件做出合理选择,而非盲目追求某种结构的普遍适用性。

目录

  1. 一、单向链表(Singly Linked List)
  2. 1.1 基本定义
  3. 1.2 结构定义
  4. 1.3 核心特性
  5. 1.4 时间复杂度分析
  6. 二、顺序栈(Sequential Stack)
  7. 2.1 基本定义
  8. 2.2 结构定义
  9. 2.3 核心特性
  10. 2.4 关键操作实现
  11. 三、链式栈(Linked Stack)
  12. 3.1 基本定义
  13. 3.2 设计模式一:单结构体头节点法
  14. 结构定义
  15. 实现特点
  16. 核心操作示例
  17. 3.3 设计模式二:双结构体封装法
  18. 结构定义
  19. 实现特点
  20. 核心操作示例
  21. 3.4 两种设计模式对比
  22. 四、三项结构综合对比
  23. 4.1 存储结构对比
  24. 4.2 操作特性对比
  25. 4.3 性能指标对比
  26. 五、结论

更多推荐文章

查看全部
  • 数据库查询执行:排序与聚合算法详解
  • VS Code 结合 Overleaf Workshop 插件实现本地 AI 辅助 LaTeX 写作
  • LazyLLM 框架实战:构建代码专家智能体
  • MCP Server 案例:利用 Excel 生成可视化 HTML 报告
  • 高频算法推理场景下的灵活计费与本地模型部署
  • 渗透测试实战:获取并破解 Net-NTLMv2 哈希
  • 使用 Miniconda 安装 ChromaDB 避免 C++ 编译错误
  • 10 本计算机开源书籍精选
  • LangChain 结合 SQLite3 实现自然语言 SQL 查询
  • Langchain-Chatchat 本地知识库部署与使用指南
  • 前端状态管理进阶:Immutable.js 实战与避坑指南
  • Python 环境安装与配置 Gurobi 求解器指南
  • 火山引擎发布豆包编程模型 Doubao-Seed-Code,支持 Agentic 任务与视觉理解
  • 机器人脑部药物递送三大技术路径的可转化性分析
  • Ubuntu 虚拟机安装配置教程
  • AMD 显卡 Vulkan 兼容性深度解析:5 步解决 llama.cpp 部署难题
  • Kiro AI 助手完整使用指南
  • .NET WebApi 项目必要可配置项详解
  • KDTS 工具实现 MySQL 至 KingbaseES 数据迁移实战
  • Kiro 安装与使用指南:AWS 新一代 AI IDE 两种部署方式

相关免费在线工具

  • 加密/解密文本

    使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online

  • Gemini 图片去水印

    基于开源反向 Alpha 混合算法去除 Gemini/Nano Banana 图片水印,支持批量处理与下载。 在线工具,Gemini 图片去水印在线工具,online

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

  • Base64 文件转换器

    将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online

  • Markdown转HTML

    将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online

  • HTML转Markdown

    将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online