当前位置: 首页 > news >正文

【数据结构入门】栈和队列

目录

1.栈

2. 栈的实现

3.队列

4.队列的实现

1.栈

        一种特殊的线性表,只允许在一端进行插入和删除操作,进行插入删除的一端称作栈顶,另一端称作栈底

        

既然是线性表,那么可以使用链表和数组来实现栈;

若使用数组,那么数组靠后的部分做栈顶,如此一来每次插入数组每次插入数据不需要挪动元素。

若使用单链表,那么单链表靠头的部分作为栈顶比较合适,当删除数据的时候只需要从头开始删除就可以了。

如果用双向链表,那么哪一个部分做栈顶都无所谓,因为每一个节点都可以找到prev。

        这里建议用数组实现,因为最简单。

2. 栈的实现

        这里选择使用数组来实现,栈顶下标默认是0,每次增加一个元素就+1,此时栈顶下标也是栈元素的个数。

①入栈:首先判断传入指针是否为空,然后如果capacity和栈元素个数top相同,那么就扩容;不需要扩容那就将top下标位置的元素赋值为相应元素。

②出栈:若top为0,说明栈内没有元素,若有元素直接将top--即可。

③得到栈大小:返回top即可。

④栈是否为空:若top为0就是空返回1,否则返回0。

⑤获取栈顶数据:直接返回top-1下标的数据即可。

