如何编写队列-原理—应用

1 .概况......就不多说了 直接上手。

        1.1 :队列原理和作用

                 原理:队列可以理解为一个管道,然后呢你往里面塞入乒乓球(入列),先塞进来的乒乓球会先出来(出列),,这就是队列先进先出的原则。

                作用:(1)一般用来缓存数据,比如串口接收数据(一般使用数组) 如果数据传入过来的频率过快就会导致数组里存入的数据还没有处理完,下一组数据又过来了,那么这时候数组里的数据就会被新数据覆盖,导致老的数据丢失。        

                        (2)如果出现这种情况 就可以通过队列的方式来处理,,每接收到一个字节的数据都先入列。然后在应用层程序同步解析处理,根据队列先进先出的规则,那么老的数据就不会被新的数据插队了。

         1.2 :队列的写法

                        入列操作:原理上就是把数据存储在一个数组里例:buff[0] = 1;,但是队列传递要稍微复杂一点,因为要考虑当前存在多少个数据的情况,如果有数据,那么就不能从【0】这个下标开始入列,所以需要考虑2个问题

                         1. 队列缓存可以存储数据的下标位置,这个我们一般称为队尾。

                        2.如果队列满了该如何处理,这里一般按照时间的顺序把最早入列的数据丢掉,用新的数据替换。(替换后,还需要做其他的处理,具体看代码)   当由数据进来用一个数据指针指向这个数据每进来一个数据指针+1 ,就能一直确定当前队列的队尾

                        出列操作:是从最早的数据的地址开始取,这个我们称为队头,同样使用指针变量来代表对头。 

        1.3 :队列在产品中的应用

                1.入列函数 

/********************************************************************************************************
*  @函数名   S_QueueDataIn					                                                           
*  @描述     输入一个字节数据进队列								                                     
*  @参数     Head-队列头地址,  Tail-队列尾地址, pBuff-数组首地址 ,Len-数组大小,pData-数据地址,DataLen数据长度
*  @返回值   无   
*  @注意    无
********************************************************************************************************/
void S_QueueDataIn(unsigned char **Head ,unsigned char **Tail,unsigned char *pBuff,unsigned char Len,unsigned char *pData,unsigned char DataLen)
{
		**Tail = *pData; //数据入列
		(*Tail) ++;   //对应的队尾指针加一 ,指向下一个存储地址
		if(*Tail == pBuff+Len)  //判断数据是否存满
		{
			*Tail = pBuff;  //存满过后又把首地址赋值给队尾
		}
		/*会出现一个问题如果,队头指针与队尾指针指向同一个地址后会产生冲突
			什么冲突:
			把旧的数据覆盖,从而把最先入列的数据给取出来了,那就违背队列的原则。
			下面是处理方法。
		*/
		if(*Tail == *Head) //当队头与队尾同时指向同一地址时,队头指针加+
		{
			 // 这里加+过后又会产生问题。当对头指针指向数组末尾时,指针会溢出。
			if(++(*Head) == pBuff+Len) //判断队列头指针是否到达了队列的末尾
			{
				*Head = pBuff; //又把队头指针复位,这样就能实现队列先进先出原则。
			}
		}
		
}

        2 出列函数:

        需要考虑的问题: 1. 队列一直入列,而队列一直不出列,队尾指针就会和队头指向的地址相同 ,会出现旧的数据还没取,就被新的数据所覆盖。采取的步骤,是把队头指针加一。

/********************************************************************************************************
*  @函数名   S_QueueDataOut					                                                           
*  @描述     输出一个字节数据进队列								                                     
*  @参数     Head-队列头地址,  Tail-队列尾地址, pBuff-数组首地址 ,Len-数组大小,pData-数据地址,DataLen数据长度
*  @返回值   无   
*  @注意    无
********************************************************************************************************/
unsigned char S_QueueDataOut(unsigned char **Head ,unsigned char **Tail,unsigned char *pBuff,unsigned char Len,unsigned char *pData,unsigned char DataLen)
{
	unsigned char status; //返回值代表数据出列
	if(*Head != *Tail) //这里先判断队列是否又数据
	{
		 *pData = **Head; //把对头的数据给数组
		 status =1;      //用来判断是否又输出出列
		/*下面也需要进行处理,每次队头都需要加+来读取入列的数据,就会出现队头指向数组末尾,需要重新复位。*/
		if(++(*Head) ==pBuff+Len)
		{
			*Head = pBuff; //又把队头指针复位,这样就能实现队列先进先出原则。
		}
	}
	return status;
}

  队列数据长度

/********************************************************************************************************
*  @函数名   S_QueueDatalen					                                                           
*  @描述     队列数据长度								                                     
*  @参数     Head-队列头地址,  Tail-队列尾地址, pBuff-数组首地址 ,Len-数组大小,pData-数据地址,DataLen数据长度
*  @返回值   无   
*  @注意    无
********************************************************************************************************/
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; // 
	}
	
	else return 0;
}

队列初始化 

//队列初始化,需要把队列 队头,队尾指向数据缓存区的地址。
void S_QueueEmpty(unsigned char **Head,unsigned char **Tail,unsigned char *pBuff)
{
	*Head = pBuff;
	*Tail = pBuff;
}

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,unsigned char DataLen);
extern unsigned short S_QueueDataLen(unsigned char **Head ,unsigned char **Tail,unsigned char *pBuff,unsigned char Len);
//x.**Head,x.**Tail,x.*pBuff 需要强制类型转换,define 传入进来的数据类型是不清楚的。
#define  QueueEmpty(x) 	      S_QueueEmpty((unsigned char **)(x).**Head,(unsigned char **)(x).**Tail,(unsigned char *)(x).*pBuff)
#define  QueueDataIn(x,y,z)   S_QueueDataIn((unsigned char **)(x).**Head ,(unsigned char **)(x).**Tail,(unsigned char *)(x).*pBuff,sizeof(x.buff),(y),(z))  //y,z 不需要转换,这里传递的时数值。
#define  QueueDataOut(x,y,z)  S_QueueDataOut((unsigned char **)(x).**Head ,(unsigned char **)(x).**Tail,(unsigned char *)(x).*pBuff,sizeof(x.buff),(y),(z))
#define  QueueDataLen(x)      S_QueueDataLen((unsigned char **)(x).**Head,(unsigned char **)(x).**Tail,(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[8]; }Queue8;
typedef struct{unsigned char *Head; unsigned char *Tail; unsigned char Buff[16]; }Queue16;
typedef struct{unsigned char *Head; unsigned char *Tail; unsigned char Buff[32]; }Queue32;
typedef struct{unsigned char *Head; unsigned char *Tail; unsigned char Buff[64]; }Queue64;
typedef struct{unsigned char *Head; unsigned char *Tail; unsigned char Buff[128]; }Queue128;
typedef struct{unsigned char *Head; unsigned char *Tail; unsigned char Buff[256]; }Queue256;


#endif

 测试代码,使用软件C-Free.

  • 9
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值