QueueStruct.h
/**********************************************************************************
* @file QueueStruct.h
* @brief 队列结构及其常用操作(C语言实现)
*
* @attention
*
* @note 可选队列实现方式,链表或数组
* 使用数组实现队列的优点和缺点:
* 优点:
* 实现简单:使用数组实现队列比较直观和简单,不需要考虑指针之间的连接关系。
* 内存占用少:数组在内存中是一块连续的存储空间,相比链表在存储指针的开销上要少一些。
* 缺点:
* 静态大小:数组的大小在初始化时就确定,队列的大小受限于数组大小,无法动态扩展。
* 频繁的操作影响性能:在队列头部插入或删除元素时,需要频繁地搬移数组元素,影响性能。
*
* 使用链表实现队列的优点和缺点:
* 优点:
* 动态大小:链表实现的队列可以动态扩展或缩小,不受固定大小的限制,更加灵活。
* 插入、删除性能好:在链表的头尾进行插入、删除操作时,时间复杂度为 O(1)。
* 缺点:
* 占用更多内存:链表中每个节点都需要存储指针信息,会占用更多的内存空间。
* 实现复杂:相比数组实现,链表需要考虑指针的操作和连接,实现起来相对复杂一些。
*总结:个人认为,由于现在MCU内存容量的提升,链表的实现方式,除了实现复杂,其余都是优点。
*
*
* @version V1.0
* - 编写队列数据结构(采用数组循环)和基本操作(创建、判空、判满、入队、出队)
*
* @date 2024-03-22
**********************************************************************************/
#ifndef __QUEUE_STRUCT__H_
#define __QUEUE_STRUCT__H_
#define QueueStruct_MAX_SIZE 100 // 队列内存大小
#pragma pack(1)
typedef enum
{
__Queue_SUCCESSFUL = 0, // 操作成功,非满,非空
__Queue_FAILEDL = -1, // 操作失败
__Queue_Is_EMPTY = 1001, // 队列空
__Queue_Is_FULL = 1002, // 队列满
__Queue_ERR_CODE_END
}E_QueueErrCode;
typedef struct
{
void* aElement[QueueStruct_MAX_SIZE];
int nFrontIndex; // 队列头部索引
int nRearIndex; // 队列尾部索引
}T_Queue;
#pragma pack()
/**********************************************************************************
* @brief 创建空队列
*
* @param
*
* @return - T_Queue*
*
* @details
*
* @note
**********************************************************************************/
T_Queue* CreateQueue();
/**********************************************************************************
* @brief 判断队列是否空
*
* @param - T_Queue*
*
* @return - __SUCCESSFUL 非空
* - __FAILED 空
* - __ABNORMAL 其它异常
*
* @details
*
* @note
**********************************************************************************/
int QueueIsEmpty(T_Queue* ptQueue);
/**********************************************************************************
* @brief 判断队列是否满
*
* @param - T_Queue*
*
* @return - __SUCCESSFUL 非满
* - __FAILED 满
* - __ABNORMAL 其它异常
*
* @details
*
* @note
**********************************************************************************/
int QueueIsFull(T_Queue* ptQueue);
/**********************************************************************************
* @brief 队尾入队
*
* @param - T_Queue*
*
* @return - __FAILED
* - __SUCCESSFUL
*
* @details
*
* @note
**********************************************************************************/
int EnterRearQueue(T_Queue* ptQueue, void* pElement);
/**********************************************************************************
* @brief 队头出队
*
* @param - T_Queue*
* - void* 出队元素指针
*
* @return - __FAILED
* - __SUCCESSFUL
* @details
*
* @note
**********************************************************************************/
int DeleteFrontQueue(T_Queue* ptQueue, void** pElement);
#endif // __QUEUE_STRUCT__H_
QueueStruct.c
#include <stdio.h>
#include <stdlib.h>
#include "QueueStruct.h"
T_Queue* CreateQueue()
{
T_Queue* tQueue = (T_Queue*)malloc(sizeof(T_Queue));
if (NULL == tQueue)
{
printf("<queue><create> Memory allocation failed.\n");
return NULL;
}
tQueue->nFrontIndex = -1;
tQueue->nRearIndex = -1;
return tQueue;
}
int QueueIsEmpty(T_Queue* ptQueue)
{
if ( (ptQueue->nFrontIndex == ptQueue->nRearIndex) || (-1 == ptQueue->nFrontIndex) && (-1 == ptQueue->nRearIndex) )
{
printf("<Queue><isEmpty><Error> Queue is empty.frot=%d, rear=%d\n", ptQueue->nFrontIndex, ptQueue->nRearIndex);
return __Queue_Is_EMPTY; // 队列空
}
else if ((ptQueue->nFrontIndex != ptQueue->nRearIndex) || (0 <= ptQueue->nRearIndex))
return __Queue_SUCCESSFUL;
else
{
printf("<Queue><isEmpty><Error> Queue is abnormal.frot=%d, rear=%d\n", ptQueue->nFrontIndex, ptQueue->nRearIndex);
return __Queue_FAILEDL;
}
}
int QueueIsFull(T_Queue* ptQueue)
{
if ((QueueStruct_MAX_SIZE-1) <= ptQueue->nRearIndex)
{
printf("<Queue><isFull><Error> Queue is full.frot=%d, rear=%d\n", ptQueue->nFrontIndex, ptQueue->nRearIndex);
return __Queue_Is_FULL; // 队列满
}
else if ((QueueStruct_MAX_SIZE-1) >= ptQueue->nRearIndex)
return __Queue_SUCCESSFUL;
else
{
printf("<Queue><isFull><Error> Queue is abnormal.frot=%d, rear=%d\n", ptQueue->nFrontIndex, ptQueue->nRearIndex);
return __Queue_FAILEDL;
}
}
int EnterRearQueue(T_Queue* ptQueue, void* pElement)
{
// 判满
int nResult1 = QueueIsFull(ptQueue);
if (__Queue_SUCCESSFUL != nResult1)
{
printf("<Queue><EnQue><Error> Queue is full or abnormal. QueueIsFull()=%d\n", nResult1);
return __Queue_FAILEDL;
}
// ++ptQueue->nRearIndex; // rear后移,没考虑取模,会有假性溢出问题
ptQueue->nRearIndex = (ptQueue->nRearIndex+1) % QueueStruct_MAX_SIZE; // 考虑取模,循环队列
ptQueue->aElement[ptQueue->nRearIndex] = pElement;
return __Queue_SUCCESSFUL;
}
int DeleteFrontQueue(T_Queue* ptQueue, void** pElement)
{
// 判空
int nResult = QueueIsEmpty(ptQueue);
if (__Queue_SUCCESSFUL != nResult)
{
printf("<Queue><DeQue><Error> Queue is empty. QueueIsEmpty()=%d\n", nResult);
return __Queue_FAILEDL;
}
// ++ptQueue->nFrontIndex; // front后移,没考虑取模,会有假性溢出问题
ptQueue->nFrontIndex = (ptQueue->nFrontIndex+1) % QueueStruct_MAX_SIZE; // 考虑取模
*pElement = ptQueue->aElement[ptQueue->nFrontIndex];
ptQueue->aElement[ptQueue->nFrontIndex] = NULL;
return __Queue_SUCCESSFUL;
}

5663

被折叠的 条评论
为什么被折叠?



