下面是队列接口实现代码 有疑问可以讨论
队列接口实现文件
queue_api.c
/*********************************************************************
* 版权所有 (c) 2021-2022 axk. 保留所有版权
* 文件名称: queue_api.c
* 文件描述: 标准队列操作接口实现
* 作 者: axk
* 创建日期: 2022/11/23
* 作 者 日 期 版 本 修改摘要
* axk 2022/11/23 1.0 文件创建
**********************************************************************/
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include "axk_base_data_type.h"
#include "queue_api.h"
/***********************************************************************
* 函数名称: queue_node_free
* 功能描述: 释放队列节点内存
* 输 入:node 需要释放的节点
* 输 出: 无
* 返 回 值: void
* 其 他:
* 日 期: 2022/11/21
* 作 者: axk
***********************************************************************/
void queue_node_free(queue_node_s_type* node)
{
if (NULL != node)
{
if (NULL != node->data)
{
if (NULL != node->free_cb)
{
node->free_cb(node->data);
}
}
node->next = NULL;
node->prev = NULL;
free(node);
node = NULL;
}
}
/***********************************************************************
* 函数名称: queue_push
* 功能描述: 入队一个节点
* 输 入:queue_head 队列头
* data 节点数据内容
* free_cb 节点数据free函数 (如果节点释放不需要free数据则填空)
* 输 出: 无
* 返 回 值: 成功返回0 失败返回对应错误码
* 其 他:
* 日 期: 2022/11/23
* 作 者: axk
***********************************************************************/
int queue_push(queue_head_s_type* queue_head, void* data, queue_data_free_cb free_cb)
{
queue_node_s_type* data_node = NULL;
queue_node_s_type* tmp_node = NULL;
if (NULL == queue_head || NULL == data)
{
AXK_LOGE("queue_head or data is NULL!");
return AXK_ERR_PARAMETER;
}
data_node = (queue_node_s_type*)malloc(sizeof(queue_node_s_type));
if (NULL == data_node)
{
AXK_LOGE("data_node malloc failed!");
return AXK_ERR_MALLOC;
}
memset(data_node, 0x0, sizeof(queue_node_s_type));
data_node->next = NULL;
data_node->prev = NULL;
data_node->data = data;
data_node->free_cb = free_cb;
if (NULL != queue_head->tail)
{
queue_head->tail->next = data_node;
data_node->prev = queue_head->tail;
queue_head->tail = data_node;
}
else
{
queue_head->head = data_node;
queue_head->tail = data_node;
}
queue_head->node_num++;
return AXK_SUCCESS;
}
/***********************************************************************
* 函数名称: queue_pop
* 功能描述: 出队一个节点
* 输 入:queue_head 队列头
* 输 出: 无
* 返 回 值: 成功返回节点地址(需要外部释放,节点数据内存也需要释放)
失败返回NULL
* 其 他:
* 日 期: 2022/11/23
* 作 者: axk
***********************************************************************/
queue_node_s_type* queue_pop(queue_head_s_type* queue_head)
{
queue_node_s_type* tmp_node = NULL;
if (NULL == queue_head)
{
AXK_LOGE("queue_head is NULL!");
return NULL;
}
if (NULL == queue_head->head)
{
AXK_LOGE("queue_head is empty!");
return NULL;
}
tmp_node = queue_head->head;
if (NULL != tmp_node->next)
{
queue_head->head = tmp_node->next;
queue_head->head->prev = NULL;
}
else
{
queue_head->tail = NULL;
queue_head->head = NULL;
}
queue_head->node_num--;
return tmp_node;
}
/***********************************************************************
* 函数名称: queue_get_head_node
* 功能描述: 获取队列头部数据节点
* 输 入:queue_head 队列头
* 输 出: 无
* 返 回 值: 成功返回头节点指针 失败返回NULL
* 其 他:
* 日 期: 2022/11/23
* 作 者: axk
***********************************************************************/
queue_node_s_type* queue_get_head_node(queue_head_s_type* queue_head)
{
if (NULL == queue_head)
{
AXK_LOGE("queue_head is NULL!");
return NULL;
}
return queue_head->head;
}
/***********************************************************************
* 函数名称: queue_get_tail_node
* 功能描述: 获取队列尾部数据节点
* 输 入:queue_head 队列头
* 输 出: 无
* 返 回 值: 成功返回尾部节点指针 失败返回NULL
* 其 他:
* 日 期: 2022/11/23
* 作 者: axk
***********************************************************************/
queue_node_s_type* queue_get_tail_node(queue_head_s_type* queue_head)
{
if (NULL == queue_head)
{
AXK_LOGE("queue_head is NULL!");
return NULL;
}
return queue_head->tail;
}
/***********************************************************************
* 函数名称: queue_destory
* 功能描述: 队列销毁
* 输 入:queue_head 队列头
* 输 出: 无
* 返 回 值: 成功返回0 失败返回对应错误码
* 其 他:
* 日 期: 2022/11/23
* 作 者: axk
***********************************************************************/
int queue_destory(queue_head_s_type* queue_head)
{
queue_node_s_type* tmp_node = NULL;
if (NULL == queue_head)
{
AXK_LOGE("queue_head is NULL!");
return AXK_ERR_PARAMETER;
}
while (0 != queue_head->node_num)
{
tmp_node = queue_head->tail;
if (NULL != tmp_node->prev)
{
queue_head->tail = tmp_node->prev;
queue_head->tail->next = NULL;
}
else
{
queue_head->tail = NULL;
queue_head->head = NULL;
}
queue_node_free(tmp_node);
queue_head->node_num--;
}
return AXK_SUCCESS;
}
/***********************************************************************
* 函数名称: queue_init
* 功能描述: 队列初始化
* 输 入:queue_head 队列头
* 输 出: 无
* 返 回 值: 成功返回0 失败返回对应错误码
* 其 他:
* 日 期: 2022/11/23
* 作 者: axk
***********************************************************************/
int queue_init(queue_head_s_type* queue_head)
{
if (NULL == queue_head)
{
AXK_LOGE("queue_head is NULL!");
return AXK_ERR_PARAMETER;
}
queue_destory(queue_head);
queue_head->node_num = 0;
queue_head->head = NULL;
queue_head->tail = NULL;
return AXK_SUCCESS;
}
队列接口头文件
/*********************************************************************
* 版权所有 (h) 2021-2022 axk. 保留所有版权
* 文件名称: queue_api.h
* 文件描述: 标准队列操作接口头文件
* 作 者: axk
* 创建日期: 2022/11/23
* 作 者 日 期 版 本 修改摘要
* axk 2022/11/23 1.0 文件创建
**********************************************************************/
#ifndef __QUEUE_API_H_
#define __QUEUE_API_H_
#include "axk_base_data_type.h"
#ifdef __cplusplus
extern "C" {
#endif
/****************************QUEUE_API 宏定义 start****************************************************/
/****************************QUEUE_API 宏定义 end****************************************************/
/****************************QUEUE_API 枚举定义 start****************************************************/
/****************************QUEUE_API 枚举定义 end****************************************************/
/****************************QUEUE_API 结构体定义 start****************************************************/
/* 释放节点数据回调函数 */
typedef void (*queue_data_free_cb)(void* data);
/* 队列节点结构体 */
typedef struct queue_node_s_type
{
struct queue_node_s_type* next;
struct queue_node_s_type* prev;
void* data;
queue_data_free_cb free_cb;
} queue_node_s_type;
/* 队列头结构体 */
typedef struct queue_head_s_type
{
int node_num;
struct queue_node_s_type* head;
struct queue_node_s_type* tail;
} queue_head_s_type;
/****************************QUEUE_API 结构体定义 end****************************************************/
/****************************QUEUE_API 函数声明 start****************************************************/
/***********************************************************************
* 函数名称: queue_push
* 功能描述: 入队一个节点
* 输 入:queue_head 队列头
* data 节点数据内容
* free_cb 节点数据free函数 (如果节点释放不需要free数据则填空)
* 输 出: 无
* 返 回 值: 成功返回0 失败返回对应错误码
* 其 他:
* 日 期: 2022/11/23
* 作 者: axk
***********************************************************************/
int queue_push(queue_head_s_type* queue_head, void* data, queue_data_free_cb free_cb);
/***********************************************************************
* 函数名称: queue_pop
* 功能描述: 出队一个节点
* 输 入:queue_head 队列头
* 输 出: 无
* 返 回 值: 成功返回节点地址(需要外部释放,节点数据内存也需要释放)
失败返回NULL
* 其 他:
* 日 期: 2022/11/23
* 作 者: axk
***********************************************************************/
queue_node_s_type* queue_pop(queue_head_s_type* queue_head);
/***********************************************************************
* 函数名称: queue_get_head_node
* 功能描述: 获取队列头部数据节点
* 输 入:queue_head 队列头
* 输 出: 无
* 返 回 值: 成功返回头节点指针 失败返回NULL
* 其 他:
* 日 期: 2022/11/23
* 作 者: axk
***********************************************************************/
queue_node_s_type* queue_get_head_node(queue_head_s_type* queue_head);
/***********************************************************************
* 函数名称: queue_get_tail_node
* 功能描述: 获取队列尾部数据节点
* 输 入:queue_head 队列头
* 输 出: 无
* 返 回 值: 成功返回尾部节点指针 失败返回NULL
* 其 他:
* 日 期: 2022/11/23
* 作 者: axk
***********************************************************************/
queue_node_s_type* queue_get_tail_node(queue_head_s_type* queue_head);
/***********************************************************************
* 函数名称: queue_destory
* 功能描述: 链表销毁
* 输 入:queue_head 队列头
* 输 出: 无
* 返 回 值: 成功返回0 失败返回对应错误码
* 其 他:
* 日 期: 2022/11/23
* 作 者: axk
***********************************************************************/
int queue_destory(queue_head_s_type* queue_head);
/***********************************************************************
* 函数名称: queue_init
* 功能描述: 队列初始化
* 输 入:queue_head 队列头
* 输 出: 无
* 返 回 值: 成功返回0 失败返回对应错误码
* 其 他:
* 日 期: 2022/11/23
* 作 者: axk
***********************************************************************/
int queue_init(queue_head_s_type* queue_head);
/****************************QUEUE_API 函数声明 end****************************************************/
#ifdef __cplusplus
}
#endif
#endif
队列接口测试代码
/*********************************************************************
* 版权所有 (c) 2021-2022 axk. 保留所有版权
* 文件名称: queue_test.c
* 文件描述: 队列接口测试文件
* 作 者: axk
* 创建日期: 2022/11/23
* 作 者 日 期 版 本 修改摘要
* axk 2022/11/23 1.0 文件创建
**********************************************************************/
/* 示例代码数据内容是char*类型字符串 实际使用可以是任意类型指针 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "queue_api.h"
#include "axk_base_data_type.h"
void print_queue(queue_head_s_type* queue_head)
{
queue_node_s_type* tmp_node = NULL;
int i = 0;
if (NULL == queue_head || 0 == queue_head->node_num)
{
printf("curr queue is NULL!\n");
return ;
}
tmp_node = queue_head->head;
while (NULL != tmp_node)
{
printf("node %d content %s.\n", i++, (char*)tmp_node->data);
tmp_node = tmp_node->next;
}
}
int main(void)
{
int menu = 0;
queue_head_s_type queue_head;
memset(&queue_head, 0x0, sizeof(queue_head_s_type));
queue_init(&queue_head);
while (1)
{
print_queue(&queue_head);
menu = 0;
printf("please select menu: \n" \
"1.queue init \n" \
"2.queue destory\n" \
"3.queue push\n" \
"4.queue pop\n" \
"5.get queue head data\n" \
"6.get queue tail data\n" \
"0.exit \n");
scanf("%d", &menu);
switch (menu)
{
case 1:
{
queue_init(&queue_head);
break;
}
case 2:
{
queue_destory(&queue_head);
break;
}
case 3:
{
char* data = (char*)malloc(128);
if (NULL == data)
{
printf("\nmalloc failed!\n");
break;
}
memset(data, 0x0, 128);
printf("please input data:\n");
scanf("%s", data);
queue_push(&queue_head, data, free);
break;
}
case 4:
{
queue_node_s_type* tmp_node = queue_pop(&queue_head);
if (NULL != tmp_node)
{
printf("node data is %s\n", (char*)tmp_node->data);
free(tmp_node->data);
free(tmp_node);
}
else
{
printf("queue is NULL!\n");
}
break;
}
case 5:
{
queue_node_s_type* tmp_node = queue_get_head_node(&queue_head);
if (NULL != tmp_node)
{
printf("node data is %s\n", (char*)tmp_node->data);
}
else
{
printf("queue is NULL!\n");
}
break;
}
case 6:
{
queue_node_s_type* tmp_node = queue_get_tail_node(&queue_head);
if (NULL != tmp_node)
{
printf("node data is %s\n", (char*)tmp_node->data);
}
else
{
printf("queue is NULL!\n");
}
break;
}
case 0:
{
exit(0);
break;
}
default:
{
printf("nosuppurt menu %d!!!\n", menu);
break;
}
}
}
queue_destory(&queue_head);
return 0;
}