栈与队列:数据结构入门指南

1.栈

1.1栈的概念及结构

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

压栈:栈的插入操作叫做进栈/压栈/入栈,入数据在栈顶。

出栈:栈的删除操作叫做出栈。出数据也在栈顶。

1.2栈的实现

栈的实现一般可以使用数组或者链表实现,相对而言数组的结构实现更优一些。因为数组在尾上插入数据的 代价比较小

复制代码
c 复制代码
// 栈结构初始化与销毁

void STInit(ST* pst)
{
    assert(pst);
    pst->a = NULL;
    pst->top = 0;        // top指向栈顶元素的下一个位置
    pst->capacity = 0;
}

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

// 栈操作函数

void STPush(ST* pst, STDataType x)
{
    assert(pst);
    
    // 检查并处理容量不足的情况
    if (pst->top == pst->capacity)
    {
        int newcapacity = pst->capacity == 0 ? 4 : pst->capacity * 2;
        STDataType* tmp = (STDataType*)realloc(pst->a, newcapacity * sizeof(STDataType));
        if (!tmp)
        {
            perror("realloc fail");
            return;
        }
        pst->a = tmp;
        pst->capacity = newcapacity;
    }
    
    pst->a[pst->top++] = x;
}

void STPop(ST* pst)
{
    assert(pst && pst->top > 0);
    --pst->top;
}

STDataType STTop(ST* pst)
{
    assert(pst && pst->top > 0);
    return pst->a[pst->top - 1];
}

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

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

2.队列

2.1队列的概念及结构

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

2.2队列的实现

队列也可以数组和链表的结构实现,使用链表的结构实现更优一些,因为如果使用数组的结构,出队列在数 组头上出数据,效率会比较低。

采用链表实现队列的方法与实现栈的方法类似,分别用两个指针指向队列的首元素与尾元素,如下图所示。用pHead来指向队列的首元素,用pEnd来指向队列的尾元素。

c 复制代码
// 初始化队列
void QueueInit(Queue* pq)
{
    assert(pq);
    pq->phead = NULL;
    pq->ptail = NULL;
    pq->size = 0;
}

// 销毁队列
void QueueDestroy(Queue* pq)
{
    assert(pq);
    QNode* cur = pq->phead;
    while (cur)
    {
        QNode* next = cur->next;
        free(cur);
        cur = next;
    }
    pq->phead = pq->ptail = NULL;
    pq->size = 0;
}

// 入队操作
void QueuePush(Queue* pq, QDataType x)
{
    assert(pq);
    QNode* newnode = (QNode*)malloc(sizeof(QNode));
    if (!newnode)
    {
        perror("malloc fail");
        return;
    }
    
    newnode->next = NULL;
    newnode->val = x;
    
    if (!pq->ptail)
    {
        pq->phead = pq->ptail = newnode;
    }
    else
    {
        pq->ptail->next = newnode;
        pq->ptail = newnode;
    }
    pq->size++;
}

// 出队操作
void QueuePop(Queue* pq)
{
    assert(pq && pq->size > 0);
    
    if (!pq->phead->next)  // 单节点情况
    {
        free(pq->phead);
        pq->phead = pq->ptail = NULL;
    }
    else  // 多节点情况
    {
        QNode* next = pq->phead->next;
        free(pq->phead);
        pq->phead = next;
    }
    pq->size--;
}

// 获取队首元素
QDataType QueueFront(Queue* pq)
{
    assert(pq && pq->phead);
    return pq->phead->val;
}

// 获取队尾元素
QDataType QueueBack(Queue* pq)
{
    assert(pq && pq->ptail);
    return pq->ptail->val;
}

// 获取队列大小
int QueueSize(Queue* pq)
{
    assert(pq);
    return pq->size;
}

// 判断队列是否为空
bool QueueEmpty(Queue* pq)
{
    assert(pq);
    return pq->size == 0;
}
 
相关推荐
http阿拉丁神猫4 小时前
Go语言入门笔记:从基础到开发环境搭建(二)
开发语言·笔记·golang
HRBorderInsight7 小时前
马来西亚人均收入一个月多少钱,个人薪资和家庭收入要分开看
经验分享·笔记
又見山9 小时前
本地 Markdown 与数据主权:你的笔记到底属于谁
笔记·obsidian
撩得Android一次心动10 小时前
Jetpack Compose 知识点整理2【个人用】
android·笔记·学习·kotlin·compose
cao233310 小时前
关于 x1 y1 等变量名冲突的指正(校对版)
笔记
quaer11 小时前
弗洛伊德算法--判圈法寻找环的入口O(n) O(1)
数据结构·算法
Demons_kirit11 小时前
CTFHub 信息泄露通关笔记:Git泄露 Log - 教程
笔记·git·网络安全
德思特12 小时前
2026 低空经济无人机与 eVTOL GNSS 模拟器选型指南:四大硬核标准与设备推荐
经验分享·gnss
xhyu6112 小时前
【学习笔记】图像质量评估方法 (5.生成图像是否符合用户要求)
笔记·学习·计算机视觉
恒锐丰科技林技术员13 小时前
EG2103 高压 MOS/IGBT 驱动芯片解析:半桥驱动的高性价比之选
经验分享·嵌入式硬件·硬件工程