FIFO 队列实现

This commit is contained in:
建峰 2024-06-22 01:37:27 +08:00
parent f7843c7226
commit 22c5df495d
7 changed files with 427 additions and 104 deletions

View File

@ -1,3 +1,13 @@
/**
* @file queue.h
* @author wenjf (Orig5826@163.com)
* @brief
* @version 0.1
* @date 2024-06-22
*
* @copyright Copyright (c) 2024
*
*/
#ifndef _QUEUE_H_ #ifndef _QUEUE_H_
#define _QUEUE_H_ #define _QUEUE_H_
@ -35,7 +45,41 @@ bool queue_get_rear(pqueue_t head, queue_data_t *data);
#endif #endif
struct _queue_node
{
void *obj;
struct _queue_node * next;
};
struct _queue
{
struct _queue_node * _front;
struct _queue_node * _back;
uint32_t _obj_size; // 元素大小
uint32_t _size; // 栈大小
uint32_t _capacity; // 总容量
uint32_t _ratio; // 扩展比率
// kernel
bool (*push)(struct _queue* self, void* obj);
bool (*pop)(struct _queue* self, void* obj);
bool (*back)(struct _queue* self, void* obj);
bool (*front)(struct _queue* self, void* obj);
bool (*clear)(struct _queue* self);
bool (*empty)(struct _queue* self);
uint32_t (*size)(struct _queue* self);
// free
void (*destory)(struct _queue* self);
// print
void (*print)(struct _queue* self);
void (*print_obj)(void* obj);
};
bool queue_init(struct _queue * queue, uint32_t obj_size);
#endif // _QUEUE_H_ #endif // _QUEUE_H_

View File

