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

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

目录

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.xdnf.cn/news/17511.html

相关文章:

  • 用天气预测理解分类算法-从出门看天气到逻辑回归
  • LeetCode111~130题解
  • Nginx 性能优化与动态内容处理
  • linux 操作ppt
  • 排序概念以及插入排序
  • C++-红黑树
  • 嵌入式 Linux Mender OTA 实战全指南
  • 上海AI Lab、浙大EagleLab等提出RRVF:利用「验证非对称性」,只输入图片学习视觉推理
  • 【LLM】Openai之gpt-oss模型和GPT5模型
  • NestJS Config 入门教程
  • 自动生成视频的AI大模型高效创作指南
  • Java Stream API 实战:提升集合处理的效率与可读性!
  • 微雪电子发布工业级ESP32-S3-POE工控板:8路隔离IO,双核240MHz赋能AIoT,一根网线解决供电与通信,工业物联网迎来高性价比控制新选择
  • 关键点检测(10)——yolov8-pose 复现coco-pose
  • 【QT】QMainWindow:打造专业级桌面应用的基石
  • Python基础教程(七)匹配模式:隐藏在结构之美中的编程革命
  • 实用Shell高级视频课程
  • 【CVPR2025】计算机视觉|PX:让模型训练“事半功倍”!
  • Uipath Studio中邮件自动化
  • 微信小程序中实现表单自动填充功能的方法
  • ABP VNext + Apache Kafka Exactly-Once 语义:金融级消息一致性实战
  • 在Docker中下载RabbitMQ(详细讲解参数)
  • 需求管理流程规范
  • Java-file类
  • Mybatis学习之自定义映射resultMap(七)
  • STM32CubeMX(十三)FatFs文件系统(SPI驱动W25Qxx)
  • BGP 笔记
  • 配送算法10 Batching and Matching for Food Delivery in Dynamic Road Networks
  • .NET程序跨平台ARM电脑上发布的程序格式是,so还是DLL?
  • stm32项目(24)——基于STM32的汽车CAN通信系统