链式链表实现队列模型(C版本)

队列是一种特殊的线性表,而线性表有顺序和链式存储两种,这里只讨论单向链式链表实现的队列模型,队列遵循的原则是先进先出,因此不管以链表的头部和尾部作为队列的头部,当弹出和压入元素的时候都会设计到队列中元素的移动。这里以链表头部为队列的尾部,以链表的尾部做为队列的头部,即压入元素时采用头插法,弹出元素时采用尾出法。

详细讲解参照https://www.bilibili.com/video/av27904891/?p=1

本次使用工具为vs2017,作者水平有限,若有问题请指出。

队列头文件:Queue_Link_C.h

#pragma once
typedef void _Queue;
typedef void _QueueItem;
typedef struct QueueNode
{
	struct QueueNode *Next;
	_Queue *data;
}QueueNode;

typedef struct Queue
{
	QueueNode QueueHead;
	int QueueLen;
}Queue;

//创建队列
_Queue *CreateQueue();

//往队列里面压入元素
int Push_Item(_Queue *_queue, _QueueItem *_item);

//从队列头部弹出元素
_QueueItem *Pop_Item(_Queue *_queue);

//获取队列头元素
_QueueItem *GetHeadItem(_Queue *_queue);

//获取队列的元素个数
int GetItemNum(_Queue *_queue);

//清空队列
int ClearQueue(_Queue *_queue);

//销毁队列
int DestoryQueue(_Queue **_queue);

队列源文件:Queue_Link_C.cpp

# include"pch.h"
# include"Queue_Link_C.h"
# include<stdio.h>
# include<stdlib.h>

//创建队列
_Queue *CreateQueue()
{
	Queue *queue = (Queue *)malloc(sizeof(Queue));
	if (queue == NULL)
	{
		printf("Malloc Queue Error : CreateQueue() \n");
		return NULL;
	}
	queue->QueueLen = 0;
	queue->QueueHead.data = NULL;
	queue->QueueHead.Next = NULL;
	return (_Queue *)queue;
}

//往队列里面压入元素
int Push_Item(_Queue *_queue, _QueueItem *_item)
{
	int ret = 0;
	if (_queue == NULL || _item == NULL)
	{
		printf("Parameters Error : Push_Item() \n");
		ret = -1;
		return ret;
	}
	//数据转换
	Queue *queue = (Queue *)_queue;
  
	//分配数据节点
	QueueNode *queuenode = (QueueNode *)malloc(sizeof(QueueNode));
	queuenode->data = _item;  //把数据挂在节点上
	queuenode->Next = NULL;   //节点 == NULL
	//这里用头插法
	if (queue->QueueLen == 0) //队列里面没有数据
	{
		queue->QueueHead.Next = queuenode;
		queue->QueueLen++;
	}
	else //队列里面有数据
	{
		queuenode->Next = queue->QueueHead.Next;
		queue->QueueHead.Next = queuenode;
		queue->QueueLen++;
	}
	return ret;
}

//从队列头部弹出元素
_QueueItem *Pop_Item(_Queue *_queue)
{
	if (_queue == NULL)
	{
		printf("Parameters Error : Pop_Item() \n");
		return NULL;
	}
	//数据转换
	Queue *queue = (Queue *)_queue;
	QueueNode *current = queue->QueueHead.Next;   //current指向0号元素
	if (queue->QueueLen == 0)  //队列中没有元素
	{
		printf("Queue is empty,can't pop element : Pop_Item() \n");
		return NULL;
	}
	for (int i=0; i<queue->QueueLen-1; i++)  //循环完了之后current指向最后一个元素
	{
		current = current->Next;
	}
	queue->QueueLen--;
	return current->data;
}

//获取队列头元素
_QueueItem *GetHeadItem(_Queue *_queue)
{
	if (_queue == NULL)
	{
		printf("Parameters Error : GetHeadItem() \n");
		return NULL;
	}
	//数据转换
	Queue *queue = (Queue *)_queue;
	QueueNode *current = queue->QueueHead.Next;   //current指向0号元素
	if (queue->QueueLen == 0)  //队列中没有元素
	{
		printf("Queue is empty,can't get element : GetHeadItem() \n");
		return NULL;
	}
	for (int i = 0; i < queue->QueueLen - 1; i++)  //循环完了之后current指向最后一个元素
	{
		current = current->Next;
	}
	return current->data;
}

