C语言队列和应用详情

目录
  • 1.队列的原理
  • 2.队列的作用
  • 3.队列程序设计思路
  • 4.入列
  • 5.出列
  • 6.掌握队列程序编写
  • 7.队列的应用

1.队列的原理

队列原理其实就像一个管道,如果我们不断往管道里面塞乒乓球,每个乒乓球在管道里就会排列一条队形。先进去的乒乓球就会先出来,这个就是队列的先进先出的规则。

球从左边进去,进去的动作就是入列,然后进去的球在管道里排成一个队列,这个叫队列缓存,说白了就是数组,那么这里存了5个球就相当于是buff[5];这样的意思,最右边出来的1号球就是最早进去的球,出来的这个动作叫出列,所以遵循了先进先出的规则。

2.队列的作用

队列最主要的作用就是用来缓存数据,比方说串口接收数据,我们一般定义一个数组来存储数据,但是假如串口数据频率很快,可能这个数组里存储的数据还没处理完,下一组串口数据又过来了,那么这时候数组里的数据就会被新数据覆盖,导致老的数据丢失。像这种就可以通过队列的方式来处理,每收到一个字节数据都先入列,然后应用程序同步解析处理,根据队列先进先出的规则,那么老的数据就不会被新的数据“插队”了。

基于这种缓存数据的技术,可以灵活应用在各种场景,比如说:

  • 1、操作系统的消息传递
  • 2、大数据处理

3.队列程序设计思路

其实实现队列的方法有很多种,但是工作原理都是一样的,我们要编写代码,首先要很清楚队列的工作原理。

  • 1、队列缓存
  • 2、入列
  • 3、出列
  • 一个队列基本上要有上面这三个必要的操作,那么队列缓存就很好理解,说白了就是直接定义一个数组,数组大小就是队列缓存的大小。入列就是把1个或者若干个数据按顺序存到队列缓存数组里,同样出列把数据从队列缓存里取出来。

入列和出列的原理懂了,那么应该怎么样用程序来实现呢?

4.入列

根据上文的说法,入列就是把数据存进数组的操作,我们平时存数组一般都是buff[0]=1;这样操作。不过在队列中我们要考虑队列里当前存在多少个数据的情况,如果有数据,那么我们就不能从[0]这个下标开始入列,所以我们在入列时要考虑两个问题:

  • 1、队列缓存可以存储的数组下标位置,这个我们一般称为队尾。
  • 2、队列是否已满,如果队列缓存满了又有新的数据入列,该怎么处理?这里我们一般处理方式是按照时间顺序,把最早入列的数据

丢弃,以新的数据替换。
第二个问题先暂时不管,先看第一个问题。根据前面学过的数组与指针,通过指针的特性,我们在用1个指针来代表队尾,然后这个队尾指针指向队列缓存数组的首地址,当入列1个数据时,我们的队尾指针就+1,这样是不是就能够知道当前队列缓存的可以存储的地址了?

5.出列

数据入列以后自然要取出来,那么我们取的时候也是有原则的,不能乱取,而是从最早入列那个数据的地址开始取,所以这个出列的数组下标我们称为队头,同样我们可以使用指针变量来代表这个队头。
我们看看下面这个图是一个出列的流程,我们这个是满编队的队列,总共有1,2,3,4,5个数据,那么队头指针指向队列缓存首地址,接着第一个出列的就是数据1,出列后队头指针加1,就指向数据2的地址,那么数据2出列后,队头指针又加1,指向数据3的地址,以此类推,这样就可以实现先进先出的原则。

6.掌握队列程序编写

那么我们知道原理后就可以用程序来实现它了,因为一个产品中,会有很多队列代表不同的数据,比如说消息我有一个队列,底层串口接收我也有一个队列,所以我们吧队列的一些操作,比如说入列,出列的操作单独写成函数接口,方便程序不同区域的调用。

#include <stdio.h>
#include "Queue.h"
Queue4 KeyMsg;

