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

栈和队列数据结构初阶:模拟实现与 STL 应用

介绍栈和队列的数据结构基础,包含手动模拟实现(基于数组和链表)及 STL 标准库用法。内容涵盖栈的初始化、入栈出栈、销毁等操作,以及队列的链式实现。此外,通过三道 LeetCode 经典习题(有效括号、用栈实现队列、设计循环队列)巩固知识,重点讲解循环队列取模处理及内存管理注意事项。

魔法巫师发布于 2026/3/24更新于 2026/5/216 浏览
栈和队列数据结构初阶:模拟实现与 STL 应用

理论部分

栈的模拟实现

typedef int STDataType;
typedef struct Stack {
    STDataType* a; // 数组
    int top;       // 当前容量/下标
    int capacity;  // 总容量
} ST;

void STInit(ST* ps) {
    assert(ps);
    ps->a = (STDataType*)malloc(sizeof(STDataType) * 4);
    if (ps->a == NULL) {
        perror("malloc fail");
        return;
    }
    ps->capacity = 4;
    ps->top = 0;
}

void STDestroy(ST* ps) {
    assert(ps);
    free(ps->a);
    ps->a = NULL;
    ps->top = 0;
    ps->capacity = 0;
}

void STPush(ST* ps, STDataType x) {
    assert(ps);
    if (ps->top == ps->capacity) {
        STDataType* tmp = (STDataType*)realloc(ps->a, sizeof(STDataType) * ps->capacity * 2);
        if (tmp == NULL) {
            perror("realloc fail");
            return;
        }
        ps->a = tmp;
        ps->capacity *= 2;
    }
    ps->a[ps->top] = x;
    ps->top++;
}

void STPop(ST* ps) {
    assert(ps);
    assert(!STEmpty(ps));
    ps->top--;
}

int STSize(ST* ps) {
    assert(ps);
    return ps->top;
}

bool STEmpty(ST* ps) {
    assert(ps);
    return ps->top == 0;
}

STDataType STTop(ST* ps) {
    assert(ps);
    assert(!STEmpty(ps));
    return ps->a[ps->top - 1];
}

注意:栈顶元素下标为 top-1。初始化时检查内存分配是否成功,扩容后需更新指针。

STL 中的栈容器

#include <stack>
// stack<T> st; // T 为任意类型
// size(), empty(), push(), pop(), top()
// 特性:先进后出 (LIFO)

队列的模拟实现

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <assert.h>

typedef char QDatatype;
typedef struct QueueNode {
    struct QueueNode* next;
    QDatatype data;
} QNode;

typedef struct Queue {
    QNode* head;
    QNode* tail;
    int size;
} Queue;

void QueueInit(Queue* pq) {
    assert(pq);
    pq->head = pq->tail = NULL;
    pq->size = 0;
}

void QueueDestroy(Queue* pq) {
    assert(pq);
    QNode* cur = pq->head;
    while (cur) {
        QNode* next = cur->next;
        free(cur);
        cur = next;
    }
    pq->head = pq->tail = NULL;
    pq->size = 0;
}

void QueuePush(Queue* pq, QDatatype x) {
    QNode* newnode = (QNode*)malloc(sizeof(QNode));
    if (newnode == NULL) {
        perror("malloc fail");
        return;
    }
    newnode->data = x;
    newnode->next = NULL;
    if (pq->head == NULL) {
        assert(pq->tail == NULL);
        pq->head = pq->tail = newnode;
    } else {
        pq->tail->next = newnode;
        pq->tail = newnode;
    }
    pq->size++;
}

void QueuePop(Queue* pq) {
    assert(pq);
    assert(pq->head != NULL);
    if (pq->head->next == NULL) {
        free(pq->head);
        pq->head = pq->tail = NULL;
    } else {
        QNode* next = pq->head->next;
        free(pq->head);
        pq->head = next;
    }
    pq->size--;
}

int QueueSize(Queue* pq) {
    assert(pq);
    return pq->size;
}

bool QueueEmpty(Queue* pq) {
    assert(pq);
    return pq->size == 0;
}

QDatatype QueueFront(Queue* pq) {
    assert(pq);
    assert(!QueueEmpty(pq));
    return pq->head->data;
}

QDatatype QueueBack(Queu* pq) {
    assert(pq);
    assert(!QueueEmpty(pq));
    return pq->tail->data;
}

注意:结构体嵌套定义无需单独手动开辟内存;assert 用于断言条件成立。

STL 中的队列容器

#include <queue>
// queue<T> q; // T 为任意类型
// size(), empty(), push(), pop(), front(), back()
// 特性:先进先出 (FIFO),pop 删除队头

作业部分

力扣 有效的括号

题目链接: https://leetcode.cn/problems/valid-parentheses/

思路: 使用栈匹配左右括号,右括号数量不等于左括号时需特殊处理。

typedef struct Stack {
    char* a;
    int top;
    int capacity;
} ST;

void STInit(ST* ps) {
    ps->a = (char*)malloc(sizeof(char) * 4);
    ps->capacity = 4;
    ps->top = 0;
}

void STPush(ST* ps, char x) {
    assert(ps);
    if (ps->top == ps->capacity) {
        char* tmp = (char*)malloc(sizeof(char) * ps->capacity * 2);
        memcpy(tmp, ps->a, sizeof(char) * ps->capacity);
        free(ps->a);
        ps->a = tmp;
        ps->capacity *= 2;
    }
    ps->a[ps->top] = x;
    ps->top++;
}

void STPop(ST* ps) {
    assert(ps);
    ps->top--;
}

bool STEmpty(ST* ps) {
    return ps->top == 0;
}

char STTop(ST* ps) {
    return ps->a[ps->top - 1];
}