//获取队列的元素个数
int GetItemNum(_Queue *_queue)
{
	int ret = 0;
	int stacklen = 0;
	if (_queue == NULL)
	{
		printf("Parameters Error :GetItemNum() \n");
		ret = -1;
		return ret;
	}
	//数据类型转换
	Queue *queue = (Queue *)_queue;
	return queue->QueueLen;
}

//清空队列
int ClearQueue(_Queue *_queue)
{
	//由于节点是自己malloc出来的,必须手动清除掉
	int ret = 0;
	if (_queue == NULL)
	{
		printf("Parameters Error :ClearQueue() \n");
		ret = -1;
		return ret;
	}
	//数据转换
	Queue *queue = (Queue *)_queue;
	QueueNode *current = queue->QueueHead.Next;   //current指向0号元素
	QueueNode *temp = NULL;						  //temp = NULL
	if (queue->QueueLen <= 0)   //队列里面没有元素
	{
		ret = 0;
		return ret;
	}
	else if(queue->QueueLen == 1) //队列里面元素个数只有1个
	{
		if (current != NULL)
		{
			free(current);
		}
		queue->QueueLen = 0;
		queue->QueueHead.data = NULL;
		queue->QueueHead.Next = NULL;
	}
	else  //队列里面元素个数大于1
	{
		for (int i = 0; i < queue->QueueLen - 1; i++)
		{
			if (current != NULL)
			{
				temp = current->Next;
				free(current);
				current = temp;
			}
			queue->QueueLen = 0;
			queue->QueueHead.data = NULL;
			queue->QueueHead.Next = NULL;
		}
	}
	return ret;
}
//销毁队列
int DestoryQueue(_Queue **_queue)
{
	//由于节点是自己malloc出来的,必须手动清除掉
	int ret = 0;
	if (_queue == NULL)
	{
		printf("Parameters Error :ClearQueue() \n");
		ret = -1;
		return ret;
	}
	//数据转换
	Queue **queue = (Queue **)_queue;
	QueueNode *current = (*queue)->QueueHead.Next;   //current指向0号元素
	QueueNode *temp = NULL;						  //temp = NULL
	if ((*queue)->QueueLen <= 0)//队列里面没有元素
	{
		ret = 0;
		(*queue)->QueueLen = 0;
		(*queue)->QueueHead.data = NULL;
		(*queue)->QueueHead.Next = NULL;
	}
	else if ((*queue)->QueueLen == 1)//队列里面元素个数只有1个
	{
		if (current != NULL)
		{
			free(current);
		}
		(*queue)->QueueLen = 0;
		(*queue)->QueueHead.data = NULL;
		(*queue)->QueueHead.Next = NULL;
	}
	else//队列里面元素个数大于1
	{
		for (int i = 0; i < (*queue)->QueueLen - 1; i++)
		{
			if (current != NULL)
			{
				temp = current->Next;
				free(current);
				current = temp;
			}
			(*queue)->QueueLen = 0;
			(*queue)->QueueHead.data = NULL;
			(*queue)->QueueHead.Next = NULL;
		}
	}
	//同一销毁头指针
	*queue = NULL;
	return ret;
}

测试队列功能源文件:Queue_Link_C_Test.cpp

# include"pch.h"
# include"Queue_Link_C.h"
# include<stdio.h>
# include<stdlib.h>
# include"string"

typedef struct person
{
	char name[16];
	int age;
}person;

