c语言实现任何数据类型的queue(队列)(动态数组,链表)
·
已经重新整理,并且拆分成多文件,阅读更方便
高仿C++STL-queue为了实现所有数据类型,本身是无类型的,采用内存拷贝实现。
内置函数获取的数据都是以void指针的形式返回,需要强转成自己使用的类型。
代码内同时写了数组和链表两种实现方式,通过queue.h修改其中的宏参数PATT 编译不同的版本
目录
void Queue_Push(queue* que, void* x);//插入到队列的队尾
void Queue_pop(struct queue* que);//删除queue的队头元素
void Queue_clear(struct queue* que);//清空queue的队列,释放内存void*
Queue_front(struct queue* que);// 返回队列的队头元素指针,但不删除该元素
void* Queue_back(struct queue* que);// 返回队列的队尾元素指针,但不删除该元素
bool Queue_empty(struct queue* que);//当队列为空时返回true,否则返回false
int Queue_size(struct queue* que);//返回队列中元素的个数
void QueueINIT(struct queue* que, int n);//queue容器初始化函数
static void open(queue* que)////开辟队列数组空间
内置函数
插入函数
void Queue_Push(queue* que, void* x);//插入到队列的队尾
void Queue_Push(QUEUE* que,void* x)//插入到队列的队尾
{
#if PATT==ARRAY
open(que);
char* str1 = (char*)que->_date + que->_type * que->_current;
memcpy(str1,x, que->_type);
#elif PATT LIST
List* p = open(que);
memcpy(p->date, x, que->_type);
#endif
que->_current++;
}
删除函数
void Queue_pop(struct queue* que);//删除queue的队头元素
void Queue_pop(struct QUEUE* que)//删除queue的队头元素
{
if (que->_current > 1)
{
#if PATT==ARRAY
char* str1 = (char*)que->_date;
char* str2 = (char*)que->_date + que->_type *1;
for (size_t i = 0; i <que->_current-1 ; i++)
{
memcpy(str1, str2, que->_type);
str1 += que->_type;
str2 += que->_type;
}
#elif PATT LIST
List* head = que->_date;
List* next = head->next;
free(head->date);
free(head);
que->_date = next;
#endif
que->_current--;
}
else if (que->_current ==1)
{
#if PATT LIST
List* head = que->_date;
free(head->date);
free(head);
que->_date = NULL;
#endif
que->_current--;
}
}
void Queue_clear(struct queue* que);//清空queue的队列,释放内存void*
void Queue_clear(QUEUE* que)//清空queue的队列,释放内存
{
if (que->_date != NULL && que->_size != 0)//无元素
{
#if PATT==ARRAY
free(que->_date);
#elif PATT LIST
List* p = que->_date;//开始指向头节点
List* pnext = NULL;
for (size_t i = 0; i < que->_size; i++)
{
pnext = p->next;//临时保存下一个节点地址
free(p->date);//释放节点的数据空间
free(p);//释放节点
p = pnext;//p指向下一个节点
}
#endif
que->_date = NULL;
que->_current = 0;
que->_size = 0;
}
}
遍历函数
Queue_front(struct queue* que);// 返回队列的队头元素指针,但不删除该元素
void* Queue_front(struct QUEUE* que)// 返回队列的队头元素指针,但不删除该元素
{
#if PATT==ARRAY
return que->_date;
#elif PATT LIST
return ((List*)que->_date)->date;
#endif
}
void* Queue_back(struct queue* que);// 返回队列的队尾元素指针,但不删除该元素
void* Queue_back(struct QUEUE* que)// 返回队列的队尾元素指针,但不删除该元素
{
#if PATT==ARRAY
char* _date = (char*)que->_date + que->_type * (que->_current - 1);
return _date;
#elif PATT LIST
return ((List*)que->_date)->prev->date;
#endif
}
判断函数
bool Queue_empty(struct queue* que);//当队列为空时返回true,否则返回false
bool Queue_empty(struct queue* que)//检测队内是否为空,空为真 O(1)
{
return !que->_current;
}
大小函数
int Queue_size(struct queue* que);//返回队列中元素的个数
int Queue_size(struct queue* que)//返回queue内元素的个数 O(1)
{
return que->_current;
}
初始化函数
void QueueINIT(struct queue* que, int n);//queue容器初始化函数
queue* NewQueue(int sizen)
{
QUEUE* que = malloc(sizeof(QUEUE));
que->clear = Queue_clear;//清空queue的队列,释放内存
que->push = Queue_Push;//插入到队列的队尾
que->pop = Queue_pop;//删除queue的队头元素
que->front = Queue_front;//返回队列的队头元素指针,但不删除该元素
que->back = Queue_back; //返回队列的队尾元素指针,但不删除该元素
que->empty = Queue_empty;//当队列为空时返回true,否则返回false
que->size = Queue_size;////返回队列中元素的个数
que->_type = sizen;
que->_size = 0;
que->_date = NULL;
que->_current = 0;
return que;
}
非公开函数
static void open(queue* que)////开辟队列数组空间
static void open(queue* que)
{
que->_date = malloc(que->_type * VECTORNUM);
if (que->_date == NULL)
{
perror("初始化queue失败");
exit(-1);
}
else
{
que->_size = VECTORNUM;
}
}
测试结果
完整代码
queue.h(头文件)
#pragma once
#define _CRT_SECURE_NO_DEPRECATE 1
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<stdbool.h>
#define ARRAY 0 //数组
#define LIST 1 //链表
#define PATT LIST//实现方式
typedef struct queue
{
void (*clear) (struct queue*);//清空queue的队列,释放内存
void(*push)(struct queue*, void*);//插入到队列的队尾
void (*pop)(struct queue*);//删除queue的队头元素
void* (*front)(struct queue*);// 返回队列的队头元素指针,但不删除该元素
void* (*back)(struct queue*);// 返回队列的队尾元素指针,但不删除该元素
bool (*empty)(struct queue*);// 当队列为空时返回true,否则返回false
int (*size)(struct queue*);//返回队列中元素的个数
}queue;
void Queue_clear(struct queue* que);//清空queue的队列,释放内存
void Queue_Push(queue* que, void* x);//插入到队列的队尾
void Queue_pop(struct queue* que);//删除queue的队头元素
void* Queue_front(struct queue* que);// 返回队列的队头元素指针,但不删除该元素
void* Queue_back(struct queue* que);// 返回队列的队尾元素指针,但不删除该元素
bool Queue_empty(struct queue* que);//当队列为空时返回true,否则返回false
int Queue_size(struct queue* que);//返回队列中元素的个数
//queue容器初始化函数
queue* NewQueue(int sizen);
queue.c(函数实现)
#include"queue.h"
typedef struct QUEUE
{
void (*clear) (struct QUEUE*);//清空queue的队列,释放内存
void(*push)(struct QUEUE*, void*);//插入到队列的队尾
void (*pop)(struct QUEUE*);//删除queue的队头元素
void* (*front)(struct QUEUE*);// 返回队列的队头元素指针,但不删除该元素
void* (*back)(struct QUEUE*);// 返回队列的队尾元素指针,但不删除该元素
bool (*empty)(struct QUEUE*);// 当队列为空时返回true,否则返回false
int (*size)(struct QUEUE*);//返回队列中元素的个数
void* _date;//指向自定义数组类型
int _current;//当前元素个数
int _size;//元素最大个数
int _type;//类型占用字节数
}QUEUE;
#if PATT==ARRAY
#define VECTORNUM 4//初始数组大小
#elif PATT==LIST
static struct List
{
void* date;
struct List* prev;//指向上一个
struct List* next;//指向下一个
};
typedef struct List List;
#endif // PATT==LIST
#if PATT==ARRAY
//开辟队列数组
static void open(QUEUE* que)
{
if (que->_date == NULL && que->_size == 0)//无元素
{
que->_date = malloc(que->_type * VECTORNUM);
if (que->_date == NULL)
{
perror("初始化queue失败");
exit(-1);
}
else
{
que->_size = VECTORNUM;
}
}
else if (que->_size == que->_current)//空间已满需要扩容
{
void* _date = realloc(que->_date, que->_size * que->_type * 2);
if (_date == NULL)
{
perror("扩容失败queue");
exit(-1);
}
else
{
que->_date = _date;
que->_size *= 2;
}
}
}
#elif PATT LIST
//开辟新的节点
static List* open(QUEUE* que)
{
List* p = NULL;
if (que->_date == NULL&& que->_size==0)//无元素
{
p = malloc(sizeof(List));//新节点
que->_date = p;
if (que->_date == NULL)
{
perror("初始化queue失败");
exit(-1);
}
else
{
p->next = p;//头节点均指向自己
p->prev = p;
p->date = malloc(que->_type);//为节点数据开辟空间储存
if (p->date == NULL)
printf("开辟数据空间的时候失败\n");
que->_size++;
}
}
else
{
p = malloc(sizeof(List));//新节点
List* head = que->_date;//头节点
List* tail = head->prev;//原尾节点
p->next = head;//新节点下一个指向头节点
p->prev = tail;//新节点上一个指向原尾节点
head->prev = p;//头节点上一个指向新节点
tail->next = p;//原尾节点下一个指向新节点
p->date = malloc(que->_type);//为节点数据开辟空间储存
if (p->date == NULL)
printf("开辟数据空间的时候失败\n");
que->_size++;
}
return p;
}
#endif
void Queue_clear(QUEUE* que)//清空queue的队列,释放内存
{
if (que->_date != NULL && que->_size != 0)//无元素
{
#if PATT==ARRAY
free(que->_date);
#elif PATT LIST
List* p = que->_date;//开始指向头节点
List* pnext = NULL;
for (size_t i = 0; i < que->_size; i++)
{
pnext = p->next;//临时保存下一个节点地址
free(p->date);//释放节点的数据空间
free(p);//释放节点
p = pnext;//p指向下一个节点
}
#endif
que->_date = NULL;
que->_current = 0;
que->_size = 0;
}
}
void Queue_Push(QUEUE* que,void* x)//插入到队列的队尾
{
#if PATT==ARRAY
open(que);
char* str1 = (char*)que->_date + que->_type * que->_current;
memcpy(str1,x, que->_type);
#elif PATT LIST
List* p = open(que);
memcpy(p->date, x, que->_type);
#endif
que->_current++;
}
void Queue_pop(struct QUEUE* que)//删除queue的队头元素
{
if (que->_current > 1)
{
#if PATT==ARRAY
char* str1 = (char*)que->_date;
char* str2 = (char*)que->_date + que->_type *1;
for (size_t i = 0; i <que->_current-1 ; i++)
{
memcpy(str1, str2, que->_type);
str1 += que->_type;
str2 += que->_type;
}
#elif PATT LIST
List* head = que->_date;
List* next = head->next;
free(head->date);
free(head);
que->_date = next;
#endif
que->_current--;
}
else if (que->_current ==1)
{
#if PATT LIST
List* head = que->_date;
free(head->date);
free(head);
que->_date = NULL;
#endif
que->_current--;
}
}
void* Queue_front(struct QUEUE* que)// 返回队列的队头元素指针,但不删除该元素
{
#if PATT==ARRAY
return que->_date;
#elif PATT LIST
return ((List*)que->_date)->date;
#endif
}
void* Queue_back(struct QUEUE* que)// 返回队列的队尾元素指针,但不删除该元素
{
#if PATT==ARRAY
char* _date = (char*)que->_date + que->_type * (que->_current - 1);
return _date;
#elif PATT LIST
return ((List*)que->_date)->prev->date;
#endif
}
bool Queue_empty(struct QUEUE* que)//检测队内是否为空,空为真 O(1)
{
return !que->_current;
}
int Queue_size(struct QUEUE* que)//返回queue内元素的个数 O(1)
{
return que->_current;
}
//初始化函数
queue* NewQueue(int sizen)
{
QUEUE* que = malloc(sizeof(QUEUE));
que->clear = Queue_clear;//清空queue的队列,释放内存
que->push = Queue_Push;//插入到队列的队尾
que->pop = Queue_pop;//删除queue的队头元素
que->front = Queue_front;//返回队列的队头元素指针,但不删除该元素
que->back = Queue_back; //返回队列的队尾元素指针,但不删除该元素
que->empty = Queue_empty;//当队列为空时返回true,否则返回false
que->size = Queue_size;////返回队列中元素的个数
que->_type = sizen;
que->_size = 0;
que->_date = NULL;
que->_current = 0;
return que;
}
test.c(测试代码)
#include"queue.h"
typedef struct user
{
char name [20];
int age;
}user;
void int_test()
{
queue* que=NewQueue(sizeof(int));//创建int类型队列
printf("int类型数据测试\n");
int num[] = {0,100,123,111,123,411};//创建要入队的数据
for (size_t i = 0; i < sizeof(num)/sizeof(num[0]); i++)
{
que->push(que, num+i);//入队
printf("%d\n", num[i]);
}
printf("下面为元素遍历\n");
while (!que->empty(que))
{
int n= *((int*)que->front(que));
printf("%d\n", n);
que->pop(que);
}
que->clear(que);//清空内存释放队列
free(que);
}
int main()
{
int_test();
return 0;
}
更多推荐
所有评论(0)