int main(int argc, char *argv[])
{
    unsigned char a; 
    QueueEmpty(KeyMsg);/*初始化*/
    printf("site:%d\r\n",sizeof(KeyMsg.Buff)); 
    printf("&KeyMsg=0x%x, KeyMsg.Buff=0x%x, KeyMsg.Head=0x%x, KeyMsg.Tail=0x%x\r\n",&KeyMsg,KeyMsg.Buff,KeyMsg.Head,KeyMsg.Tail);
    printf("&buff[0]=0x%x, &buff[1]=0x%x, &buff[2]=0x%x, &buff[3]=0x%x \r\n",&KeyMsg.Buff[0],&KeyMsg.Buff[1],&KeyMsg.Buff[2],&KeyMsg.Buff[3]);
    printf("\r\n"); 
    
    a = 1;
    QueueDataIn(KeyMsg,&a,1);/*要用哪一个队列,要存那个数据,要存多少个数据*/
    printf("&KeyMsg=0x%x, KeyMsg.Buff=0x%x, KeyMsg.Head=0x%x, KeyMsg.Tail=0x%x\r\n",&KeyMsg,KeyMsg.Buff,KeyMsg.Head,KeyMsg.Tail);
    printf("buff[0]=0x%x, buff[1]=0x%x, buff[2]=0x%x, buff[3]=0x%x \r\n",KeyMsg.Buff[0],KeyMsg.Buff[1],KeyMsg.Buff[2],KeyMsg.Buff[3]);
    printf("\r\n"); 
    
    a = 2;
    QueueDataIn(KeyMsg,&a,1);
    printf("&KeyMsg=0x%x, KeyMsg.Buff=0x%x, KeyMsg.Head=0x%x, KeyMsg.Tail=0x%x\r\n",&KeyMsg,KeyMsg.Buff,KeyMsg.Head,KeyMsg.Tail);
    printf("buff[0]=0x%x, buff[1]=0x%x, buff[2]=0x%x, buff[3]=0x%x \r\n",KeyMsg.Buff[0],KeyMsg.Buff[1],KeyMsg.Buff[2],KeyMsg.Buff[3]);
    printf("\r\n"); 
    
    a = 3;
    QueueDataIn(KeyMsg,&a,1);
    printf("&KeyMsg=0x%x, KeyMsg.Buff=0x%x, KeyMsg.Head=0x%x, KeyMsg.Tail=0x%x\r\n",&KeyMsg,KeyMsg.Buff,KeyMsg.Head,KeyMsg.Tail);
    printf("buff[0]=0x%x, buff[1]=0x%x, buff[2]=0x%x, buff[3]=0x%x \r\n",KeyMsg.Buff[0],KeyMsg.Buff[1],KeyMsg.Buff[2],KeyMsg.Buff[3]);
    printf("\r\n"); 
    
    a = 4;
    QueueDataIn(KeyMsg,&a,1);
    printf("&KeyMsg=0x%x, KeyMsg.Buff=0x%x, KeyMsg.Head=0x%x, KeyMsg.Tail=0x%x\r\n",&KeyMsg,KeyMsg.Buff,KeyMsg.Head,KeyMsg.Tail);
    printf("buff[0]=0x%x, buff[1]=0x%x, buff[2]=0x%x, buff[3]=0x%x \r\n",KeyMsg.Buff[0],KeyMsg.Buff[1],KeyMsg.Buff[2],KeyMsg.Buff[3]);
    printf("\r\n"); 
    
    a = 5;
    QueueDataIn(KeyMsg,&a,1);
    printf("&KeyMsg=0x%x, KeyMsg.Buff=0x%x, KeyMsg.Head=0x%x, KeyMsg.Tail=0x%x\r\n",&KeyMsg,KeyMsg.Buff,KeyMsg.Head,KeyMsg.Tail);
    printf("buff[0]=0x%x, buff[1]=0x%x, buff[2]=0x%x, buff[3]=0x%x \r\n",KeyMsg.Buff[0],KeyMsg.Buff[1],KeyMsg.Buff[2],KeyMsg.Buff[3]);
    printf("\r\n"); 
    
    printf("&KeyMsg=0x%x, KeyMsg.Buff=0x%x, KeyMsg.Head=0x%x, KeyMsg.Tail=0x%x\r\n",&KeyMsg,KeyMsg.Buff,KeyMsg.Head,KeyMsg.Tail);
    QueueDataOut(KeyMsg,&a);/*要用哪一个队列,要取那个数据*/
    printf("a=%d\r\n",a); 
    printf("&KeyMsg=0x%x, KeyMsg.Buff=0x%x, KeyMsg.Head=0x%x, KeyMsg.Tail=0x%x\r\n",&KeyMsg,KeyMsg.Buff,KeyMsg.Head,KeyMsg.Tail);
    printf("buff[0]=0x%x, buff[1]=0x%x, buff[2]=0x%x, buff[3]=0x%x \r\n",KeyMsg.Buff[0],KeyMsg.Buff[1],KeyMsg.Buff[2],KeyMsg.Buff[3]);
    printf("\r\n"); 
    
    return 0;
}

queue.c代码