//测试person类型的数据
void test_person()
{
	person p1, p2, p3, p4, p5, p6, p7, p8;
	strcpy_s(p1.name, sizeof("aaa"), "aaa");
	strcpy_s(p2.name, sizeof("bbb"), "bbb");
	strcpy_s(p3.name, sizeof("ccc"), "ccc");
	strcpy_s(p4.name, sizeof("ddd"), "ddd");
	strcpy_s(p5.name, sizeof("eee"), "eee");
	strcpy_s(p6.name, sizeof("fff"), "fff");
	strcpy_s(p7.name, sizeof("ggg"), "ggg");
	strcpy_s(p8.name, sizeof("hhh"), "hhh");
	p1.age = 81;
	p2.age = 82;
	p3.age = 83;
	p4.age = 84;
	p5.age = 85;
	p6.age = 86;
	p7.age = 87;
	p8.age = 88;

	person *data = NULL;
	int ret = 0;

	void *queue = CreateQueue();
	ret = Push_Item(queue, &(p1));
	ret = Push_Item(queue, &(p2));
	ret = Push_Item(queue, &(p3));
	ret = Push_Item(queue, &(p4));
	ret = Push_Item(queue, &(p5));
	//连续读取和弹出5个元素
	printf("测试 压入,读取,弹出数据\n");
	for (int i = 0; i < 3; i++)  //操作5次
	{
		data = (person*)GetHeadItem(queue);
		if (data != NULL)
		{
			printf("%s    %d \n", data->name ,data->age);
		}
		data = (person *)Pop_Item(queue);
		if (data != NULL)
		{
			printf("%s    %d \n", data->name, data->age);
		}
	}

	//测试清空队列
	printf("\n测试清空队列后, 压入,读取,弹出数据\n");
	ret = ClearQueue(queue);
	if (ret == 0)  //清空成功
	{
		ret = Push_Item(queue, &(p7));
		ret = Push_Item(queue, &(p7));
		for (int i = 0; i < 2; i++)  //操作2次
		{
			data = (person*)GetHeadItem(queue);
			if (data != NULL)
			{
				printf("%s    %d \n", data->name, data->age);
			}
			data = (person *)Pop_Item(queue);
			if (data != NULL)
			{
				printf("%s    %d \n", data->name, data->age);
			}
		}
	}
	//测试销毁队列
	printf("\n测试销毁队列\n");
	ret = Push_Item(queue, &(p7));
	ret = Push_Item(queue, &(p8));
	ret = Push_Item(queue, &(p8));
	DestoryQueue(&queue);
	ret = Push_Item(queue,&p7);
	
}

//测试int类型数据
void test_int()
{
	int a[] = { 1,2,3,4,5,6,7,8,9,10,11 };
	int *data = NULL;
	int ret = 0;

	void *queue = CreateQueue();
	for (int i=0; i<7; i++)  //插入7个元素
	{
		ret = Push_Item(queue,a+i);
		if (ret != 0)
		{
			printf("Push element into queue error : %d \n",i);
			break;
		}
	}
	//连续读取和弹出5个元素
	printf("测试 压入,读取,弹出数据\n");
	for (int i = 0; i < 5; i++)  //操作5次
	{
		data = (int*)GetHeadItem(queue);
		if (data != NULL)
		{
			printf("%d  ",*data);
		}
		data = (int *)Pop_Item(queue);
		if (data != NULL)
		{
			printf("%d  ", *data);
		}
	}
	//测试清空队列
	printf("\n测试清空队列后, 压入,读取,弹出数据\n");
	ret = ClearQueue(queue);
	if (ret == 0)  //清空成功
	{
		for (int i = 0; i < 2; i++)  //插入2个元素
		{
			ret = Push_Item(queue, a +8+i);
			if (ret != 0)
			{
				printf("Push element into queue error : %d \n", i);
				break;
			}
		}
		for (int i = 0; i < 2; i++)  //操作2次
		{
			data = (int *)GetHeadItem(queue);
			if (data != NULL)
			{
				printf("%d  ", *data);
			}
			data = (int *)Pop_Item(queue);
			if (data != NULL)
			{
				printf("%d  ", *data);
			}
		}
	}
	//测试销毁队列
	printf("\n测试销毁队列\n");
	for (int i = 0; i < 3; i++)  //插入3个元素
	{
		ret = Push_Item(queue, a+9);
		if (ret != 0)
		{
			printf("Push element into queue error : %d \n", i);
			break;
		}
	}
	DestoryQueue(&queue);
	ret = Push_Item(queue, a + 9);
}


int main()
{
	test_int();
	test_person();
	system("pause");
	return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值