环形(循环)队列在串口通信中的使用、原理、代码-C语言-篇1

1.什么是(顺序)队列

队列是一种特殊的线性表(物理空间地址连续存储,指针类型正相反),特殊之处在于它只允许在表的前端(front)进行删除操作,而在表的后端(rear)进行插入操作,和栈一样,队列是一种操作受限制的线性表。进行插入操作的端称为队尾,进行删除操作的端称为队头,是先进先出FIFO形式。

线性表中就包括数组,所以这里使用数组来完成队列的数据存取;这里先讲解顺序队列

例图:长度为8的数组

 

 上面是队列空时,头尾指向的位置是一样的head=tail;

当数据存储时,head保持不变,tail向后移动,则1是先存进去,然后是2,最后是3存进去;

数据读取时,head向后移动,tail保持不变,1先被读取,然后是2,最后是3;

这里只介绍这些用到的参数,关于存满或溢出等参数其它可以自行百度

2.什么是环形队列

原因:更好管理队列,更好的判断队列空或满

 循环队列也是用数组来构建,只不过经过特别算法,使得头尾内存上实现连接

存取数据仍是一样:

当数据存储时,head保持不变,tail向后移动,则1是先存进去,然后是2,最后是3存进去;

数据读取时,head向后移动,tail保持不变,1先被读取,然后是2,最后是3;

提示:无论是顺序队列还是循环队列,tail一直指向的是空位置

3.实际重要的是如何判断循环队列空满?:

        空判断:head=tail指向,队列无数据

        满判断:head=tail指向,队列有数据

由上可知,无论队列是空是满,都存在head=tail;那如何区分呢?

网上有说, 判断队列空用 head=tail

                    判断队列满用front=(rear+1)%MaxSize

我不大习惯用这个,这个还会有一个空间用不了,浪费;而是单独标志变量flag来标识数据进出:写入数据flag=1,读出数据flag=0;

空时:head=tail  && flag=0

满时:head=tail  && flag=1

4.环形队列存取数据原理步骤

(1)先判断循环队列是否满,如果满则输出提示信息,或者按照设计进行从头覆盖处理;

一般来说,实际串口通信时,不可能存满的,如果有存满标志说明是程序设计错误;

(2)如果不满则开始逐个字节存入数据,队列tail尾指向向下移动(数组下标加1),存入标志置flag=1

(3)读数据时,先判断数据是否为空,如果空则不读取了;如果不空,则head指向向下移动,开始从数组中读取数据,head对应的数组下标也加1,读取标志清flag=0

(4)判断head是否等于tail,同时判断falg标志,最后判断是否为空,为空时说明数据已经完全读取了

5.环形队列存取数据代码实验

#include "stdio.h"
/*-------------------------环形队列------------------------------------------*/
typedef unsigned char u8;
typedef unsigned short int u16;

#define size 8         //环形队列大小
u8 Table[size]={0};  //环形队列

typedef struct
{
    u8 head;//头
    u8 tail;//尾
    u8 flag;//满标志
}Queue_InitTypeDef;