void S_QueueEmpty(unsigned char **Head,unsigned char **Tail,unsigned char *pBuff)
{
    *Head = pBuff;
    *Tail = pBuff; 
}

void S_QueueDataIn(unsigned char **Head,unsigned char **Tail,unsigned char *pBuff,unsigned char Len,unsigned char *pData,unsigned char DataLen)
{
    unsigned char num;
    //关闭中断 
    for(num=0; num < DataLen; num++,pData++)
    {    
        **Tail = *pData;        //这里把数据入列 
        (*Tail)++;                //队尾指针加1
         if(*Tail == pBuff+Len)
         {
             *Tail = pBuff; 
         }
        if(*Tail == *Head)
        {
            
            if(++(*Head) == pBuff+Len)
            {
                *Head = pBuff;    
            }
        }
    }
    //打开中断 
}

unsigned char S_QueueDataOut(unsigned char **Head,unsigned char **Tail,unsigned char *pBuff,unsigned char Len,unsigned char *pData)
{
    unsigned char status;
    //关闭中断 
    status = 0;
    if(*Head != *Tail)
    {
        *pData = **Head;
        status = 1;
        if(++(*Head) == pBuff+Len)
        {
            *Head = pBuff;
        }
    }
    //恢复中断 
    return status;
}

unsigned short S_QueueDataLen(unsigned char **Head,unsigned char **Tail,unsigned char *pBuff,unsigned char Len)
{
    if(*Tail > *Head)
    {
        return *Tail-*Head;
    }
    if(*Tail < *Head)
    {
        return *Tail+Len-*Head;    
    }
}

queue.h代码

#ifndef _QUEUE_H_
#define _QUEUE_H_

extern void S_QueueEmpty(unsigned char **Head,unsigned char **Tail,unsigned char *pBuff);
extern void S_QueueDataIn(unsigned char **Head,unsigned char **Tail,unsigned char *pBuff,unsigned char Len,unsigned char *pData,unsigned char DataLen);
extern unsigned char S_QueueDataOut(unsigned char **Head,unsigned char **Tail,unsigned char *pBuff,unsigned char Len,unsigned char *pData); 
extern unsigned short S_QueueDataLen(unsigned char **Head,unsigned char **Tail,unsigned char *pBuff,unsigned char Len); 

#define QueueEmpty(x)  S_QueueEmpty((unsigned char **)&(x).Head,(unsigned char **)&(x).Tail,(unsigned char *)(x).Buff)

#define QueueDataIn(x,y,z) S_QueueDataIn((unsigned char **)&(x).Head,(unsigned char **)&(x).Tail,(unsigned char *)&(x).Buff,sizeof((x).Buff),y,z)
#define QueueDataOut(x,y)  S_QueueDataOut((unsigned char **)&(x).Head,(unsigned char **)&(x).Tail,(unsigned char *)&(x).Buff,sizeof((x).Buff),y)
#define QueueDataLen(x)     S_QueueDataLen((unsigned char **)&(x).Head,(unsigned char **)&(x).Tail,(unsigned char *)&(x).Buff,sizeof((x).Buff))
 
typedef struct
{
    unsigned char *Head;     //队头指针,用来出列用的 
    unsigned char *Tail;     //队尾指针,用来入列用的 
    unsigned char Buff[4];    //队列缓存 
}Queue4;

typedef struct
{
    unsigned char *Head;     //队头指针,用来出列用的 
    unsigned char *Tail;     //队尾指针,用来入列用的 
    unsigned char Buff[128];    //队列缓存 
}Queue128;

typedef struct
{
    unsigned char *Head;     //队头指针,用来出列用的 
    unsigned char *Tail;     //队尾指针,用来入列用的 
    unsigned char Buff[512];    //队列缓存 
}Queue512;
#endif

7.队列的应用

串口的应用:

如果产品有两个功能,一个功能需要灯一秒闪1次,另一个功能需要灯1秒闪2次,在功能切换很快的情况下,需要功能正常并且灯的闪烁正常,那么就需要队列了。