#define _CRT_SECURE_NO_WARNINGS
#include"stack.h"// 初始化
void InitStack(Stack* stk)
{assert(stk);stk->_a = malloc(sizeof(dataType) * 4);stk->_capacity = 4;stk->_top = 0;// 栈顶元素下标为0
}
// 销毁
void DestroyStack(Stack* stk)
{assert(stk);free(stk->_a);stk->_a = NULL;stk->_capacity = stk->_top = 0;
}
// 入栈
void PushStack(Stack* stk, dataType x)
{assert(stk);if (stk->_capacity == stk->_top) // 容量和栈元素个数相等,就扩容{stk->_capacity *= 2;dataType* tmp = (dataType*)realloc(stk->_a, sizeof(dataType) * stk->_capacity);if (tmp){printf("内存不足!");exit(-1);}else{stk->_a = tmp;}}// 正常插入stk->_a[stk->_top] = x;stk->_top++;}
// 出栈
void PopStack(Stack* stk)
{assert(stk);assert(stk->_top > 0);// 有元素才能删除stk->_top--;
}
// 栈的元素个数
int SizeStack(Stack* stk) 
{assert(stk);return stk->_top;
}
// 栈是否为空
void isEmpty(Stack* stk) 
{assert(stk);return stk->_top == 0 ? 1 : 0; // 没有元素就是空
}
// 获取栈顶数据
dataType getTop(Stack* stk) 
{ assert(stk);if (stk->_top > 0){return stk->_a[stk->_top - 1];}else {return NULL;}
}

3.队列

进行插入操作的一端称为队尾,进行删除操作一端称作队头。

        当然队列可以用数组和链表来实现,如果使用数组,可以有两种方法实现:

①每次插入数据的时候,依次插入即可,出队的时候需要移动后面的数据将前面的数据进行覆盖从而达到出队的效果;

②或者直接指定一个下标,每次出队,将下标后移,但是这样的话,每次出队都会浪费一个空间。

所以数组实现队列是一个不好的选择。

        这里使用单链表进行实现,我们可以维护两个指针,一个指向队头,一个指向队尾,当入队的时候可以使用队尾指针,当出队的时候,可以使用队头指针。

        所以这里推荐使用单链表+两个指针就能实现队列。

4.队列的实现

        我们使用两个结构体来完成队列,第一个结构体代表队列的节点,包含数据和next指针;

第二个结构体代表整个队列,包含头指针和尾指针;

①初始化队列:将头尾指针置空。

②销毁队列:从头指针开始当当前指针不为空就直接销毁,最后将头尾指针置空。

③队列入队:如果此时队列为空(head == NULL),将新节点作为头尾指针;如果队列不为空,只需要旧的尾结点的next指向新节点,同时新节点为tail。

④队列出队:将头指针的next保存下来,将头指针释放,更新头指针,若在更新的过程中将最后一个节点删除,即head为NULL,此时需要将tail也置为空,为了保持程序的合理运行,在程序开始之前需要判断head不为空。

⑤获取队头元素:当队头不为空,返回队头的值,队尾同理不再赘述。

⑥判空:其实就是判断头指针是否为空,为空返回1,不为空返回0。

⑦求队列长度:用一个指针遍历即可。

#define _CRT_SECURE_NO_WARNINGS
#include"queue.h"void QueInit(Queue* pq)
{assert(pq);pq->head = pq->tail = NULL;
}void QueDestroy(Queue* pq)
{assert(pq);QueueNode* curr = pq->head;while (curr){QueueNode* next = curr->next;free(curr);curr = next;}pq->head = pq->tail = NULL;
}void QuePush(Queue* pq, dataType x)
{assert(pq);QueueNode* newNode = (QueueNode*)malloc(sizeof(QueueNode));newNode->data = x;newNode->next = NULL;if (pq->head == NULL) // 如果队列为空,插入一个节点{pq->head = pq->tail = newNode;}else{pq->tail->next = newNode; // 队列不为空,tail插入节点pq->tail = newNode;}
}
void QuePop(Queue* pq)
{assert(pq);assert(pq->head);QueueNode* next = pq->head->next;free(pq->head);pq->head = next;if (pq->head == NULL){// tail   head == NULL,删除的过程中,删除到最后一个的时候需要将tail置空pq->tail = NULL;}}
dataType QueFront(Queue* pq) 
{assert(pq);assert(pq->head);return pq->head->data;
}
dataType QueBack(Queue* pq) 
{assert(pq);assert(pq->tail);return pq->tail->data;
}
int isEmpty(Queue* pq) 
{assert(pq);if (pq->head == NULL) {return 1;}else{return 0;}
}
int QueSize(Queue* pq) 
{assert(pq);QueueNode* curr = pq->head;int size = 0;while (curr) {curr = curr->next;size++;}return size;
}

        下一期内容,将栈和队列的OJ题进行详解。

http://www.dtcms.com/a/322807.html

相关文章:

  • 网盘短剧资源转存项目源码 支持垮克 带后台 附教程
  • Kafka服务端NIO操作原理解析(二)
  • MX 播放器:安卓设备上的全能视频播放器
  • 【解决方法】华为电脑的亮度调节失灵
  • 本地部署接入 whisper + ollama qwen3:14b 总结字幕
  • 服务机器人选择屏幕的逻辑
  • 微软推出革命性AI安全工具Project IRE,重塑网络安全防御新范式
  • Orange的运维学习日记--37.iSCSI详解与服务部署
  • FreeRTOS学习笔记:任务通知和软件定时器
  • jQuery 零基础学习第一天
  • 数据结构—二叉树及gdb的应用
  • 【贪心】P4873 [USACO14DEC] Cow Jog G|省选-
  • MBR分区nvme固态硬盘安装win7--非UEFI启动和GPT分区
  • llm本地部署+web访问+交互
  • Oracle字段操作
  • [TryHackMe]Challenges---Game Zone游戏区
  • 力扣热题100-----118.杨辉三角
  • Kettle ETL 工具存在的问题以及替代方案的探索
  • Arm Development Studio 安全通告:CVE-2025-7427
  • 什么情况下需要JVM调优?
  • Java-file类
  • 力扣 30 天 JavaScript 挑战 第二题笔记
  • 每日算法刷题Day59:8.9:leetcode 队列8道题,用时2h30min
  • 【攻防实战】从外到内全链路攻防实战纪实
  • python---类型别名
  • 1073. 沙漏
  • sqli-labs通关笔记-第40关 GET字符型堆叠注入(单引号括号闭合 手工注入+脚本注入两种方法)
  • J2000平赤道系、瞬时平赤道系与瞬时真赤道系
  • (论文速读)重新思考CNN生成网络中的上采样操作
  • 优先队列,链表优化