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

数据结构之三:栈和队列

线性表:有个n个元素的集合,逻辑上成线性结构。(顺序表、链表、栈、队列、串)。

:一种特殊的线性表,其只允许在固定的一端进行插入和删除元素操作。

进行数据插入和删除操作的一端称为栈顶,另一端称为栈底

栈中的数据元素遵守后进先出LIFO(Last In First Out)的原则。

数组来实现:

链表来实现:

  • 如果是双向链表,那么哪边是栈顶,哪边是栈底都无所谓。
  • 如果是单链表: 

实现栈数组更加简单(对于当代的计算机,内存开辟带来的时间开销可以忽略不计)。

头文件
#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>typedef int STDataType;
#define N 4/*
静态
struct Stack
{int* _a[N};int _size;//
};
*/
typedef struct Stack
{STDataType* _a;int _top;		//栈顶下标int _capacity;	//容量
}Stack;void StackInit(Stack* pst);
void StackDestory(Stack* ppst);
void StackPush(Stack* pst, STDataType x);
void StackPop(Stack* pst);
int StackSize(const Stack* pst);//返回1是空,返回0是非空
int StackEmpty(Stack* pst);
//获取栈顶数据
STDataType StackTop(Stack* pst);
实现 
#define _CRT_SECURE_NO_WARNINGS#include "stack.h"void StackInit(Stack* pst)
{assert(pst);pst->_a = (STDataType*)malloc(sizeof(int) * N);pst->_capacity = N;pst->_top = 0;//初始0:top在栈顶的下一个位置//初始1:top在栈顶位置
}void StackDestory(Stack* pst)
{assert(pst);free(pst->_a);pst->_a = NULL;pst->_capacity = 0;pst->_top = -1;}void StackPush(Stack* pst, STDataType x)
{assert(pst);if (pst->_top == pst->_capacity){pst->_capacity *= 2;STDataType* tmp= (STDataType*)realloc(pst->_a, sizeof(STDataType) * pst->_capacity);if (tmp == NULL){printf("内存不足\n");exit(-1);}else{pst->_a = tmp;}}pst->_a[pst->_top] = x;pst->_top++;
}void StackPop(Stack* pst)
{assert(pst);assert(pst->_top > 0);//if(pst->_top>0)pst->_top--;
}int StackSize(const Stack* pst)
{assert(pst);return pst->_top;
}
STDataType StackTop(Stack* pst)
{assert(pst);assert(pst->_top > 0);return pst->_a[pst->_top - 1];
}
int StackEmpty(Stack* pst)
{assert(pst);return !pst->_top;
}

队列

 队列:只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表

队列具有先进先出FIFO(First In First Out)

  • 入队列:进行插入操作的一端称为队尾
  • 出队列:进行删除操作的一端称为队头

数组来实现:无论是哪一边做队头,都需要挪动数据,开销大效率低。(不挪动数据相对复杂)。

链表实现

 头文件
#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>typedef int QDataType;typedef struct QueueNode
{struct QueueNode* _next;QDataType _data;
}QueueNode;typedef struct Queue
{QueueNode* _head;QueueNode* _tail;
}Queue;void QueueInit(Queue* pq);
void QueueDestory(Queue* pq);
//出入队
void QueuePush(Queue* pq, QDataType x);
void QueuePop(Queue* pq);
QDataType QueueFront(Queue* pq);
QDataType QueueBack(Queue* pq);//返回1是空,返回0是非空
int QueueEmpty(Queue* pst);
//获取栈顶数据
QDataType QueueTop(Queue* pst);
实现
#define _CRT_SECURE_NO_WARNINGS
#include "queue.h"void QueueInit(Queue* pq)
{assert(pq);pq->_head = pq->_tail = NULL;
}
void QueueDestory(Queue* pq)
{assert(pq);QueueNode* cur = pq->_head;while (cur){QueueNode* next = cur->_next;free(cur);cur = next;}pq->_head = pq->_tail = NULL;
}
//出入队
void QueuePush(Queue* pq, QDataType x)
{assert(pq);QueueNode* newnode = (QueueNode*)malloc(sizeof(QueueNode));if (newnode == NULL){exit(-1);}newnode->_data = x;newnode->_next = NULL;if (pq->_head == NULL){pq->_head = pq->_tail = newnode;}else{pq->_tail->_next = newnode;pq->_tail = newnode;}
}
void QueuePop(Queue* pq)
{assert(pq);assert(pq->_head);QueueNode* next = pq->_head->_next;free(pq->_head);pq->_head = next;if (pq->_head == NULL){pq->_tail = NULL;}
}
QDataType QueueFront(Queue* pq)
{assert(pq&&pq->_head);return pq->_head->_data;
}
QDataType QueueBack(Queue* pq)
{assert(pq && pq->_tail);return pq->_tail->_data;
}//返回1是空,返回0是非空
int QueueEmpty(Queue* pq)
{return pq->_head == NULL ? 1 : 0;
}
//获取栈顶数据
QDataType QueueTop(Queue* pq)
{assert(pq);int sz = 0;QueueNode* cur = pq->_head;while (cur){sz++;cur = cur->_next;}return sz;
}

