实战日记:以数组方式实现静态队列操作

学习背景

工作两年,大多数时间都是用一些常用的代码实现一些功能,对数据结构并没有怎么使用,也没有怎么花时间去了解,只知道队列是先进先出这些基本的东西(-.-),并没有去细究其中的实现过程,直到最近在做一个项目,用到串口收发,为避免极端情况下发生发送碰撞(在极短时间内有两条发送指令一起执行,导致从机无法做到数据的有效识别,比如一些正常的指令固定每隔几分钟发一次,在这个指令准备发送的时候一个条件触发的指令也被触发了,就会一瞬间发送两条指令),受同事启发使用队列结构,其实现效果为:当有指令需要通过串口发送时,将指令标识放入队列中,主函数每隔一定时间(假定为10ms)判断队列是否为空,如果不为空则从队列中取出指令标识,判断该指令标识属于哪一个指令,然后执行该指令的发送函数。

注:下文讲解的源码来自于网络,非本人所写,如有侵权请联系作者删除,本文主要借助于源码和实验讲解队列的实现过程

写这篇博客一方面为了记录自己所学到东西,一方面为了加强理解,同时将这篇文章发布出来,希望可以得到相应的指正!

队列

队列操作

常用队列包含的操作有:创建队列、添加数据、取出数据、判断队列是否为空

本文主要介绍以数组为模型的静态方式创建一个队列的方法,既然以数组为模型,那它大致应该是这样的:创建一个指定大小的数组,该数组的长度即为队列的大小,每当向队列中存一个数,也就是给数组的指定下标赋值,然后将下标+1,该下标应该是从0开始的,所以需要一个变量记录这个操作,我们先暂时将这个变量定义为in,同时还需要一个计数器count,每存一个数,count加1,每取出一个数count减1,这个count可以用来判断队列是否为空和是否溢出,同时还需要一个变量用来记录取数据的数组下标,因为队列是先进先出,所以这个变量也是从0开始的,也就是从数组下标0开始取数据

根据以上的叙述,所以定义出一个队列的结构体变量类型,如下:

typedef struct
{
  uint8_t out;	//记录取数据的数组下标
  uint8_t in;		//记录存数据的数组下标
  uint8_t count;	//已存入队列中的元素个数
  uint8_t queueSize;//队列大小
  uint8_t elementType;//元素的大小,也就是数组元素的大小
  QElementType* array;//存放你所定义的数组的指针
}
QUEUE_T;

创建队列

所谓创建队列,也就是队列的初始化,也就是对队列中各个元素的赋值,如下

#define QUEUE_SIZE 5 //队列大小

QUEUE_T MyQueue;//定义一个队列结构体变量

u8 MyQueue_pBuffer[QUEUE_SIZE];//对应队列的数组模型

u8 tx;//模拟的用于存放发送标志的变量

//函数源码
void queue_Init(QUEUE_T * pQueue, void * pBuffer, BYTE sizeOfElements, BYTE numberOfElements)
{
  pQueue->out = 0;
  pQueue->in = 0;
  pQueue->queueSize = numberOfElements;
  pQueue->count = 0;
  pQueue->elementType = sizeOfElements;
  pQueue->array = (BYTE*)pBuffer;
}

//初始化队列
queue_Init(&MyQueue,MyQueue_pBuffer,sizeof(MyQueue_pBuffer[0]),QUEUE_SIZE);

向队列中添加一个元素

//源码
BOOL queue_Enqueue(QUEUE_T * pQueue, void * pElement)
{
  if (pQueue->count >= pQueue->queueSize)
  {
    return FALSE;
  }
  else
  {
    BYTE i;
    BYTE* pEl = pElement;

    for (i = 0; i < pQueue->elementType; i++)
    {
      pQueue->array[ (pQueue->in)*(pQueue->elementType) + i ] = *(pEl + i);
    }

    pQueue->in = (pQueue->in + 1) % pQueue->queueSize;
    pQueue->count = pQueue->count + 1;
  }
  return TRUE;
}

//添加一个元素的调用例程
tx='1';
queue_Enqueue(&MyQueue,&tx);

从队列中取出一个元素

