数据结构之队列的实现(附源码)

目录

一、队列的概念及结构

二、队列的实现

 拓展:循环队列

三、初学的队列以及栈和队列结合的练习题


一、队列的概念及结构

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

二、队列的实现

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

 具体代码如下(C语言实现):

#pragma once//Queue.h
// 链式结构:表示队列#include <stdio.h>
#include <stdlib.h>
#include <assert.h>typedef int QDateType;typedef struct QListNode
{struct QListNode* _next;QDateType _data;
}QNode;// 队列的结构 
typedef struct Queue
{QNode* _front;//队头QNode* _rear;//队尾int size;
}Queue;// 初始化队列 
void QueueInit(Queue* q);
// 队尾入队列 
void QueuePush(Queue* q, QDateType data);
// 队头出队列 
void QueuePop(Queue* q);
// 获取队列头部元素 
QDateType QueueFront(Queue* q);
// 获取队列队尾元素 
QDateType QueueBack(Queue* q);
// 获取队列中有效元素个数 
int QueueSize(Queue* q);
// 检测队列是否为空,如果为空返回非零结果,如果非空返回0 
int QueueEmpty(Queue* q);
// 销毁队列 
void QueueDestroy(Queue* q);
//Queue.c
#include "Queue.h"void QueueInit(Queue* q)
{assert(q);q->_front = NULL;q->_rear = NULL;q->size = 0;
}void QueuePush(Queue* q, QDateType data)
{assert(q);QNode* tmp = (QNode*)malloc(sizeof(QNode));if (tmp == NULL){perror("tmp malloc");exit(-1);}tmp->_data = data;tmp->_next = NULL;if (q->_rear == NULL){q->_front = q->_rear = tmp;}else{q->_rear->_next = tmp;q->_rear = tmp;}q->size++;
}void QueuePop(Queue* q)
{assert(q);assert(QueueEmpty(q));if (q->_front->_next == NULL){free(q->_front);q->_front = q->_rear = NULL;}else{QNode* next = q->_front->_next;free(q->_front);q->_front = next;}q->size--;
}QDateType QueueFront(Queue* q)
{assert(q);assert(QueueEmpty(q));return q->_front->_data;
}QDateType QueueBack(Queue* q)
{assert(q);assert(QueueEmpty(q));return q->_rear->_data;
}int QueueSize(Queue* q)
{assert(q);return q->size;
}int QueueEmpty(Queue* q)
{assert(q);return q->size;
}void QueueDestroy(Queue* q)
{assert(q);QNode* cur = q->_front;while (cur){Queue* next = cur->_next;free(cur);cur = next;}q->_front = q->_rear = NULL;q->size = 0;
}
//test.c
#include "Queue.h"void test02()
{Queue q1;QueueInit(&q1);QueuePush(&q1, 1);QueuePush(&q1, 2);QueuePush(&q1, 3);QueuePush(&q1, 4);QueuePush(&q1, 5);QueuePop(&q1);while (QueueEmpty(&q1)){printf("%d ", QueueFront(&q1));QueuePop(&q1);}printf("\n");QueueDestroy(&q1);
}int main()
{test02();return 0;
}

 拓展:循环队列

如上图所示:循环队列的节点数一般会比要求的节点数多一个,以便区分空的循环队列和满的循环队列。空的循环队列front和rear指向同一个节点,满的循环队列可以理解为rear = front + 1。

三、初学的队列以及栈和队列结合的练习题

题目一:设计循环队列

  • MyCircularQueue(k): 构造器,设置队列长度为 k 。
  • Front: 从队首获取元素。如果队列为空,返回 -1 。
  • Rear: 获取队尾元素。如果队列为空,返回 -1 。
  • enQueue(value): 向循环队列插入一个元素。如果成功插入则返回真。
  • deQueue(): 从循环队列中删除一个元素。如果成功删除则返回真。
  • isEmpty(): 检查循环队列是否为空。
  • isFull(): 检查循环队列是否已满。
