【数据结构】超详细——链队列结构的实现

1、队列的概念及结构

队列:只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表,队列具有先进先出FIFO(First In First Out)排队功能的线性表。

入队列:进行插入操作的一端称为队尾

出队列:进行删除操作的一端称为队头

image-20221119151414974

2、队列的实现

线性表有顺序存储和链式存储,队列也是线性表的一种表现形式。因而,队列也可以数组和链表的结构实现。顺序结构一般采用数组形式,在存储空间内开辟一块大小为n的数组,并将队列的数据存储在素组的前n单元内。数组下标0为队头,下标n-1为队尾。数组的入队列如下图所示:

image-20221126203810108

队列从下标0位置的队头出,则整个队列在数组上都必须整体向前移动,以保障下标0处的队头不为空,此时的时间复杂度为0(n),具体的出队列如下图所示:

image-20221126204610085

队头出队列时,队列需要整体前移,这大大降低了队列的效率。为了增加效率,使用链表的结构实现队列更优一些。队列的链表存储结构,本质上就是线性表的单链表,只不过它只能尾插头删而已,因而称之为链队列。

为了方便代码实现,下图中head指针指向队头结点,tail指针指向队尾结点。

image-20221126211259695

空队列时,headtail都指向头结点,下图所示:

image-20221126213806896

2.1 入队操作

入队列操作就是在链表尾部an处插入新结点,如下图所示:

image-20221126211715277

链队列的入队操作的代码如下:

void QueuePush(Queue* pq, QDataType x)
{
	assert(pq);

	QNode* newnode = (QNode*)malloc(sizeof(QNode));
	if (newnode == NULL)
	{
		perror("malloc fail");
		exit(-1);
	}
	newnode->data = x;
	newnode->next = NULL;
	if (pq->tail == NULL)
	{
		pq->head = pq->tail = newnode;
	}
	else
	{
		pq->tail->next = newnode;
		pq->tail = newnode;
	}
}

2.2 出队操作

出队列就是头结点a1出队(删除),a1的下一个结点作为新的头结点。

image-20221126212338585

链队列的出队列操作的代码如下:

void QueuePop(Queue* pq)
{
	assert(pq);
	assert(!QueueEmpty(pq));
	if (pq->head->next == NULL)
	{
		free(pq->head);
		pq->head = pq->tail = NULL;
	}
	else
	{ 
		QNode* del = pq->head;
		pq->head = pq->head->next;

		free(del);
		del = NULL;
	}
}

2.3 队列是否为空的判定函数

bool QueueEmpty(Queue* pq)
{
	assert(pq);

	return pq->head == NULL && pq->tail == NULL;
}

2.4 取队头数据

QDataType QueueFront(Queue* pq)
{
	assert(pq);
	assert(!QueueEmpty(pq));

	return pq->head->data;
}

2.5 取队尾数据

QDataType QueueBack(Queue* pq)
{
	assert(pq);
	assert(!QueueEmpty(pq));

	return pq->tail->data;
}

2.6 队列大小

int QueueSize(Queue* pq)
{
	assert(pq);

	int size = 0;
	QNode* cur = pq->head;
	while (cur)
	{
		cur = cur->next;
		++size;
	}

	return size;
}

2.7 初始化

void QueueInit(Queue* pq)
{
	assert(pq);

	pq->head = NULL;
	pq->tail = NULL;

}

2.8 队列清空

void QueueDestroy(Queue* pq)
{
	assert(pq);

	QNode* cur = pq->head;
	while (cur)
	{
		QNode* del = cur;
		cur = cur->next;

		free(del);
		del = NULL;
	}

	pq->head = pq->tail = NULL;
}

3、测试

为了检验上面的逻辑及代码的可行性,使用下面代码进行测试,包括了队列初始化、入队列、出队列、打印队列的占用空间(int类型)大小及清空队列(释放链表在对内的空间)。

void QueueTest1()
{
	Queue q;
	QueueInit(&q);
	QueuePush(&q, 10);
	QueuePush(&q, 20);
	QueuePush(&q, 30);
	QueuePush(&q, 40);
	QueuePop(&q);
	int n = QueueSize(&q);
	printf("The number of queue is %d", n);
	QueueDestroy(&q);
}

在队列尾部插入数据后,队列内部的数据下图所示:

image-20221126220021005

队列头部出队列后的队列内部数据具体下图所示:

image-20221126215824242

输出调试函数的相关结果下图所示,此时队列内仅剩3个整型数。

image-20221126215916832
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值