//源码
BOOL queue_Dequeue(QUEUE_T * pQueue, void * pElement)
{
  if (pQueue->count <= 0)
  {
    return FALSE;
  }
  else
  {
    BYTE i;
    BYTE* pEl = pElement;

    for (i = 0; i < pQueue->elementType; i++)
    {
      *(pEl + i) = pQueue->array[(pQueue->out) * (pQueue->elementType) + i];
    }

    pQueue->out = (pQueue->out + 1) % pQueue->queueSize;
    pQueue->count = pQueue->count - 1;
  }
  return TRUE;
}
//调用例程
u8 rtn;
queue_Dequeue(&MyQueue,&rtn);

 我的测试实验

通过打印的内容观察分析队列原理,以下给出我的测试实验源码和实验结果,以助于理解队列,我的实验大致流程为:

创建队列(队列长度为5)

向队列中添加一个字符'1'

向队列中添加一个字符'2'

向队列中添加一个字符'3'

向队列中添加一个字符'4'

向队列中添加一个字符'5'

然后:取数据-取数据-存数据(字符‘4’)-取数据

实验源码

queue_Init(&MyQueue,MyQueue_pBuffer,sizeof(MyQueue_pBuffer[0]),QUEUE_SIZE);
	my_printf("out=%d ,in=%d ,count=%d ,queueSize=%d ,elementType=%d ,array=%s\r\n",MyQueue.out,MyQueue.in,MyQueue.count,MyQueue.queueSize,MyQueue.elementType,MyQueue.array);
	HAL_Delay(500);
	
	tx='1';
	my_printf("%d ",queue_Enqueue(&MyQueue,&tx));//存数据,同时打印返回值
	my_printf("out=%d ,in=%d ,count=%d ,queueSize=%d ,elementType=%d ,array=%s\r\n",MyQueue.out,MyQueue.in,MyQueue.count,MyQueue.queueSize,MyQueue.elementType,MyQueue.array);
	HAL_Delay(500);
	
	tx='2';
	my_printf("%d ",queue_Enqueue(&MyQueue,&tx));//存数据,同时打印返回值
	my_printf("out=%d ,in=%d ,count=%d ,queueSize=%d ,elementType=%d ,array=%s\r\n",MyQueue.out,MyQueue.in,MyQueue.count,MyQueue.queueSize,MyQueue.elementType,MyQueue.array);
	HAL_Delay(500);
	
	tx='3';
	my_printf("%d ",queue_Enqueue(&MyQueue,&tx));//存数据,同时打印返回值
	my_printf("out=%d ,in=%d ,count=%d ,queueSize=%d ,elementType=%d ,array=%s\r\n",MyQueue.out,MyQueue.in,MyQueue.count,MyQueue.queueSize,MyQueue.elementType,MyQueue.array);
	HAL_Delay(500);
	
	tx='4';
	my_printf("%d ",queue_Enqueue(&MyQueue,&tx));//存数据,同时打印返回值
	my_printf("out=%d ,in=%d ,count=%d ,queueSize=%d ,elementType=%d ,array=%s\r\n",MyQueue.out,MyQueue.in,MyQueue.count,MyQueue.queueSize,MyQueue.elementType,MyQueue.array);
	HAL_Delay(500);
	
	tx='5';
	my_printf("%d ",queue_Enqueue(&MyQueue,&tx));//存数据,同时打印返回值
	my_printf("out=%d ,in=%d ,count=%d ,queueSize=%d ,elementType=%d ,array=%s\r\n",MyQueue.out,MyQueue.in,MyQueue.count,MyQueue.queueSize,MyQueue.elementType,MyQueue.array);
	HAL_Delay(500);
	
	my_printf("%d ",queue_Dequeue(&MyQueue,&rtn));//取数据,同时打印返回值
	my_printf("rtn=%s ",&rtn);
	my_printf("out=%d ,in=%d ,count=%d ,queueSize=%d ,elementType=%d ,array=%s\r\n",MyQueue.out,MyQueue.in,MyQueue.count,MyQueue.queueSize,MyQueue.elementType,MyQueue.array);
	HAL_Delay(500);
	
	
	my_printf("%d ",queue_Dequeue(&MyQueue,&rtn));//取数据,同时打印返回值
	my_printf("rtn=%s ",&rtn);
	my_printf("out=%d ,in=%d ,count=%d ,queueSize=%d ,elementType=%d ,array=%s\r\n",MyQueue.out,MyQueue.in,MyQueue.count,MyQueue.queueSize,MyQueue.elementType,MyQueue.array);
	HAL_Delay(500);
	
	tx='4';
	my_printf("%d ",queue_Enqueue(&MyQueue,&tx));//存数据,同时打印返回值
	my_printf("out=%d ,in=%d ,count=%d ,queueSize=%d ,elementType=%d ,array=%s\r\n",MyQueue.out,MyQueue.in,MyQueue.count,MyQueue.queueSize,MyQueue.elementType,MyQueue.array);
	HAL_Delay(500);
	
	my_printf("%d ",queue_Dequeue(&MyQueue,&rtn));//取数据,同时打印返回值
	my_printf("rtn=%s ",&rtn);
	my_printf("out=%d ,in=%d ,count=%d ,queueSize=%d ,elementType=%d ,array=%s\r\n",MyQueue.out,MyQueue.in,MyQueue.count,MyQueue.queueSize,MyQueue.elementType,MyQueue.array);
	HAL_Delay(500);