int main(void)
{
    u8 a,b,i;
    char InOut=' ';
    Queue_InitTypeDef Queue_InitStre={0};//结构体元素全部清0
    Queue_InitTypeDef * Queue=NULL;
    Queue=&Queue_InitStre;

    Queue->flag=0;
    Queue->head=0;
    Queue->tail=0;
    while(1)
    {
        if(InOut==' ')
        {
            printf("请输入指令 i是入数据  o是出数据:");//提示选择功能
            scanf("%c",&InOut);//
            printf("InOut=%c\r\n",InOut);//
        }
        else if(InOut=='i')//写入
        {
            if((Queue->head==Queue->tail)&&(Queue->flag==1))//满判断
            {
                printf("队列存满\r\n");
                for(i=0;i<size;i++)
                {
                    printf("val=%d",Table[i]);//打印数据
                }
                InOut='o';//自动转为输出
                printf("自动转为输出\r\n");
            }
            else//非满
            {
                printf("请输入数据:");//提示
                scanf("%d",&a);//入数据
                printf("a=%d\r\n",a);//入数据

                Table[Queue->tail]=a;//数据处理    
                Queue->tail=(Queue->tail+1)%size;//tail指向向后移动
                Queue->flag=1;//写入时标志清0
                printf("head=%d tail=%d flag=%d\r\n",Queue->head,Queue->tail,Queue->flag);//输出head,tail,flag

                #if 1 //调试用-不存满实验只存5个字节
                if(Queue->tail==5)
                {
                    InOut='o';//自动转为输入
                    printf("自动转为输出\r\n");
                }
                #endif
            }
        }
        else if(InOut=='o')//读取
        {
           if((Queue->head==Queue->tail)&&(Queue->flag==0))//空判断
            {
                   printf("head=%d tail=%d flag=%d\r\n",Queue->head,Queue->tail,Queue->flag);//输出head,tail,flag
                printf("队列为空\r\n");
                Queue->head=0;//从头再来,有 没有存满时读取的情况
                Queue->tail=0;//从头再来,有 没有存满时读取的情况
                InOut='i';//自动转为输入
                printf("自动转为输入\r\n");
            }
           else//非空
           {
               b=Table[Queue->head];//出数据
               Queue->head=(Queue->head+1)%size;head指向向后移动
               Queue->flag=0;//读取时标志清0

               printf("b=%d\r\n",b);//打印读取的数据
               printf("head=%d tail=%d flag=%d\r\n",Queue->head,Queue->tail,Queue->flag);//输出head,tail,flag
           }
        }
        else
        {
            InOut=' ';    
        }
    }
    return 0;
}

测试结果:队列长度是5

  • 3
    点赞
  • 44
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
环形指针队列是一种非常常见的数据结构,通常用于解决多任务并发处理、缓存数据等问题。它的核心思想是将队列的元素存储在一个环形的数组,通过两个指针front和rear分别指向队头和队尾,实现入队和出队操作。 具体实现原理如下: 1. 定义环形队列结构体,包含队列数组、队头指针front、队尾指针rear、队列长度等信息。 ``` #define MAXSIZE 100 typedef struct { int data[MAXSIZE]; int front; int rear; int size; } CircleQueue; ``` 2. 初始化队列,将队头和队尾指针都指向0。 ``` void InitQueue(CircleQueue *queue) { queue->front = 0; queue->rear = 0; queue->size = 0; } ``` 3. 判断队列是否为空,当队头指针等于队尾指针时,队列为空。 ``` int IsEmpty(CircleQueue *queue) { return queue->front == queue->rear; } ``` 4. 判断队列是否满,当队尾指针加1等于队头指针时,队列满。 ``` int IsFull(CircleQueue *queue) { return (queue->rear + 1) % MAXSIZE == queue->front; } ``` 5. 入队操作,将元素插入队尾,队尾指针加1,当队尾指针等于数组长度时,将其置为0。 ``` void EnQueue(CircleQueue *queue, int x) { if (IsFull(queue)) { printf("Queue is full.\n"); return; } queue->data[queue->rear] = x; queue->rear = (queue->rear + 1) % MAXSIZE; queue->size++; } ``` 6. 出队操作,将队头元素弹出,队头指针加1,当队头指针等于数组长度时,将其置为0。 ``` int DeQueue(CircleQueue *queue) { if (IsEmpty(queue)) { printf("Queue is empty.\n"); return -1; } int x = queue->data[queue->front]; queue->front = (queue->front + 1) % MAXSIZE; queue->size--; return x; } ``` 这样,就完成了环形指针队列的实现。需要注意的是,由于在环形队列,队尾指针可能会超过数组长度,因此需要使用取模运算将其限制在数组范围内。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值