@ -4,135 +4,286 @@
bool queue_init(pqueue_t * head) bool queue_init(pqueue_t * head)
{ {
*head = (pqueue_t)malloc(sizeof(queue_t)); *head = (pqueue_t)malloc(sizeof(queue_t));
if(*head == NULL) ifqueue_head == NULL)
{ {
return false; return false;
} }
(*head)->front = NULL; queue_head)->front = NULL;
(*head)->rear = NULL; queue_head)->rear = NULL;
(*head)->size = 0; queue_head)->size = 0;
return true; return true;
} }
void queue_destroy(pqueue_t * head) void queue_destroy(pqueue_t * head)
{ {
if(*head != NULL) ifqueue_head != NULL)
{ {
queue_clear(*head); queue_clearqueue_head);
free(*head); freequeue_head);
*head = NULL; *head = NULL;
} }
} }
bool queue_empty(pqueue_t head) bool queue_empty(pqueue_t head)
{ {
return (head == NULL || head->front == NULL || head->rear == NULL) ? true : false; return (head == NULL || head->front == NULL || head->rear == NULL) ? true : false;
} }
void queue_clear(pqueue_t head) void queue_clear(pqueue_t head)
{ {
pqueue_node_t front_item; pqueue_node_t front_item;
if(head != NULL) if(head != NULL)
{ {
front_item = head->front; front_item = head->front;
while(head->front != NULL) while(head->front != NULL)
{ {
head->front = front_item->next; head->front = front_item->next;
free(front_item); free(front_item);
front_item = head->front; front_item = head->front;
} }
head->rear = head->front; head->rear = head->front;
head->size = 0; head->size = 0;
} }
} }
uint32_t queue_get_size(pqueue_t head) uint32_t queue_get_size(pqueue_t head)
{ {
return head->size; return head->size;
} }
bool queue_in(pqueue_t head, queue_data_t data) bool queue_in(pqueue_t head, queue_data_t data)
{ {
pqueue_node_t new_item; pqueue_node_t new_item;
if(head == NULL) if(head == NULL)
{ {
return false; return false;
} }
new_item = (pqueue_node_t)malloc(sizeof(queue_node_t)); new_item = (pqueue_node_t)malloc(sizeof(queue_node_t));
if(new_item == NULL) if(new_item == NULL)
{ {
return false; return false;
} }
new_item->data = data; new_item->data = data;
new_item->next = NULL; new_item->next = NULL;
if(head->front == NULL) if(head->front == NULL)
{ {
head->front = new_item; head->front = new_item;
} }
// insert from tail // insert from tail
if(head->rear != NULL) if(head->rear != NULL)
{ {
head->rear->next = new_item; head->rear->next = new_item;
} }
head->rear = new_item; head->rear = new_item;
if (head->size < _UI32_MAX) if (head->size < _UI32_MAX)
{ {
head->size++; head->size++;
} }
return true; return true;
} }
void queue_out(pqueue_t head, queue_data_t *data) void queue_out(pqueue_t head, queue_data_t *data)
{ {
pqueue_node_t front_item; pqueue_node_t front_item;
if(!queue_empty(head)) if(!queue_empty(head))
{ {
front_item = head->front; front_item = head->front;
*data = front_item->data; *data = front_item->data;
// free the front item // free the front item
head->front = front_item->next; head->front = front_item->next;
free(front_item); free(front_item);
front_item = NULL; front_item = NULL;
if (queue_get_size(head) == 1) if (queue_get_size(head) == 1)
{ {
head->rear = NULL; head->rear = NULL;
} }
if (head > 0) if (head > 0)
{ {
head->size--; head->size--;
} }
} }
} }
bool queue_get_front(pqueue_t head, queue_data_t *data) bool queue_get_front(pqueue_t head, queue_data_t *data)
{ {
if(!queue_empty(head)) if(!queue_empty(head))
{ {
*data = head->front->data; *data = head->front->data;
return true; return true;
} }
else else
{ {
return false; return false;
} }
} }
bool queue_get_rear(pqueue_t head, queue_data_t *data) bool queue_get_rear(pqueue_t head, queue_data_t *data)
{ {
if(!queue_empty(head)) if(!queue_empty(head))
{ {
*data = head->rear->data; *data = head->rear->data;
return true; return true;
} }
else else
{ {
return false; return false;
} }
} }
#endif #endif
bool queue_push(struct _queue* self, void* obj)
{
assert(self != NULL);
assert(obj != NULL);
void * obj_new = malloc(self->_obj_size);
if (obj_new == NULL)
{
return false;
}
memmove(obj_new, obj, self->_obj_size);
struct _queue_node* node_new = (struct _queue_node*)malloc(sizeof(struct _queue_node));
if(node_new == NULL)
{
return false;
}
node_new->obj = obj_new;
node_new->next = NULL;
if(self->empty(self))
{
self->_front = node_new;
self->_back = node_new;
}
else
{
self->_back->next = node_new;
self->_back = node_new;
}
self->_size++;
return true;
}
bool queue_pop(struct _queue* self, void* obj)
{
assert(self != NULL);
if (self->empty(self))
{
return false;
}
struct _queue_node* node = self->_front;
if(obj != NULL)
{
memmove(obj, node->obj, self->_obj_size);
}
self->_front = node->next;
self->_size--;
free(node->obj);
free(node);
return true;
}
bool queue_back(struct _queue* self, void* obj)
{
assert(self != NULL);
if (self->empty(self))
{
return false;
}
memmove(obj, self->_back->obj, self->_obj_size);
return true;
}
bool queue_front(struct _queue* self, void* obj)
{
assert(self != NULL);
if (self->empty(self))
{
return false;
}
memmove(obj, self->_front->obj, self->_obj_size);
return true;
}
bool queue_clear(struct _queue* self)
{
assert(self != NULL);
struct _queue_node* node = self->_front;
struct _queue_node* next = NULL;
while (node)
{
next = node->next;
free(node->obj);
free(node);
node = next;
}
self->_front = NULL;
self->_back = NULL;
self->_size = 0;
return true;
}
bool queue_empty(struct _queue* self)
{
assert(self != NULL);
return !self->size(self);
}
uint32_t queue_size(struct _queue* self)
{
assert(self != NULL);
return self->_size;
}
void queue_destory(struct _queue* self)
{
assert(self != NULL);
self->clear(self);
}
void queue_print(struct _queue* self)
{
assert(self != NULL);
struct _queue_node * node = self->_front;
while (node)
{
self->print_obj(node->obj);
node = node->next;
}
}
bool queue_init(struct _queue * queue, uint32_t obj_size)
{
assert(queue != NULL);
assert(obj_size > 0);
// attribute init
queue->_size = 0;
queue->_obj_size = obj_size;
// queue->_capacity = 0;
// queue->_ratio = 0;
// function init
queue->push = queue_push;
queue->pop = queue_pop;
queue->back = queue_back;
queue->front = queue_front;
queue->clear = queue_clear;
queue->empty = queue_empty;
queue->size = queue_size;
queue->destory = queue_destory;
queue->print = queue_print;
// init front & back
queue->_front = NULL;
queue->_back = NULL;
}

View File