数据结构的栈和堆和内存中的堆栈有什么区别? 

  • 数据结构的栈、堆:存储和管理数据,解决一些一些问题。
  • 内存中的堆栈虚拟进程地址空间分段。一段内存区域的划分。

数据结构的栈和内存的栈都满足“后进先出”的规则。

循环队列

循环队列用数组实现更容易判断队列的空满。

 

typedef struct {int*_a;int front;int rear;int k;
} MyCircularQueue;bool myCircularQueueIsFull(MyCircularQueue* obj);
MyCircularQueue* myCircularQueueCreate(int k) {MyCircularQueue* q=(MyCircularQueue*)malloc(sizeof(MyCircularQueue));q->_a=(int*)malloc(sizeof(int)*(k+1));q->front=q->rear=0;q->k=k;return q;
}bool myCircularQueueEnQueue(MyCircularQueue* obj, int value) {if(myCircularQueueIsFull(obj)){return false;}else{obj->_a[obj->rear]=value;obj->rear = (obj->rear+1)%(obj->k+1);return true;}}bool myCircularQueueDeQueue(MyCircularQueue* obj) {if(obj->front==obj->rear){return false;}else{obj->front = (obj->front+1)%(obj->k+1);return true;}
}int myCircularQueueFront(MyCircularQueue* obj) {if(obj->front==obj->rear){return -1;}return obj->_a[obj->front];
}int myCircularQueueRear(MyCircularQueue* obj) {if(obj->front==obj->rear){return -1;}int tail=obj->rear-1;if(tail==-1){tail=obj->k;}return obj->_a[tail];
}bool myCircularQueueIsEmpty(MyCircularQueue* obj) {return obj->front==obj->rear;
}bool myCircularQueueIsFull(MyCircularQueue* obj) {return (obj->rear+1)%(obj->k+1)==obj->front;
}void myCircularQueueFree(MyCircularQueue* obj) {free(obj->_a);free(obj);
}


http://www.mrgr.cn/news/78835.html

相关文章:

  • Android 系统之Init进程分析
  • 黑马2024AI+JavaWeb开发入门Day04-SpringBootWeb入门-HTTP协议-分层解耦-IOCDI飞书作业
  • 2024年Android面试总结
  • C++分治思想
  • 基于Python的猎聘网招聘数据采集与可视化分析
  • Postgres数据库自动化分区
  • Web登录页面设计
  • 用go语言写一个小服务
  • 手机卡限速丨中国移动5G变3G,网速500kb
  • 单链表---移除链表元素
  • LearnOpenGL学习(光照 -- 颜色,基础光照,材质)
  • go使用mysql实现增删改查操作
  • 我们来学mysql -- 事务之概念(原理篇)
  • 深度学习 | pytorch + torchvision + python 版本对应及环境安装
  • spring boot3.3.5 logback-spring.xml 配置
  • create-vue创建vue3项目
  • 【2024】使用Docker搭建redis sentinel哨兵模式集群全流程(包含部署、测试、错误点指正以及直接部署)
  • dpwwn02靶场
  • uniapp手机端一些坑记录
  • 基于go语言探讨 Kubernetes 中 Rollout History 的实现与优化
  • Java启动通用参数,自动记录GC等信息到专门日志文件中
  • python学习笔记9-零散知识点
  • 微服务即时通讯系统的实现(服务端)----(2)
  • 工具:Zotero Better BibTex插件和Latex基础知识
  • 【动手学电机驱动】STM32-FOC(9)无感 FOC 电机转速调节
  • openjdk17 jvm堆空间分配