实验结果

 

队列源码

最后贴出队列的源码,注:源码来自于网络,如有侵权,请联系作者删除

#include "myQueue.h"


void queue_Init(QUEUE_T * pQueue, void * pBuffer, BYTE sizeOfElements, BYTE numberOfElements)
{
  pQueue->out = 0;
  pQueue->in = 0;
  pQueue->queueSize = numberOfElements;
  pQueue->count = 0;
  pQueue->elementType = sizeOfElements;
  pQueue->array = (BYTE*)pBuffer;
}

BOOL queue_Enqueue(QUEUE_T * pQueue, void * pElement)
{
  if (pQueue->count >= pQueue->queueSize)
  {
    return FALSE;
  }
  else
  {
    BYTE i;
    BYTE* pEl = pElement;

    for (i = 0; i < pQueue->elementType; i++)
    {
      pQueue->array[ (pQueue->in)*(pQueue->elementType) + i ] = *(pEl + i);
    }

    pQueue->in = (pQueue->in + 1) % pQueue->queueSize;
    pQueue->count = pQueue->count + 1;
  }
  return TRUE;
}

BOOL queue_Dequeue(QUEUE_T * pQueue, void * pElement)
{
  if (pQueue->count <= 0)
  {
    return FALSE;
  }
  else
  {
    BYTE i;
    BYTE* pEl = pElement;

    for (i = 0; i < pQueue->elementType; i++)
    {
      *(pEl + i) = pQueue->array[(pQueue->out) * (pQueue->elementType) + i];
    }

    pQueue->out = (pQueue->out + 1) % pQueue->queueSize;
    pQueue->count = pQueue->count - 1;
  }
  return TRUE;
}

uint8_t queue_GetItemCount(QUEUE_T * pQueue)
{
  return pQueue->count;
}

#ifndef _MYQUEUE_H
#define _MYQUEUE_H


#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
#include "stdint.h"
#define BYTE uint8_t 
#define BOOL bool 
#define TRUE true 
#define FALSE false 
		
typedef uint8_t QElementType;

/**
 * In order to use the Queue module, a variable of this type must be declared before calling
 * \ref ZW_util_queue_Init.
 */
typedef struct
{
  uint8_t out;
  uint8_t in;
  uint8_t count;
  uint8_t queueSize;
  uint8_t elementType;
  QElementType* array;
}
QUEUE_T;

/**
 * @brief Initializes a given queue with a given buffer.
 * @param[in] pQueue Pointer to the queue to initialize.
 * @param[in] pBuffer Pointer to a buffer to initialize the queue with.
 * @param[in] sizeOfElements Size of elements in the given buffer.
 * @param[in] numberOfElements Number of elements in the given buffer.
 */
void queue_Init(QUEUE_T * pQueue, void * pBuffer, BYTE sizeOfElements, BYTE numberOfElements);

/**
 * @brief Enqueues a given element to a given queue.
 * @param[in] pQueue Pointer to a queue.
 * @param[in] pElement Pointer to an element.
 * @return TRUE if element was enqueued, FALSE otherwise.
 */
BOOL queue_Enqueue(QUEUE_T * pQueue, void * pElement);

/**
 * @brief Dequeues a given element from a given queue.
 * @param[in] pQueue Pointer to a queue.
 * @param[out] pElement Pointer to an element.
 * @return TRUE if element was dequeued, FALSE otherwise.
 */
BOOL queue_Dequeue(QUEUE_T * pQueue, void * pElement);

/**
 * @brief Get number of elements in queue.
 * @param[in] pQueue Pointer to a queue.
 * @return Number of queue elements.
 */
uint8_t queue_GetItemCount(QUEUE_T * pQueue);

#endif

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值