已经重新整理,并且拆分成多文件,阅读更方便

gitee 旧版本源码

gitee 新版面向对象方式重写源码

高仿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)////开辟队列数组空间

测试结果​

完整代码

queue.h(头文件)

queue.c(函数实现)

test.c(测试代码)


内置函数

插入函数

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;
}

Logo

北京人形旗下天工造物具身智能开源社区,聚焦具身天工与慧思开物两大平台

更多推荐