@ -1,16 +1,37 @@
#include "test.h" #include "test.h"
void print_num(void* obj)
{
printf("(%2d ) ", *(int*)obj);
}
void print_struct(void* obj)
{
struct _student* student = (struct _student*)obj;
printf("(%4d:%-8s) ", student->id, student->name);
}
void print_char(void* obj)
{
printf("(%2c ) ", *(char*)obj);
}
void print_str(void* obj)
{
printf("(%s ) ", (char*)obj);
}
int main() int main()
{ {
printf("----- unicstl -----\n"); printf("----- unicstl test -----\n");
// while (1) // while (1)
{ {
// list_test(); // list_test();
// stack_test(); // stack_test();
deque_test(); // deque_test();
queue_test();
// queue_test();
// tree_test(); // tree_test();
// rbtree_test(); // rbtree_test();
} }

View File

@ -19,6 +19,27 @@
#endif #endif
#endif #endif
/**
* @brief test objects
*
*/
struct _student
{
char name[16];
int id;
};
void print_num(void* obj);
void print_char(void* obj);
void print_struct(void* obj);
void print_str(void* obj);
/**
* @brief test function
*
*/
void list_test(void); void list_test(void);
void stack_test(void); void stack_test(void);
void deque_test(void); void deque_test(void);

View File

@ -74,7 +74,7 @@ static void deque_test_num(void)
} }
else else
{ {
printf("pop failed! because stack is empty\n"); printf("pop failed! because it is empty\n");
} }
if (dq.empty(&dq)) if (dq.empty(&dq))
@ -258,7 +258,7 @@ static void deque_test_struct(void)
} }
else else
{ {
printf("pop failed! because stack is empty\n"); printf("pop failed! because it is empty\n");
} }
if (dq.empty(&dq)) if (dq.empty(&dq))

View File

@ -1,4 +1,5 @@
#include "queue.h"
#include "test.h" #include "test.h"
#if QUEUE_TEST == 1 #if QUEUE_TEST == 1
@ -147,9 +148,94 @@ void queue_test(void)
#else #else
static void queue_test_num(void)
{
uint32_t i = 0;
int data[] = { 1,2,3,4,5,6,7,8,9,10 };
int temp = 0;
uint32_t len = sizeof(data) / sizeof(data[0]);
struct _queue queue;
queue_init(&queue, sizeof(int));
queue.print_obj = print_num;
printf("\n\n----- queue_test_num -----\n");
printf("----- after push-----\n");
for (i = 0; i < len; i++)
{
queue.push(&queue, &data[i]);
queue.front(&queue, &temp);
printf("front = ");
queue.print_obj(&temp);
queue.back(&queue, &temp);
printf("\tback = ");
queue.print_obj(&temp);
printf("\tsize = %2d\n", queue.size(&queue));
}
printf("----- print -----\n");
queue.print(&queue);
printf("\n");
queue.clear(&queue);
if (queue.empty(&queue))
{
printf("----- empty -----\n");
}
printf("----- push -----\n");
for (i = 0; i < len; i++)
{
queue.push(&queue, &data[i]);
}
printf("----- after pop -----\n");
for (i = 0; i < len + 1; i++)
{
if (true == queue.pop(&queue, &temp))
{
printf("pop = ");
queue.print_obj(&temp);
if (true == queue.front(&queue, &temp))
{
printf("front = ");
queue.print_obj(&temp);
}
if (queue.back(&queue, &temp))
{
printf("back = ");
queue.print_obj(&temp);
}
printf("size = %2d\n", queue.size(&queue));
}
else
{
printf("pop failed! because it is empty\n");
}
if (queue.empty(&queue))
{
printf("----- empty -----\n");
}
}
printf("----- print -----\n");
queue.print(&queue);
printf("\n");
queue.destory(&queue);
}
void queue_test(void) void queue_test(void)
{ {
queue_test_num();
} }
#endif #endif

View File

@ -54,7 +54,7 @@ static void stack_test_num(void)
} }
else else
{ {
printf("pop failed! because stack is empty\n"); printf("pop failed! because it is empty\n");
} }
if (s.empty(&s)) if (s.empty(&s))
@ -119,7 +119,7 @@ static void stack_test_char(void)
} }
else else
{ {
printf("pop failed! because stack is empty\n"); printf("pop failed! because it is empty\n");
} }
if (s.empty(&s)) if (s.empty(&s))
@ -207,7 +207,7 @@ static void stack_test_struct(void)
} }
else else
{ {
printf("pop failed! because stack is empty\n"); printf("pop failed! because it is empty\n");
} }
if (s.empty(&s)) if (s.empty(&s))