typedef struct 
{int* a;int front;int rear;int k;
} MyCircularQueue;MyCircularQueue* myCircularQueueCreate(int k) 
{MyCircularQueue* obj = (MyCircularQueue*)malloc(sizeof(MyCircularQueue));obj->a = (int*)malloc(sizeof(int)*(k+1));obj->front = obj->rear = 0;obj->k = k;return obj;
}bool myCircularQueueIsEmpty(MyCircularQueue* obj) 
{//front和rear相等即为空return obj->front == obj->rear;    
}bool myCircularQueueIsFull(MyCircularQueue* obj) 
{//数学方法判满return (obj->rear + 1) % (obj->k + 1) == obj->front;
}bool myCircularQueueEnQueue(MyCircularQueue* obj, int value) 
{if(myCircularQueueIsFull(obj))return false;obj->a[obj->rear] = value;++obj->rear;//不然rear可能越界obj->rear %= (obj->k+1);return true;
}bool myCircularQueueDeQueue(MyCircularQueue* obj) 
{if(myCircularQueueIsEmpty(obj))return false;obj->front++;obj->front %= (obj->k+1);return true; 
}int myCircularQueueFront(MyCircularQueue* obj) 
{if(myCircularQueueIsEmpty(obj))return -1;elsereturn obj->a[obj->front];
}int myCircularQueueRear(MyCircularQueue* obj) 
{if(myCircularQueueIsEmpty(obj))return -1;else//数学方法return obj->a[(obj->rear + obj->k) % (obj->k + 1)];
}void myCircularQueueFree(MyCircularQueue* obj) 
{free(obj->a);free(obj);
}

题目二:用队列实现栈

思路:用两个队列,保持一个队列为空一个不为空,当要出栈的时候就将不为空的队列中除了队尾的元素全都入到为空的队列中,然后将唯一的那个元素出栈。

typedef int QDateType;typedef struct QListNode
{struct QListNode* _next;QDateType _data;
}QNode;// 队列的结构 
typedef struct Queue
{QNode* _front;QNode* _rear;int size;
}Queue;void QueueInit(Queue* q)
{assert(q);q->_front = NULL;q->_rear = NULL;q->size = 0;
}void QueuePush(Queue* q, QDateType data)
{assert(q);QNode* tmp = (QNode*)malloc(sizeof(QNode));if (tmp == NULL){perror("tmp malloc");exit(-1);}tmp->_data = data;tmp->_next = NULL;if (q->_rear == NULL){q->_front = q->_rear = tmp;}else{q->_rear->_next = tmp;q->_rear = tmp;}q->size++;
}void QueuePop(Queue* q)
{assert(q);assert(QueueEmpty(q));if (q->_front->_next == NULL){free(q->_front);q->_front = q->_rear = NULL;}else{QNode* next = q->_front->_next;free(q->_front);q->_front = next;}q->size--;
}QDateType QueueFront(Queue* q)
{assert(q);assert(QueueEmpty(q));return q->_front->_data;
}QDateType QueueBack(Queue* q)
{assert(q);assert(QueueEmpty(q));return q->_rear->_data;
}int QueueSize(Queue* q)
{assert(q);return q->size;
}int QueueEmpty(Queue* q)
{assert(q);return q->size;
}void QueueDestroy(Queue* q)
{assert(q);QNode* cur = q->_front;while (cur){Queue* next = cur->_next;free(cur);cur = next;}q->_front = q->_rear = NULL;q->size = 0;
}typedef struct 
{Queue q1;Queue q2;
} MyStack;MyStack* myStackCreate() 
{MyStack* tmp = (MyStack*)malloc(sizeof(MyStack));QueueInit(&tmp->q1);QueueInit(&tmp->q2);return tmp;
}void myStackPush(MyStack* obj, int x) 
{if(QueueEmpty(&obj->q1)){QueuePush(&obj->q1, x);}else{QueuePush(&obj->q2, x);}
}int myStackPop(MyStack* obj) 
{Queue* empty = &obj->q1;Queue* noempty = &obj->q2;if(QueueEmpty(&obj->q1)){empty = &obj->q2;noempty = &obj->q1;}while(QueueSize(noempty) > 1){QueuePush(empty, QueueFront(noempty));QueuePop(noempty);}int top = QueueFront(noempty);QueuePop(noempty);return top;
}int myStackTop(MyStack* obj) 
{if(QueueEmpty(&obj->q1))return QueueBack(&obj->q1);elsereturn QueueBack(&obj->q2);
}bool myStackEmpty(MyStack* obj) 
{int ret1, ret2;if(QueueEmpty(&obj->q1) == 0)ret1 = 0;elseret1 = 1;if(QueueEmpty(&obj->q2) == 0)ret2 = 0;elseret2 = 1;if(ret1 == 0 && ret2 == 0)return true;elsereturn false;
}void myStackFree(MyStack* obj) 
{QueueDestroy(&obj->q1);QueueDestroy(&obj->q2);free(obj);
}

