当前位置: 首页 > 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.lryc.cn/news/615417.html

相关文章:

  • 物理AI与人形机器人:从实验室到产业化的关键跨越
  • day15_keep going on
  • [激光原理与应用-202]:光学器件 - 增益晶体 - Nd:YVO₄增益晶体的制造过程与使用过程
  • RecyclerView 缓存机制
  • 202506 电子学会青少年等级考试机器人六级器人理论真题
  • 【自动化运维神器Ansible】playbook自动化部署Nginx案例解析:助力从零构建高效Web服务
  • Kettle ETL 工具存在的问题以及替代方案的探索
  • AWT 事件监听器深入浅出:Action/Mouse/Key/Window 全解析与实战
  • B2.0:对硬件学习的一些个人心得感悟
  • 跨境电商系统开发:ZKmall开源商城的技术选型与代码规范实践
  • Linux 中CentOS Stream 8 - yum -y update 异常报错问题
  • MySQL 主备(Master-Slave)复制 的搭建
  • 每日五个pyecharts可视化图表-line:从入门到精通
  • 基于springboot+vue开发的校园食堂评价系统【源码+sql+可运行】【50809】
  • 计算机系统设计中都有什么任务~计算密集~IO密集~逻辑密集等
  • 通过 Docker 运行 Prometheus 入门
  • 如何在 Excel 中快速求和?【图文详解】Excel求和技巧,Excel求和公式大全,多种方式求和
  • 轻松Linux-5.进程控制
  • drippingblues靶机
  • Easysearch 冷热架构实战
  • 从 AI 到实时视频通道:基于模块化架构的低延迟直播全链路实践
  • Docker容器lnmp平台部署discuz论坛
  • 配送算法10 Batching and Matching for Food Delivery in Dynamic Road Networks
  • 算法篇----分治(快排)
  • Java 大视界 -- Java 大数据在智能医疗手术机器人操作数据记录与性能评估中的应用(390)
  • 【能碳建设1】用AI+开源打造物联网+能碳管理+交易SaaS系统的最短路径实施指南
  • Mac屏幕取色不准?探究原理和换算规则
  • C++四种类型转换
  • 97-基于Python的大众点评数据分析预测系统
  • react之React.cloneElement()