到此这篇关于C语言队列和应用详情的文章就介绍到这了,更多相关C语言队列和应用内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • C语言数组实现三子棋应用实例

    本文实例为大家分享了C语言数组实现三子棋应用的具体代码,供大家参考,具体内容如下 三子棋:(拆分部分如下) test.c 测试游戏逻辑 game.h关于游戏相关的函数声明,符号声明 头文件的包含 game.c游戏相关函数的实现 游戏进行的过程:(4种) 1.玩家获胜--*(游戏结束) 2.电脑获胜--#(游戏结束) 3.平局--Q(游戏结束) 4.游戏继续--C IsWin函数 用来判断游戏的状态 game.c #include"game.h" #include<stdio.h&

  • C语言基础应用处理学生打分 计算时间 最少硬币问题详细过程

    第一题: 最少硬币问题(简单版) 假设有三种面值的硬币,分别为10.5.1.接收一个整数作为金额数,计算要达到该金额数,每个面值的硬币最少需要多少枚. 输出结果演示: 参考答案: #include <stdio.h> typedef struct StructrueMoneyBox { int n10; int n5; int n1; } MoneyBox; int main(void) { MoneyBox change = {0, 0, 0}; int face_value[4] = {1

  • 深入浅出理解C语言指针的综合应用

    目录 指针是什么? 指针变量 使用指针变量的例子 通过指针引用数组 &数组名vs数组名 野指针 野指针成因 1.指针未初始化 2.指针越界访问 如何避免野指针 指针运算 指针是什么? 指针是c语言中的一个重要概念,也是C语言的一个重要的特色,正确而灵活地运用它,可以使程序简洁,紧凑,高效,每一个学习和使用c语言的人,都应当深入了解地学习和掌握指针,可以说,不掌握指针就是没有掌握C的精华也可以说 指针是C语言的灵魂(doge) 由于通过地址能找到所需的变量单元,可以说,地址指向变量单元,打个比方,

  • C语言中用栈+队列实现队列中的元素逆置

    下面举例代码: 提到的Q是一个队列,S是一个空栈,实现将队列中的元素逆置的算法 #include<stdio.h> #define MaxSize 10 typedef int ElemType; typedef struct{     ElemType data[MaxSize];     int front,rear; }Queue; typedef struct{     ElemType data[MaxSize];     int top; }SqStack;   void Init

  • C语言数据结构之链队列的基本操作

    目录 1.队列的定义 2.队列的表示和实现 (1) 初始化操作 (2)销毁队列 (3) 入队操作 (4) 出队操作 附录完整代码: 总结 1.队列的定义 队列 (Queue)是另一种限定性的线性表,它只允许在表的一端插入元素,而在另一端删除元素,所以队列具有先进先出(Fist In Fist Out,缩写为FIFO)的特性.在队列中,允许插入的一端叫做队尾(rear),允许删除的一端则称为队头(front). 假设队列为q=(a1,a2,-,an),那么a1就是队头元素,an则是队尾元素.队列中

  • C语言实现顺序循环队列实例

    目录 一.队列和循环队列基本概念 二.代码实操 总结 一.队列和循环队列基本概念 队列: 和栈相反,队列是一种先进先出(FIFO)的线性表.只允许在一端插入,在另一端删除. 允许插入的叫"队尾"(rear),允许删除的叫"队头"(front). 入队操作:L->rear++;   L->data[L->rear]=x;(需要入队的元素) 出队操作:L->front++;  x=L->data[L->front]; 求队长:队长=(

  • C语言数据结构系列队列篇

    目录 一.队列(Queue) 0x00队列的概念 0x01队列的结构 二.队列的定义 0x00链式队列 0x02 接口函数 三.队列的实现 0x00队列初始化(QueueInit) 0x01销毁队列(QueueDestroy) 0x02判断队列是否为空(HeapIsEmpty) 0x03入队(QueuePush) 0x04出队(QueuePop) 0x05 返回队头数据(QueueFront) 0x06 返回队尾数据(QueueBack) 0x07 求队列大小(QueueSize) 0x08完整

  • C语言队列和应用详情

    目录 1.队列的原理 2.队列的作用 3.队列程序设计思路 4.入列 5.出列 6.掌握队列程序编写 7.队列的应用 1.队列的原理 队列原理其实就像一个管道,如果我们不断往管道里面塞乒乓球,每个乒乓球在管道里就会排列一条队形.先进去的乒乓球就会先出来,这个就是队列的先进先出的规则. 球从左边进去,进去的动作就是入列,然后进去的球在管道里排成一个队列,这个叫队列缓存,说白了就是数组,那么这里存了5个球就相当于是buff[5];这样的意思,最右边出来的1号球就是最早进去的球,出来的这个动作叫出列,

  • Go语言的变量定义详情

    目录 一.变量 声明变量 二.短声明 指针 三.new函数 四.变量的生命期 五.变量的作用域 一.变量 声明变量 go定义变量的方式和c,c++,java语法不一样,如下: var 变量名 类型, 比如 : var a int var在前,变量名在中间,类型在后面 我们以代码举例,如下: var i int = 0 var i = 0 var i int 以上三个表达式均是合法的,第三个表达式会将i初始化为int类型的零值,0:如果i是bool类型,则为false:i是float64类型,则为

  • C语言 队列的实现全解析

    目录 队列的实现 基本概念 创建结构体 初始化结构体 销毁队列结构体 入队 出队 判断队列是否为空 访问对头的值 访问队尾的值 返回队列的长度 Queue.h Queue.c Test.c “ 江天一色无纤尘,皎皎空中孤月轮. ” 队列的实现 基本概念 队列:只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表,队列具有先进先出 FIFO(First In First Out) 入队列:进行插入操作的一端称为队尾 出队列:进行删除操作的一端称为队头 队列也可以数组和链表的结构实现,

  • C语言 队列的实现全解析

    目录 队列的实现 基本概念 创建结构体 初始化结构体 销毁队列结构体 入队 出队 判断队列是否为空 访问对头的值 访问队尾的值 返回队列的长度 Queue.h Queue.c Test.c 队列的实现 基本概念 队列:只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表,队列具有先进先出 FIFO(First In First Out) 入队列:进行插入操作的一端称为队尾 出队列:进行删除操作的一端称为队头 队列也可以数组和链表的结构实现,使用链表的结构实现更优一些,因为如果使用数

  • Python通过队列实现进程间通信详情

    目录 一.前言 二.队列简介 三.多进程队列的使用 四.使用队列在进程间通信 一.前言 在多进程中,每个进程之间是什么关系呢?其实每个进程都有自己的地址空间.内存.数据栈以及其他记录其运行状态的辅助数据.下面通过一个例子,验证一下进程之间能否直接共享信息. 定义一个全局变量g_num,分别创建2个子进程对g_num执行不同的操作,并输出操作后的结果. 代码如下: # _*_ coding:utf-8 _*_ from multiprocessing import Process def plus

  • C语言超详细讲解队列的实现及代码

    目录 前言 队列的概念 队列的结构 队列的应用场景 队列的实现 创建队列结构 队列初始化 队列销毁 入队列 出队列 队列判空 获取队列元素个数 获取队列头部元素 获取队列尾部元素 总代码 Queue.h 文件 Queue.c 文件 Test.c 文件 前言 队列的概念 队列:只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表,队列具有先进先出FIFO(First In First Out) 入队列:进行插入操作的一端称为队尾 出队列:进行删除操作的一端称为队头 队列和前文所学的栈

  • C语言简明讲解队列的实现方法

    目录 前言 队列的表示和实现 队列的概念及结构 代码实现 束语 前言 大家好啊,我又双叒叕来水博客了,道路是曲折的,前途是光明的,事物是呈螺旋式上升的,事物最终的发展结果还是我们多多少少能够决定的,好啦,吹水结束,这与这篇博客的主题并没有太多联系.关于栈和队列这一板块本来是想不写(就是想偷懒),但是想了想,觉得这样不太好,关于数据结构这一块可能会有缺失,所以最终还是决定写,必须补齐这一块,恰好最近有时间写博客,所以还是写了,这篇博客将介绍队列的知识点,理解链表那一块的操作后,栈和队列的相关操作还

  • C语言详解链式队列与循环队列的实现

    目录 队列的实现 链式队列 链式队列的定义 链式队列的实现 循环队列 循环队列的定义 循环队列的实现 队列的实现 队列是一种先进先出(First in First Out)的线性表,简称FIFO.与栈不同,栈是一种后进先出(先进后出)的线性表.在队列中,允许插入的一端称为队尾,允许删除的一端称为队头.假设队列是q=(a1,a2,…,an),那么a1就是队头元素,而an是队尾元素.这样我们就可以删除时,总是从a1开始,而插入时,列在最后.这也比较符合我们通常生活中的习惯,排在第一个的优先出列,最后

  • C语言实现队列的示例详解

    目录 前言 一. 什么是队列 二. 使用什么来实现栈 三. 队列的实现 3.1头文件 3.2 函数的实现 四.完整代码 前言 前一段时间,我们试着用C语言实现了数据结构中的顺序表,单链表,双向循环链表,栈.今天我们再用C语言来实现另一种特殊的线性结构:队列 一. 什么是队列 队列是一种特殊的线性表,特殊之处在于它只允许在表的前端(head)进行删除操作,而在表的后端(tail)进行插入操作,和栈一样,队列是一种操作受限制的线性表.进行插入操作的端称为队尾,进行删除操作的端称为队头. 这个队列就可

随机推荐