数据结构--链式队列

1. 简介

队列是限制在两端进行插入操作和删除操作的线性表,允许进行存入操作的一端称为“队尾”,允许进行删除操作的一端称为“队头”。当线性表中没有元素时,称为“空队”。特点:先进先出(FIFO)。

2. 源码

[LinkQueue.c]

/*
*********************************************************************************************************
* @file     LinkQueue.c
* @author   SY
* @version  V1.0.1
* @date     2016-9-12 13:08:32
* @IDE      V4.70.0.0
* @Chip     STM32F407VE
* @brief    链式队列源文件
*********************************************************************************************************
* @attention
*   队列是限制在两端进行插入操作和删除操作的线性表,允许进行存入操作的一端称为“队尾”,
*   允许进行删除操作的一端称为“队头”。当线性表中没有元素时,称为“空队”。特点:先进先出(FIFO)。
* -------------------------------------------------------------------------------------------------------
* 版本:V1.0.1     修改人:SY      修改日期:2016-9-12 13:08:40
* 
* 1、增加链式队列的遍历。
* -------------------------------------------------------------------------------------------------------   
*   
*
* 
*********************************************************************************************************
*/

/*
*********************************************************************************************************
*                                           Private Includes
*********************************************************************************************************
*/
#include "utils.h"
#include "LinkQueue.h"


/*
*********************************************************************************************************
*                                           Private define
*********************************************************************************************************
*/


/*
*********************************************************************************************************
*                                           Private typedef
*********************************************************************************************************
*/

/*
*********************************************************************************************************
*                                           Private constants
*********************************************************************************************************
*/

/*
*********************************************************************************************************
*                                           Private macro
*********************************************************************************************************
*/

/*
*********************************************************************************************************
*                                           Private variables
*********************************************************************************************************
*/

/*
*********************************************************************************************************
*                                           Private function prototypes
*********************************************************************************************************
*/

/*
*********************************************************************************************************
*                                           Private functions
*********************************************************************************************************
*/
/*
*********************************************************************************************************
* Function Name : CreateLinkQueue
* Description   : 创建链式队列(内存空间由内部提供、动态内存)
* Input         : None
* Output        : None
* Return        : None
*********************************************************************************************************
*/
LINK_QUEUE_TypeDef *CreateLinkQueue( void )
{
    /* 生成头指针 */
    LINK_QUEUE_TypeDef *pHead = (LINK_QUEUE_TypeDef *)calloc(1,sizeof(LINK_QUEUE_TypeDef));
    if (pHead == NULL)
    {
        return NULL;
    }

    /* 生成头结点 */
    LINK_QUEUE_NODE_TypeDef *pNode = (LINK_QUEUE_NODE_TypeDef *)calloc(1,sizeof(LINK_QUEUE_NODE_TypeDef));
    if (pNode == NULL)
    {
        return NULL;
    }

    pNode->data = NULL;
    pNode->next = NULL;
    pHead->front = pNode;
    pHead->rear = pNode;

    return pHead;
}

/*
*********************************************************************************************************
* Function Name : LinkQueueIsEmpty
* Description   : 链式队列是否为空
* Input         : None
* Output        : None
* Return        : None
*********************************************************************************************************
*/
DATA_STRUCT_STATUS_ENUM LinkQueueIsEmpty( LINK_QUEUE_TypeDef *pHead )
{
    if (pHead == NULL)
    {
        return STATUS_DATA_STRUCT_UNDEFINED;
    }

    if (pHead->front->next == NULL)
    {
        return STATUS_DATA_STRUCT_TRUE;
    }
    else
    {
        return STATUS_DATA_STRUCT_FALSE;
    }
}

/*
*********************************************************************************************************
* Function Name : ClearLinkQueue
* Description   : 清空链式队列
* Input         : None
* Output        : None
* Return        : None
*********************************************************************************************************
*/
void ClearLinkQueue( LINK_QUEUE_TypeDef *pHead )
{
    if (pHead != NULL)
    {
        LINK_QUEUE_NODE_TypeDef *oldNode = NULL;

        while (pHead->front->next != NULL)
        {
            oldNode = pHead->front->next;
            pHead->front->next = oldNode->next;
            oldNode->next = NULL;

            if (oldNode->data != NULL)
            {
                free(oldNode->data);
                oldNode->data = NULL;
            }

            free(oldNode);
            oldNode = NULL;             
        }

        pHead->rear = pHead->front;
    }
}

/*
*********************************************************************************************************
* Function Name : DestoryLinkQueue
* Description   : 销毁链式队列
* Input         : None
* Output        : None
* Return        : None
*********************************************************************************************************
*/
void DestoryLinkQueue( LINK_QUEUE_TypeDef **pHead )
{
    LINK_QUEUE_TypeDef *this = *pHead;

    if (this != NULL)
    {
        ClearLinkQueue(this);

        if (this->front != NULL)
        {
            /* 释放头结点 */
            free(this->front);
            this->front = this->rear = NULL;

            /* 释放头指针 */
            free(this);

            *pHead = NULL;
        }
    }
}

