跳到主要内容
极客日志极客日志
首页博客AI提示词GitHub精选代理工具
搜索
|注册
博客列表
C算法

数据结构:栈和队列的定义与实现

综述由AI生成栈是一种后进先出的线性表,仅允许在栈顶进行插入和删除操作,通常使用顺序表实现以方便动态增容。队列是先进先出的线性表,在队尾插入、队头删除,为避免数据移动效率问题常采用单链表实现。文章详细阐述了两种结构的定义、特点,并给出了基于 C 语言的完整接口声明与核心函数实现代码,涵盖初始化、入栈/入队、出栈/出队、获取栈顶/队头元素及销毁等关键功能。

微码行者发布于 2026/3/16更新于 2026/4/2610 浏览
数据结构:栈和队列的定义与实现

栈结构示意

1. 栈

1.1 栈的定义及结构

栈是一种特殊的线性表,其只允许在固定的一端进行插入和删除元素操作。进行数据插入和删除操作的一端称为栈顶,另一端称为栈底。栈中的数据元素遵守后进先出(LIFO, Last In First Out)的原则。

  • 压栈:栈的插入操作叫做进栈/压栈/入栈,入数据在栈顶。
  • 出栈:栈的删除操作叫做出栈。出数据也在栈顶。

总结:栈是一个后进先出的容器。一个入栈序列可以对应多个出栈序列。

1.2 栈的实现

分析:顺序表和链表均可实现栈,但顺序表在一端操作更为方便,因此选择顺序表来实现栈。

大体思想如下:

栈实现示意图

顺序表已实现过动态增容,用其实现栈需注意细节。以下是头文件声明:

typedef int StackDataType;

typedef struct Stack {
    StackDataType* _Array;
    int _top;
    int _capacity;
} Stack;

// 栈初始化
void StackInit(Stack* s);
// 销毁栈
void StackDestory(Stack* s);
// 入栈
void StackPush(Stack* s, StackDataType x);
// 出栈
void StackPop(Stack* s);
// 获取栈顶元素
StackDataType StackTop(Stack* s);
// 获取栈有效元素个数
int StackSize(Stack* s);
// 判断栈是否为空,空返回 1,非空返回 0
int StackEmpty(Stack* s);
核心接口实现
// 栈初始化
void StackInit(Stack* s) {
    assert(s);
    // 修正:分配空间应为数据类型大小而非结构体大小
    s->_Array = (StackDataType*)malloc(sizeof(StackDataType) * ARRAYINITSIZE);
    s->_top = 0;
    s->_capacity = ARRAYINITSIZE;
}

// 销毁栈
void StackDestory(Stack* s) {
    assert(s);
    free(s->_Array);
    s->_Array = NULL;
    s->_top = s->_capacity = 0;
}

// 入栈
void StackPush(Stack* s, StackDataType x) {
    assert(s);
    if (s->_top == s->_capacity) {
        s->_capacity *= 2;
        // 修正:类型匹配
        StackDataType* temp = (StackDataType*)realloc(s->_Array, sizeof(StackDataType) * s->_capacity);
        if (temp == NULL) {
            printf("内存不足\n");
            exit(-1);
        } else {
            s->_Array = temp;
        }
    }
    s->_Array[s->_top] = x;
    s->_top++;
}

// 出栈
void StackPop(Stack* s) {
    assert(s);
    assert(s->_top != 0);
    s->_top--;
}

其它接口只需返回相应变量即可,建立接口是为了保持接口一致性。

2. 队列

2.1 队列的定义及结构

队列是只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表,具有先进先出(FIFO, First In First Out)特性。

  • 入队列:进行插入操作的一端称为队尾。
  • 出队列:进行删除操作的一端称为队头。

总结:队列如同日常排队,谁先进谁先出,一种入队序列只能对应一种出队序列。

2.2 队列的实现

分析:队列需要一头进、另一头出。顺序表头删效率低,单链表适合此场景。采用单链表形式实现队列。

typedef int QueueDataType;

typedef struct QueueListNode {
    QueueDataType _data;
    struct QueueListNode* _next;
} QueueListNode;

typedef struct Queue {
    QueueListNode* _front;
    QueueListNode* _rear;
} Queue;