bool isValid(char* s) {
    ST st;
    STInit(&st);
    for (int i = 0; s[i]; i++) {
        if (s[i] == '(' || s[i] == '[' || s[i] == '{') {
            STPush(&st, s[i]);
        } else {
            if (STEmpty(&st)) {
                STDestroy(&st);
                return false;
            }
            char top = STTop(&st);
            if ((s[i] == ')' && top != '(') ||
                (s[i] == ']' && top != '[') ||
                (s[i] == '}' && top != '{')) {
                STDestroy(&st);
                return false;
            }
            STPop(&st);
        }
    }
    bool result = STEmpty(&st);
    STDestroy(&st);
    return result;
}

力扣 用栈实现队列

题目链接: https://leetcode.cn/problems/implement-queue-using-stacks/

思路: 双栈法,一个栈入栈,一个栈出栈。出栈空时将入栈数据倒入。

class MyQueue {
public:
    stack<int> q1; // 入栈
    stack<int> q2; // 出栈

    void push(int x) {
        q1.push(x);
    }

    int pop() {
        if (!q2.empty()) {
            int m = q2.top();
            q2.pop();
            return m;
        } else {
            while (!q1.empty()) {
                q2.push(q1.top());
                q1.pop();
            }
            int n = q2.top();
            q2.pop();
            return n;
        }
    }

    int peek() {
        if (!q2.empty()) {
            return q2.top();
        } else {
            while (!q1.empty()) {
                q2.push(q1.top());
                q1.pop();
            }
            return q2.top();
        }
    }

    bool empty() {
        return q1.empty() && q2.empty();
    }
};

力扣 设计循环队列

题目链接: https://leetcode.cn/problems/design-circular-queue/

思路: 使用数组模拟,通过取模运算实现循环。需注意区分空和满状态(通常预留一个空间)。

typedef struct {
    int* a;
    int front;
    int rear;
    int k;
} MyCircularQueue;

MyCircularQueue* myCircularQueueCreate(int k) {
    MyCircularQueue* obj = (MyCircularQueue*)malloc(sizeof(MyCircularQueue));
    obj->front = obj->rear = 0;
    obj->k = k;
    obj->a = (int*)malloc(sizeof(int) * (k + 1));
    return obj;
}

bool myCircularQueueIsEmpty(MyCircularQueue* obj) {
    return obj->front == obj->rear;
}

bool myCircularQueueIsFull(MyCircularQueue* obj) {
    return (obj->rear + 1) % (obj->k + 1) == obj->front;
}

bool myCircularQueueEnQueue(MyCircularQueue* obj, int value) {
    if (myCircularQueueIsFull(obj)) return false;
    obj->a[obj->rear] = value;
    obj->rear = (++obj->rear) % (obj->k + 1);
    return true;
}

bool myCircularQueueDeQueue(MyCircularQueue* obj) {
    if (myCircularQueueIsEmpty(obj)) return false;
    obj->front = (++obj->front) % (obj->k + 1);
    return true;
}

int myCircularQueueFront(MyCircularQueue* obj) {
    if (myCircularQueueIsEmpty(obj)) return -1;
    return obj->a[obj->front];
}

int myCircularQueueRear(MyCircularQueue* obj) {
    if (myCircularQueueIsEmpty(obj)) return -1;
    return obj->a[(obj->rear - 1 + obj->k + 1) % (obj->k + 1)];
}

void myCircularQueueFree(MyCircularQueue* obj) {
    free(obj->a);
    free(obj);
}

注:队列和栈均属于线性数据结构,循环队列亦为线性结构。内存分配后务必释放,避免泄漏。

目录

  1. 理论部分
  2. 栈的模拟实现
  3. STL 中的栈容器
  4. 队列的模拟实现
  5. STL 中的队列容器
  6. 作业部分
  7. 力扣 有效的括号
  8. 力扣 用栈实现队列
  9. 力扣 设计循环队列
  • 💰 8折买阿里云服务器限时8折了解详情
  • GPT-5.5 超高智商模型1元抵1刀ChatGPT中转购买
  • 代充Chatgpt Plus/pro 帐号了解详情
  • 🤖 一键搭建Deepseek满血版了解详情
  • 一键打造专属AI 智能体了解详情
极客日志微信公众号二维码

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

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

更多推荐文章

查看全部
  • Claude Code 终端 AI 编程助手使用指南与功能详解
  • 45 岁程序员求职困境:技术精湛为何难获面试机会
  • llama.cpp Docker 镜像国内加速下载方案
  • Agent Memory 相关文献追踪:异构存储与经验记忆
  • 多模态 Agent 图像识别 Skills 开发实战:JavaScript+Python 全栈方案
  • HTTP 应用层协议详解与简易服务器实现
  • 人工智能三大核心要素:算力、算法与数据的协同演进逻辑
  • 大模型训练全流程指南:预训练与指令微调
  • Android WebView 核心配置与实战要点
  • Google GenAI Toolbox:企业级 AI 数据库中间件与 LLM-SQL 安全互联实践
  • SpringBoot 整合 LangChain4j 与 Tavily 实现联网搜索及 API Key 获取指南
  • LangChain4j 集成国产大模型(通义千问、文心一言、智谱 AI)实战
  • npm 全局包安装时 Git SSH 公钥权限拒绝错误排查
  • ClawdBot 本地离线部署指南:Docker 一键启动与 Web UI 配置
  • Nginx 是什么:核心定位、使用场景与配置详解
  • JDK 17 下载与安装详细教程
  • Go 语言泛型与 WebAssembly 应用指南
  • Midjourney Imagine API 申请流程与使用详解
  • VS Code 中切换或退出 GitHub Copilot 账号的方法
  • AI 应用开发工程师(Agent 方向):核心技能与实战项目

相关免费在线工具

  • 加密/解密文本

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