/*
*********************************************************************************************************
* Function Name : PushLinkQueue
* Description   : 链式队列入队
* Input         : None
* Output        : None
* Return        : None
*********************************************************************************************************
*/
DATA_STRUCT_STATUS_ENUM PushLinkQueue( LINK_QUEUE_TypeDef *pHead, void *dataIn, uint32_t dataSize )
{
    if (pHead == NULL)
    {
        return STATUS_DATA_STRUCT_UNDEFINED;
    }

    /* 增加新节点 */
    LINK_QUEUE_NODE_TypeDef *pNode = (LINK_QUEUE_NODE_TypeDef *)calloc(1,sizeof(LINK_QUEUE_NODE_TypeDef));
    if (pNode == NULL)
    {
        return STATUS_DATA_STRUCT_FALSE;
    }
    pNode->next = NULL; 

    if (pHead->front->next == NULL)
    {
        pHead->rear = pHead->front;
    }
    pHead->rear->next = pNode;
    pHead->rear = pNode;

    /* 存储用户数据 */
    pNode->data = (void *)calloc(1,dataSize);
    if (pNode->data == NULL)
    {
        return STATUS_DATA_STRUCT_FALSE;
    }   
    memcpy(pNode->data,dataIn,dataSize);

    return STATUS_DATA_STRUCT_TRUE;
}

/*
*********************************************************************************************************
* Function Name : PopLinkQueue
* Description   : 链式队列出队
* Input         : None
* Output        : None
* Return        : None
*********************************************************************************************************
*/
DATA_STRUCT_STATUS_ENUM PopLinkQueue( LINK_QUEUE_TypeDef *pHead, void *dataOut, uint32_t dataSize )
{
    if (pHead == NULL)
    {
        return STATUS_DATA_STRUCT_UNDEFINED;
    }

    if (LinkQueueIsEmpty(pHead) == STATUS_DATA_STRUCT_TRUE)
    {
        return STATUS_DATA_STRUCT_FALSE;
    }

    /* 出队时,头指针始终指向头结点,出队头结点后面的节点 */
    LINK_QUEUE_NODE_TypeDef *oldNode = pHead->front->next;  
    pHead->front->next = oldNode->next;
    oldNode->next = NULL;
    if (pHead->front->next == NULL)
    {
        pHead->rear = pHead->front;
    }

    DATA_STRUCT_STATUS_ENUM isDataOK = STATUS_DATA_STRUCT_FALSE;
    if (oldNode->data != NULL)
    {
        memcpy(dataOut,oldNode->data,dataSize);
        free(oldNode->data);
        oldNode->data = NULL;
        isDataOK = STATUS_DATA_STRUCT_TRUE;
    }
    free(oldNode);
    oldNode = NULL;

    return isDataOK;
}

/*
*********************************************************************************************************
* Function Name : GetLinkQueueElement
* Description   : 获取链式队列元素
* Input         : None
* Output        : None
* Return        : None
*********************************************************************************************************
*/
DATA_STRUCT_STATUS_ENUM GetLinkQueueElement( LINK_QUEUE_TypeDef *pHead, void *dataOut, uint32_t dataSize )
{
    if (pHead == NULL)
    {
        return STATUS_DATA_STRUCT_UNDEFINED;
    }

    if (LinkQueueIsEmpty(pHead) == STATUS_DATA_STRUCT_TRUE)
    {
        return STATUS_DATA_STRUCT_FALSE;
    }

    /* 出队时,头指针始终指向头结点,出队头结点后面的节点 */
    DATA_STRUCT_STATUS_ENUM isDataOK = STATUS_DATA_STRUCT_FALSE;
    LINK_QUEUE_NODE_TypeDef *oldNode = pHead->front->next;      
    if (oldNode->data != NULL)
    {
        memcpy(dataOut,oldNode->data,dataSize);
        isDataOK = STATUS_DATA_STRUCT_TRUE;
    }

    return isDataOK;
}

/*
*********************************************************************************************************
* Function Name : TraverseLinkQueue
* Description   : 遍历链式队列
* Input         : None
* Output        : None
* Return        : None
*********************************************************************************************************
*/
void TraverseLinkQueue( LINK_QUEUE_TypeDef *pHead, void *dataOut, uint32_t dataSize,\
        void (*show_CallBack)( void *dataOut ) )
{
    LINK_QUEUE_TypeDef queue = *pHead;
    LINK_QUEUE_NODE_TypeDef *pNode = queue.front->next;

    while (pNode != NULL)
    {
        memcpy(dataOut,pNode->data,dataSize);

        if (show_CallBack)
        {
            show_CallBack(dataOut);
        }

        pNode = pNode->next;
    }
}

/************************ (C) COPYRIGHT STMicroelectronics **********END OF FILE*************************/
[LinkQueue.h]