// 初始化队列
void QueueInit(Queue* q);
// 队尾入队列
void QueuePush(Queue* q, QueueDataType data);
// 队头出队列
void QueuePop(Queue* q);
// 获取队列头部元素
QueueDataType QueueFront(Queue* q);
// 获取队列队尾元素
QueueDataType QueueBack(Queue* q);
// 获取队列中有效元素个数
int QueueSize(Queue* q);
// 检测队列是否为空,如果为空返回非零结果,如果非空返回 0
int QueueEmpty(Queue* q);
// 销毁队列
void QueueDestroy(Queue* q);

通过结构体存放头尾指针,使接口保持一致性,避免部分接口需传二级指针。

核心接口实现
// 队尾入队列
void QueuePush(Queue* q, QueueDataType data) {
    assert(q);
    if (q->_front == NULL) {
        // 修正:类型匹配
        QueueListNode* temp = (QueueListNode*)malloc(sizeof(QueueListNode));
        if (temp == NULL) {
            printf("内存不足\n");
            exit(-1);
        } else {
            q->_front = q->_rear = temp;
        }
    } else {
        QueueListNode* temp = (QueueListNode*)malloc(sizeof(QueueListNode));
        if (temp == NULL) {
            printf("内存不足\n");
            exit(-1);
        } else {
            q->_rear->_next = temp;
            q->_rear = temp;
        }
    }
    q->_rear->_data = data;
    q->_rear->_next = NULL;
}

// 队头出队列
void QueuePop(Queue* q) {
    assert(q);
    assert(q->_front != NULL);
    QueueListNode* frontNext = q->_front->_next;
    free(q->_front);
    q->_front = frontNext;
}

总结:栈常用于迷宫回溯等后进先出场景;队列常见于银行排队等先进先出场景。掌握这两种基础数据结构对理解算法设计至关重要。

目录

  1. 1. 栈
  2. 1.1 栈的定义及结构
  3. 1.2 栈的实现
  4. 核心接口实现
  5. 2. 队列
  6. 2.1 队列的定义及结构
  7. 2.2 队列的实现
  8. 核心接口实现
  • 💰 8折买阿里云服务器限时8折了解详情
  • 💰 8折买阿里云服务器限时8折购买
  • 🦞 5分钟部署阿里云小龙虾了解详情
  • 🤖 一键搭建Deepseek满血版了解详情
  • 一键打造专属AI 智能体了解详情
极客日志微信公众号二维码

微信扫一扫,关注极客日志

微信公众号「极客日志V2」,在微信中扫描左侧二维码关注。展示文案:极客日志V2 zeeklog

更多推荐文章

查看全部
  • FPGA PCIe IP 核详解、实现及仿真流程
  • WebSocket 连接教程示例(Spring Boot + STOMP + SockJS + Vue)
  • Java 异常处理:核心机制与实战
  • Python 自动化办公实战:Excel、Word、PPT 及邮件处理指南
  • 程序员求职季:从金三银四到铜三铁四的面试避坑指南
  • 基于 TextIn 与 Coze 的财报数据自动化抽取实践
  • Java Maven 项目结合 Git 与 Jenkins 的自动化构建部署指南
  • Ubuntu 20.04 网络配置指南
  • Home Assistant 美的设备本地控制配置指南
  • 鸿蒙电商购物车项目:用户管理、商品列表与购物车实现
  • 自然语言处理在法律领域的应用与实战
  • 腾讯混元 Image 2.1 GGUF 版:消费级显卡本地部署方案
  • OpenVLA 模型微调与机器人平台部署实战
  • 本地运行大模型工具:Ollama 安装与使用详解
  • 通义千问 2.5-7B-Instruct 本地部署与 Gradio 交互界面搭建
  • 数学建模竞赛全流程指南与 AI 提示词
  • 数据结构:八种常见排序算法
  • OpenClaw 本地 AI 助手安装与使用指南
  • OpenClaw 接入 Telegram 机器人配置与加入群聊
  • 国内升级 GitHub Copilot 专业版 PayPal 支付方案

相关免费在线工具

  • 加密/解密文本

    使用加密算法(如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