程序内功篇五--队列

  • 一、队列
    • 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. 【数据结构与算法】程序内功篇四--栈

    程序内功篇四--栈 一.栈的原理 二.顺序栈的实现 1.顺序栈原理 2.栈的创建 3.顺序栈进栈 4.顺序栈出栈 5.顺序栈删除 6.清空栈与是否清空栈 三.链表栈的实现 1.栈的单链表实现 2.创建 ...

  2. 【数据结构与算法】起始篇

    持续学习&持续更新中- 守破离 [数据结构与算法]起始篇 什么是数据结构和算法 什么是数据结构 什么是算法 为什么要学习数据结构和算法1 为什么要学习数据结构和算法2 为什么要学习数据结构和算 ...

  3. C++数据结构和算法2 栈 双端/队列 冒泡选择插入归并快排 二三分查找 二叉树 二叉搜索树 贪婪 分治 动态规划

    C++数据结构和算法2 栈 双端/队列 冒泡选择插入归并快排 二三分查找 二叉树 二叉搜索树 贪婪 分治 动态规划 博文末尾支持二维码赞赏哦 _ github 章3 Stack栈 和 队列Queue= ...

  4. 新星计划Day4【数据结构与算法】 稀疏数组与队列

    新星计划Day4[数据结构与算法] 稀疏数组与队列

  5. 《代码随想录(Carl)》 数据结构与算法 程序的性能分析知识点总结

    <代码随想录(Carl)> 数据结构与算法 程序的性能分析 2.1时间复杂度分析 2.1.1时间复杂度 时间复杂度是一个函数,它定性描述该算法的运行时间. 假设算法的数据规模为n,操作单元 ...

  6. 【数据结构与算法】第一篇:数据结构

    系列文章目录 提示:这里可以添加系列文章的所有文章的目录,目录需要自己手动添加 TODO:写完再整理 文章目录 系列文章目录 前言 STL库的介绍 容器(containers) 算法(algorith ...

  7. 假设有搅乱顺序的一群儿童成一个队列_数据结构与算法系列之栈amp;队列(GO)...

    以下完整代码均可从这里获取 栈 栈的基本概念 「后进先出.先进后出就是典型的栈结构」.栈可以理解成一种受了限制的线性表,插入和删除都只能从一端进行 当某个数据集合只涉及在一端插入和删除数据,并且满足后 ...

  8. java数据结构与算法之(Queue)队列设计与实现

    [版权申明]转载请注明出处(请尊重原创,博主保留追究权) http://blog.csdn.net/javazejian/article/details/53375004 出自[zejian的博客] ...

  9. Python__数据结构与算法——表、栈、队列

    目录 一.表 二.栈(后进先出) 三.队列(先进先出) 数据结构使用来描述一种或多种数据元素之间的特定关系,算法是程序设计中对数据操作的描述,数据结构和算法组成了程序.对于简单的任务,只要使用编程语言 ...

最新文章

  1. spring定时器突然不执行了_编程中常常遇到了定时器不工作的问题分析
  2. 剑指Offer_12_数值的整数次方
  3. C# 在自定义的控制台输出重定向类中整合调用方信息
  4. Leetcode之打印链接的倒数第K个节点
  5. android studio -genymotion神奇错误
  6. 如何固定最小宽度_如何使用更新的HTML和CSS函数创建响应式设计
  7. HLSL内置函数一览
  8. UMD格式与解析详解
  9. Could not found global transaction xid
  10. Kubernetes crictl管理命令详解
  11. 计算机辅助设计师考试报考网址,计算机辅助设计师证如何报考?报名入口
  12. sync.Pool 使用
  13. 金融类APP上架经验分享
  14. Java筑基18-布置作业啦(考查抽象类、内部类、工厂模式等)
  15. 喜茶多肉瓜瓜 | 埃德珈奶茶饮品培训,饮品配方做法制作教程
  16. Euler diagram
  17. 《可解释机器学习公开课》来了!
  18. 【基于stm32c8t6的智能加湿系统】
  19. ubuntu更新软件包
  20. 第一次用示波器怎么使用(基础经验)

热门文章

  1. ubuntu20双系统+Mininet+Floodlight+eclipse luna
  2. 一款远控木马分析,仅供学习思路用途
  3. mac 下格式化U盘
  4. Guava(一)Lists与Maps
  5. oracle函数isnull,SQL中的ISNULL函数使用介绍
  6. 基于深度学习方法的头盔佩戴检测研究与系统实现
  7. 基础概念之均方根值RMS
  8. 【单元测试】NUnit框架了解及使用
  9. 互联网大爆炸:制造业迎来百年不遇的发展机会
  10. Android家庭财务管理系统计算机程序