/*
*********************************************************************************************************
* @file     LinkQueue.h
* @author   SY
* @version  V1.0.0
* @date     2016-9-1 11:17:33
* @IDE      V4.70.0.0
* @Chip     STM32F407VE
* @brief    链式队列头文件
*********************************************************************************************************
* @attention
*
* 
*********************************************************************************************************
*/

/*
*********************************************************************************************************
*                                           Define to prevent recursive inclusion
*********************************************************************************************************
*/
#ifndef __LINKQUEUE_H
#define __LINKQUEUE_H

/*
*********************************************************************************************************
*                                           Exported Includes
*********************************************************************************************************
*/



/*
*********************************************************************************************************
*                                           Exported define
*********************************************************************************************************
*/

/*
*********************************************************************************************************
*                                           Exported types
*********************************************************************************************************
*/
typedef struct tagLINK_QUEUE_NODE_TypeDef
{
    void *data;
    struct tagLINK_QUEUE_NODE_TypeDef *next;
}LINK_QUEUE_NODE_TypeDef;

typedef struct
{
    LINK_QUEUE_NODE_TypeDef *front;
    LINK_QUEUE_NODE_TypeDef *rear;
}LINK_QUEUE_TypeDef;


/*
*********************************************************************************************************
*                                           Exported constants
*********************************************************************************************************
*/

/*
*********************************************************************************************************
*                                           Exported macro
*********************************************************************************************************
*/

/*
*********************************************************************************************************
*                                           Exported variables
*********************************************************************************************************
*/

/*
*********************************************************************************************************
*                                           Exported functions
*********************************************************************************************************
*/
LINK_QUEUE_TypeDef *CreateLinkQueue( void );
DATA_STRUCT_STATUS_ENUM LinkQueueIsEmpty( LINK_QUEUE_TypeDef *pHead );
void ClearLinkQueue( LINK_QUEUE_TypeDef *pHead );
void DestoryLinkQueue( LINK_QUEUE_TypeDef **pHead );
DATA_STRUCT_STATUS_ENUM PushLinkQueue( LINK_QUEUE_TypeDef *pHead, void *dataIn, uint32_t dataSize );
DATA_STRUCT_STATUS_ENUM PopLinkQueue( LINK_QUEUE_TypeDef *pHead, void *dataOut, uint32_t dataSize );
DATA_STRUCT_STATUS_ENUM GetLinkQueueElement( LINK_QUEUE_TypeDef *pHead, void *dataOut, uint32_t dataSize );
void TraverseLinkQueue( LINK_QUEUE_TypeDef *pHead, void *dataOut, uint32_t dataSize,\
        void (*show_CallBack)( void *dataOut ) );


#endif
/************************ (C) COPYRIGHT STMicroelectronics **********END OF FILE*************************/

备注:


1、本文以链表形式实现队列,使用动态内存存储链表节点及数据域。
2、采用泛型编程思想,不限制数据类型。数据可以是基本数据类型也可以是复合数据类型。

3、测试

[main.c]

/*
*********************************************************************************************************
* Function Name : TestSeqQueue
* Description   : 测试顺序队列
* Input         : None
* Output        : None
* Return        : None
*********************************************************************************************************
*/
void PrintSeqQueue( void *data )
{
    uint8_t *temp = data;

    printf("%d\r\n",*temp);
}

/*
*********************************************************************************************************
* Function Name : TestLinkQueue
* Description   : 测试链式队列
* Input         : None
* Output        : None
* Return        : None
*********************************************************************************************************
*/
void TestLinkQueue( void )
{
    LINK_QUEUE_TypeDef *pHead = CreateLinkQueue();
    if (pHead == NULL)
    {
        printf("内存分配失败!\r\n");

        return;
    }

    {
        for (uint8_t i=1; i<=3; ++i)
        {
            PushLinkQueue(pHead, &i, sizeof(i));
        }

        uint8_t dataBuff = 0;

        printf("----- STATR -----\r\n");
        TraverseLinkQueue(pHead, &dataBuff, sizeof(dataBuff), PrintSeqQueue);
        printf("----- E N D -----\r\n\r\n");
    }

    {
        uint8_t dataBuff = 0;
        PopLinkQueue(pHead,&dataBuff, sizeof(dataBuff));
        printf("出队元素:%d\r\n",dataBuff);

        printf("----- STATR -----\r\n");
        TraverseLinkQueue(pHead, &dataBuff, sizeof(dataBuff), PrintSeqQueue);
        printf("----- E N D -----\r\n\r\n");
    }
}

/*
*********************************************************************************************************
* Function Name : main
* Description   : 入口函数
* Input         : None
* Output        : None
* Return        : None
*********************************************************************************************************
*/
int main( void )
{
    InitSystem();

    TestLinkQueue();

    while (1);  
}

打印结果:


—– STATR —–
1
2
3
—– E N D —–

出队元素:1
—– STATR —–
2
3
—– E N D —–

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值