题目三:用栈实现队列

思路:使用两个栈,一个push栈一个pop栈,先往push栈中堆入元素,出队时,先将push栈中的元素先pop到pop栈中,再从pop栈中pop元素,其间再有元素堆入入到push栈中。

typedef int STDataType;
typedef struct Stack
{STDataType* _a;int _top;		// 栈顶int _capacity;  // 容量 
}Stack;void StackInit(Stack* ps)
{assert(ps);ps->_a = NULL;ps->_top = 0;ps->_capacity = 0;
}void StackPush(Stack* ps, STDataType data)
{assert(ps);if (ps->_capacity == ps->_top){int newCapacity = ps->_capacity == 0 ? 4 : ps->_capacity * 2;STDataType* tmp = (STDataType*)realloc(ps->_a,sizeof(STDataType) * newCapacity);if (tmp == NULL){perror("realloc fail");exit(-1);}ps->_a = tmp;ps->_capacity = newCapacity;}ps->_a[ps->_top] = data;ps->_top++;
}void StackPop(Stack* ps)
{assert(ps);assert(ps->_top > 0);ps->_top--;
}STDataType StackTop(Stack* ps)
{assert(ps);assert(ps->_top > 0);return ps->_a[ps->_top - 1];
}int StackSize(Stack* ps)
{assert(ps);return ps->_top;
}int StackEmpty(Stack* ps)
{return ps->_top;
}void StackDestroy(Stack* ps)
{assert(ps);free(ps->_a);ps->_a = NULL;ps->_capacity = 0;ps->_top = 0;
}typedef struct 
{Stack pushst;Stack popst;
} MyQueue;MyQueue* myQueueCreate() 
{MyQueue* obj = (MyQueue*)malloc(sizeof(MyQueue));StackInit(&obj->pushst);StackInit(&obj->popst);return obj;
}void myQueuePush(MyQueue* obj, int x) 
{StackPush(&obj->pushst, x);
}int myQueuePeek(MyQueue* obj) 
{//pop栈为空就往其中堆入元素if(StackEmpty(&obj->popst) == 0){while(StackEmpty(&obj->pushst) > 0){StackPush(&obj->popst, StackTop(&obj->pushst));StackPop(&obj->pushst);}}return StackTop(&obj->popst);
}int myQueuePop(MyQueue* obj) 
{int front = myQueuePeek(obj);StackPop(&obj->popst);return front;
}bool myQueueEmpty(MyQueue* obj) 
{int ret1, ret2;if(StackEmpty(&obj->pushst) == 0)ret1 = 0;elseret1 = 1;if(StackEmpty(&obj->popst) == 0)ret2 = 0;elseret2 = 1;if(ret1 == 0 && ret2 == 0)return true;elsereturn false; 
}void myQueueFree(MyQueue* obj) 
{StackDestroy(&obj->pushst);StackDestroy(&obj->popst);free(obj);
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/102834.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

processflow流程图多人协作预热

前言 在线上办公如火如荼的今天&#xff0c;多人协作功能是每个应用绕不开的门槛。processflow在线流程图&#xff08;前身基于drawio二次开发&#xff09;沉寂两年之久&#xff0c;经过长时间设计开发&#xff0c;调整&#xff0c;最终完成了多人协作的核心模块设计。废话不多…

基于网络表示学习的 新闻推荐算法研究与系统实现

摘要 第1章绪论 新闻推荐通常是利用用户的阅读行为和习惯、阅读选择和爱好等信息,为 用户推荐新闻内容。新闻推荐能够减少用户在数量庞大数据信息中获取信息的 时间消耗,从而能够缓解“信息过载[7]”的难题。以文本为内容的新闻,和商品、 电影、短视频等推荐系统相比,新闻推…

【LeetCode】202. 快乐数 - hash表 / 快慢指针

目录 2023-9-5 09:56:152023-9-6 19:40:51 202. 快乐数 2023-9-5 09:56:15 关键是怎么去判断循环&#xff1a; hash表&#xff1a; 每次生成链中的下一个数字时&#xff0c;我们都会检查它是否已经在哈希集合中。 如果它不在哈希集合中&#xff0c;我们应该添加它。如果它在…

966SEO扫地僧站群·万能HTML模板[V1.9.1]

扫地僧站群万能HTML模板是一款站点管理软件,其主要特点是可以将原始的html模板放入程序中,无需编写任何标签,程序会全自动替换处理,从而快速构建出一个完整的网站,这种模式相对于传统的网站建设方式更加快速、简单,同时可以大幅度降低网站建设的成本和难度.服务器及域名量的配置…

PaddleOCR学习笔记2-初步识别服务

今天初步实现了网页&#xff0c;上传图片&#xff0c;识别显示结果到页面的服务。后续再完善。 采用flask paddleocr bootstrap快速搭建OCR识别服务。 代码结构如下&#xff1a; 模板页面代码文件如下&#xff1a; upload.html : <!DOCTYPE html> <html> <…

[git] 如何克隆仓库,进行项目撰写,并绑定自己的远程仓库

摘要&#xff1a;删除.git文件&#xff0c;才可重新绑定远程仓库。 具体步骤&#xff1a; 文件夹右键&#xff0c;进入”Git Bash Here“执行命令 1. 执行 ”git clone 仓库地址“&#xff0c;克隆仓库 2. 在生成的仓库中&#xff0c;删除 .git 文件 3. git init 初始化仓库…

Leetcode.174 地下城游戏

题目链接 Leetcode.174 地下城游戏 hard 题目描述 恶魔们抓住了公主并将她关在了地下城 d u n g e o n dungeon dungeon 的 右下角 。地下城是由 m x n 个房间组成的二维网格。我们英勇的骑士最初被安置在 左上角 的房间里&#xff0c;他必须穿过地下城并通过对抗恶魔来拯救公…

Spring MVC入门必读:实现增删改查

目录 引言 一、前期准备 1.1.搭建Maven环境 1.2.导入pom.xml依赖 1.3.导入配置文件 ①jdbc.properties ②generatorConfig.xml ③log4j2.xml ④spring-mybatis.xml ⑤spring-context.xml ⑥spring-mvc.xml ⑦修改web.xml文件 二、逆向生成增删改查 2.1.导入相关u…

【数据结构与算法系列5】螺旋矩阵II (C++ Python)

给你一个正整数 n &#xff0c;生成一个包含 1 到 n2 所有元素&#xff0c;且元素按顺时针顺序螺旋排列的 n x n 正方形矩阵 matrix 。 示例 1&#xff1a; 输入&#xff1a;n 3 输出&#xff1a;[[1,2,3],[8,9,4],[7,6,5]]示例 2&#xff1a; 输入&#xff1a;n 1 输出&am…

Linux-Shell整理集合

Shell变量 参考文章&#xff1a; Shell脚本中变量的使用 shell语法之 , ‘ ‘ , {},, ,‘‘,(),$(())四种语法含义 参考文章&#xff1a; shell语法之 , ‘ ‘ , {},, ,‘‘,(),$(())四种语法含义 grep常用用法 Shell awk命令详解 grep 跟awk连着用&#xff1a; 获取某程序的…

Scala的函数式编程与高阶函数,匿名函数,偏函数,函数的闭包、柯里化,抽象控制,懒加载等

Scala的函数式编程 函数式编程 解决问题时&#xff0c;将问题分解成一个一个的步骤&#xff0c;将每个步骤进行封装&#xff08;函数&#xff09;&#xff0c;通过调用这些封装好的步骤&#xff0c;解决问题。 例如&#xff1a;请求->用户名、密码->连接 JDBC->读取…

消息队列理解

rocketMQ RocketMQ消息存储原理_码上得天下的博客-CSDN博客 领域模型概述 | RocketMQ kafka Kafka基本架构介绍-腾讯云开发者社区-腾讯云 看完这篇Kafka&#xff0c;你也许就会了Kafka_心的步伐的博客-CSDN博客 Apache Kafka