【数据结构与算法】程序内功篇五--队列
程序内功篇五--队列
- 一、队列
- 1、队列原理
- 2、队列演示
- 二、顺序队列
- >1、顺序队列原理
- >2、顺序队列的创建
- >3、顺序队列的入队
- >4、顺序队列的出队
- >5、顺序队列的释放
- >6、顺序队列的清空
- >7、队列是否为空的判断
- >8、队列是否为满的判断
- 三、链表队列
- >1、链表队列的原理
- >2、链表队列的操作演示
- >3、链表队列的创建
- >4、链表队列的入队
- >5、链表队列的出队
- >6、链表队列的释放
- >7、链表队列的清空
- >8、判断链表队列是否为空
- 四、链表的应用--球钟问题
- 1、球钟简介
- 2、球钟工作原理
- 3、问题阐述
- 4、程序实现
一、队列
1、队列原理
队列
是限制在两端
进行插入操作
和删除操作
的线性表
允许进行
存入操作
的一端称为“队尾
”
允许进行
删除操作
的一端称为“队头
”
当线性表中
没有元素
时,称为“空队
”
特点 :先进先出(
FIFO
)
2、队列演示
二、顺序队列
>1、顺序队列原理
规定:
front指向队头元素的位置; rear指向队尾元素的下一个位置。
在队列操作过程中,为了提高效率,以调整指针代替队列元素的移动,并将
数组
作为循环队列
的操作空间。
为区别空队
和满队
,满队元素个数比数组元素个数少一个。
因此顺序队列
的结构体
定义为:
#define DEBUG 1 //1-打开debug,0关闭debug
typedef int data_t ; /*定义队列中数据元素的数据类型*/
#define N 64 /*定义队列的容量*/
typedef struct {data_t data[N] ; /*用数组作为队列的储存空间*/int front, rear ; /*指示队头位置和队尾位置的指针*/
} s_queue,*squeue ; /*顺序队列类型定义*/
>2、顺序队列的创建
/*** @description: 顺序队列的创建* @param {*}* @return {squeue-队列指针}*/
squeue squeue_create()
{squeue queue = (squeue)malloc(sizeof(s_queue));if(queue == NULL){#if DEBUGprintf("squeue create error!\n");#endifreturn 0;}memset(queue->data,0,sizeof(queue->data)); queue->front = queue->rear =0;return queue;
}
>3、顺序队列的入队
/*** @description: 入顺序队列* @param {squeue} queue-队列指针* @param {data_t} value-入队列的值* @return {0-函数失败,1-函数成功}*/
int squeue_enter(squeue queue, data_t value)
{if(queue == NULL){#if DEBUGprintf("squeue create error!\n");#endifreturn 0;}if((queue->rear+1)%N == queue->front){#if DEBUGprintf("squeue already full!\n");#endifreturn 0;}queue->data[queue->rear] = value;queue->rear = (queue->rear+1)%N; //取余可以是值满后回到0return 1;
}
>4、顺序队列的出队
/*** @description:出队列 * @param {squeue} queue-队列指针* @return {0-函数失败,value-出队列单元储存的值}*/
int squeue_out(squeue queue)
{ data_t value;if(queue == NULL){#if DEBUGprintf("squeue create error!\n");#endifreturn 0;}if(queue->front == queue->rear){#if DEBUGprintf("squeue is empty!\n");#endifreturn 0;}value = queue->data[queue->front];queue->data[queue->front] = 0;queue->front = (queue->front+1)%N;return value;
}
>5、顺序队列的释放
/*** @description: 队列释放* @param {squeue} queue-队列指针* @return {0-函数失败,1-函数成功}*/
int squeue_free(squeue queue)
{if(queue == NULL){#if DEBUGprintf("squeue create error!\n");#endifreturn 0;}free(queue);return 1;
}
>6、顺序队列的清空
/*** @description: 队列清空* @param {squeue} queue-队列指针* @return {0-函数失败,1-函数成功}*/
int squeue_clear(squeue queue)
{if(queue == NULL){#if DEBUGprintf("squeue create error!\n");#endifreturn 0;}memset(queue->data,0,sizeof(queue->data));queue->front = queue->rear = 0;return 1;
}
>7、队列是否为空的判断
/*** @description: 判断队列是否为空* @param {squeue} queue-队列指针* @return {-1-函数失败,1-队列为空,0-队列不为空}*/
int squeue_empty(squeue queue)
{if(queue == NULL){#if DEBUGprintf("squeue create error!\n");#endifreturn -1;}return queue->front == queue->rear? 1:0;
}
>8、队列是否为满的判断
/*** @description: 判断队列是否满* @param {squeue} queue* @return {-1-函数失败,1-队列满,0-队列不满}*/
int squeue_full(squeue queue)
{if(queue == NULL){#if DEBUGprintf("squeue create error!\n");#endifreturn -1;}if((queue->rear+1)%N == queue->front)return 1;elsereturn 0;
}
三、链表队列
>1、链表队列的原理
插入操作
在队尾
进行,删除操作
在队头
进行,由队头指针和队尾指针控制队列的操作。
因此链表队列
的结构体
定义为:
#define DEBUG 1typedef int data_t;
typedef struct node
{data_t data;struct node *next;
}linklist_t,*linklist;
typedef struct
{linklist front,rear;
}listqueue,*linkqueue;
>2、链表队列的操作演示
>3、链表队列的创建
/*** @description: 链表队列创建* @param {*}* @return {lq-链表队列地址}*/
linkqueue linkqueue_create()
{linkqueue lq = (linkqueue)malloc(sizeof(listqueue)); if(lq == NULL){#if DEBUGprintf("linkqueue create error!\n");#endifreturn 0;}lq->front = lq->rear = (linklist)malloc(sizeof(linklist_t));if(lq->front == NULL || lq->rear == NULL){ #if DEBUGprintf("linkqueue create error!\n");#endifreturn 0;}lq->front->data = 0;lq->front->next = NULL;return lq;
}
>4、链表队列的入队
/*** @description: 链表队列入队* @param {linkqueue} lq-链表队列指针* @param {data_t} value-入队列的值* @return {0-函数失败,1-函数成功}*/
int linkqueue_enter(linkqueue lq, data_t value)
{linklist node = (linklist)malloc(sizeof(linklist_t));if(lq == NULL){#if DEBUGprintf("lq is NULL!\n");#endifreturn 0;}if(node == NULL){ #if DEBUGprintf("node create error!\n");#endifreturn 0;}lq->rear->next = node;lq->rear = node;node->data = value;node->next = NULL;return 1;
}
>5、链表队列的出队
/*** @description:链表队列出队 * @param {linkqueue} lq-链表队列指针* @return {0-函数失败,lq->front->data-出队列的值}*/
data_t linkqueue_out(linkqueue lq)
{linklist node;if(lq == NULL){#if DEBUGprintf("lq is NULL!\n");#endifreturn 0;}if(lq->front == lq->rear){#if DEBUGprintf("lq is empty!\n");#endifreturn 0;}node = lq->front;lq->front = node->next;free(node);return lq->front->data;
}
>6、链表队列的释放
/*** @description: 链表队列释放* @param {linkqueue} lq-链表队列指针* @return {0-函数失败,1-函数成功}*/
int linkqueue_free(linkqueue lq)
{linklist node;if(lq == NULL){#if DEBUGprintf("lq is NULL!\n");#endifreturn 0;}while(lq->front){node = lq->front;lq->front = node->next;free(node);}free(lq);return 1;
}
>7、链表队列的清空
/*** @description: 链表队列清空* @param {linkqueue} lq-链表队列指针* @return {0-函数失败,1-函数成功}}*/
int linkqueue_clear(linkqueue lq)
{linklist node;if(lq == NULL){#if DEBUGprintf("lq is NULL!\n");#endifreturn 0;}while(lq->front != lq->rear){node = lq->front;lq->front = node->next;free(node);}return 1;
}
>8、判断链表队列是否为空
/*** @description:判断链表队列是否为空 * @param {linkqueue} lq-链表队列指针* @return {-1-函数失败,1-队列为空,0-队列不为空}*/
int linkqueue_empty(linkqueue lq)
{if(lq == NULL){#if DEBUGprintf("lq is NULL!\n");#endifreturn -1;}return lq->front == lq->rear? 1:0;
}
四、链表的应用–球钟问题
1、球钟简介
球
钟是一个利用球的移动
来记录时间
的简单装置
它有
三个
可以容纳若干个球的指示器:分钟指示器
,五分钟指示器
,小时指示器
若分钟指示器中有2个球,五分钟指示器中有6个球,小时指示器中有5个球,则时间为5:32
2、球钟工作原理
- 每过
一分钟
,球钟就会从球队列
的队首
取出一个球
放入分钟指示器
,分钟指示器最多可容纳4个球
。 - 当放入
第五个球
时,在分钟指示器的4个球
就会按照他们被放入时
的相反顺序
加入球队列的队尾
。而第五个球
就会进入五分钟指示器
。 - 按此类推,
五分钟指示器
最多可放11个球
,小时指示器
最多可放11个球
。
3、问题阐述
- 当
小时指示器
放入第12个球
时,原来的11个球
按照他们被放入时
的相反顺序
加入球队列的队尾
,然后第12个球
也回到队尾
。 - 这时,
三个指示器
均为空,回到初始状态,从而形成一个循环
。因此,该球钟表示时间的范围是从0:00到11:59
。
问题:
现设初始时球队列的球数为27
,球钟的三个指示器初态均为空。要经过多久,球队列才能恢复
到原来的顺序
?
4、程序实现
这个问题我们选择顺序栈
来作为指示器
,链表队列
作为球队列
。实现代码如下:
/** @Author: your name* @Date: 2022-03-11 16:23:40* @LastEditTime: 2022-03-11 18:37:53* @LastEditors: your name* @Description: 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE* @FilePath: \ballclock\test.c*/
#include "linkqueue.h"
#include "sqstack.h"int queue_check(linkqueue lq); //检查是否队列为有序队列int main(int argc, const char *argv[])
{linkqueue lq;int i, min = 0;data_t value;sqstack *s_hour,*s_five,*s_min;lq = linkqueue_create();if(lq == NULL)return 0;s_hour = stack_create(11); //创建储存小时球的栈if(s_hour == NULL)return 0;s_five = stack_create(11); //创建储存5分钟球的栈if(s_five == NULL)return 0;s_min = stack_create(4); //创建储存分钟球的栈if(s_min == NULL)return 0;for(i = 1; i < 28; i++) //将27颗数字球放入队列内{linkqueue_enter(lq, i); }while(1){min++;value = linkqueue_out(lq); //一分钟后取出一颗球if(!stack_full(s_min)) //若分钟栈没满stack_push(s_min, value); //存入分钟栈内else {while(!stack_empty(s_min)) //分钟栈满了,取出栈内所有球linkqueue_enter(lq, stack_pop(s_min));if(!stack_full(s_five)) //若5分钟栈没满,下面步骤与上面类似stack_push(s_five, value);else{while(!stack_empty(s_five))linkqueue_enter(lq, stack_pop(s_five));if(!stack_full(s_hour))stack_push(s_hour, value);else{while(!stack_empty(s_hour))linkqueue_enter(lq, stack_pop(s_hour));linkqueue_enter(lq, value);if(queue_check(lq)) //检查是否队列为有序队列break;}}}}printf("min=%d\n",min); //得到回归初始状态需要多少分钟while(!linkqueue_empty(lq)) //打印出队列值{printf("%d ",linkqueue_out(lq));}puts("");linkqueue_free(lq);stack_free(s_min);stack_free(s_five);stack_free(s_hour);return 0;
}int queue_check(linkqueue lq)
{linklist p;if(lq == NULL){printf("lq is NULL\n");return 0;}p = lq->front->next;if(p == NULL || p->next == NULL) //若队列没有值或者只有一个值return 0;while(p->next){if(p->data > p->next->data)return 0;p = p->next;}return 1;
}
到这里就结束啦!
这里给出免费完整代码的下载链接:
队列C程序实现
【数据结构与算法】程序内功篇五--队列相关推荐
- 【数据结构与算法】程序内功篇四--栈
程序内功篇四--栈 一.栈的原理 二.顺序栈的实现 1.顺序栈原理 2.栈的创建 3.顺序栈进栈 4.顺序栈出栈 5.顺序栈删除 6.清空栈与是否清空栈 三.链表栈的实现 1.栈的单链表实现 2.创建 ...
- 【数据结构与算法】起始篇
持续学习&持续更新中- 守破离 [数据结构与算法]起始篇 什么是数据结构和算法 什么是数据结构 什么是算法 为什么要学习数据结构和算法1 为什么要学习数据结构和算法2 为什么要学习数据结构和算 ...
- C++数据结构和算法2 栈 双端/队列 冒泡选择插入归并快排 二三分查找 二叉树 二叉搜索树 贪婪 分治 动态规划
C++数据结构和算法2 栈 双端/队列 冒泡选择插入归并快排 二三分查找 二叉树 二叉搜索树 贪婪 分治 动态规划 博文末尾支持二维码赞赏哦 _ github 章3 Stack栈 和 队列Queue= ...
- 新星计划Day4【数据结构与算法】 稀疏数组与队列
新星计划Day4[数据结构与算法] 稀疏数组与队列
- 《代码随想录(Carl)》 数据结构与算法 程序的性能分析知识点总结
<代码随想录(Carl)> 数据结构与算法 程序的性能分析 2.1时间复杂度分析 2.1.1时间复杂度 时间复杂度是一个函数,它定性描述该算法的运行时间. 假设算法的数据规模为n,操作单元 ...
- 【数据结构与算法】第一篇:数据结构
系列文章目录 提示:这里可以添加系列文章的所有文章的目录,目录需要自己手动添加 TODO:写完再整理 文章目录 系列文章目录 前言 STL库的介绍 容器(containers) 算法(algorith ...
- 假设有搅乱顺序的一群儿童成一个队列_数据结构与算法系列之栈amp;队列(GO)...
以下完整代码均可从这里获取 栈 栈的基本概念 「后进先出.先进后出就是典型的栈结构」.栈可以理解成一种受了限制的线性表,插入和删除都只能从一端进行 当某个数据集合只涉及在一端插入和删除数据,并且满足后 ...
- java数据结构与算法之(Queue)队列设计与实现
[版权申明]转载请注明出处(请尊重原创,博主保留追究权) http://blog.csdn.net/javazejian/article/details/53375004 出自[zejian的博客] ...
- Python__数据结构与算法——表、栈、队列
目录 一.表 二.栈(后进先出) 三.队列(先进先出) 数据结构使用来描述一种或多种数据元素之间的特定关系,算法是程序设计中对数据操作的描述,数据结构和算法组成了程序.对于简单的任务,只要使用编程语言 ...
最新文章
- spring定时器突然不执行了_编程中常常遇到了定时器不工作的问题分析
- 剑指Offer_12_数值的整数次方
- C# 在自定义的控制台输出重定向类中整合调用方信息
- Leetcode之打印链接的倒数第K个节点
- android studio -genymotion神奇错误
- 如何固定最小宽度_如何使用更新的HTML和CSS函数创建响应式设计
- HLSL内置函数一览
- UMD格式与解析详解
- Could not found global transaction xid
- Kubernetes crictl管理命令详解
- 计算机辅助设计师考试报考网址,计算机辅助设计师证如何报考?报名入口
- sync.Pool 使用
- 金融类APP上架经验分享
- Java筑基18-布置作业啦(考查抽象类、内部类、工厂模式等)
- 喜茶多肉瓜瓜 | 埃德珈奶茶饮品培训,饮品配方做法制作教程
- Euler diagram
- 《可解释机器学习公开课》来了!
- 【基于stm32c8t6的智能加湿系统】
- ubuntu更新软件包
- 第一次用示波器怎么使用(基础经验)