数据结构--队列

文章目录

文章目录

一、队列是什么?

二、代码实现

1.存储结构

2.常见接口函数

2.1初始化和销毁

2.2 插入和弹出

2.3其他接口

总结


​​​​​​

一、队列是什么?

        队列也是一种线性表,特性为“先进先出”。就像是我们生活中的排队,排队早的人就会早轮到。

数据结构--队列

         队列只能在队头弹出和队尾插入。数据结构--队列


二、代码实现


1.存储结构

        队列的存储可以使用数组或者链表,由于使用数组在队头弹出时要把整个队列往前整,并不方便,因此本文这里选择的以链表的结构来实现这个队列。

        节点设置与链表一样,一个数据域存数据,一个指针域存储下一个节点地址。另外为了尾插方便,定义一个结构体包括了头尾两个指针成员变量。

typedef int QDataType;
typedef struct QueueNode
{
	struct QueueNode* next;
	QDataType data;
}QNode;

typedef struct Queue
{
	QNode* head;
	QNode* tail;
}Queue;


2.常见接口函数

2.1初始化和销毁

        初始化和销毁与链表类似比较简单。销毁时需要注意设置一个next指针记录下一个节点,以免释放当前节点后,找不到下一个节点。

void QueueInit(Queue* q)
{
	assert(q);
	q->head = q->tail = NULL;
}

void QueueDestroy(Queue* q)
{
	assert(q);
	QNode* cur = q->head;
	while (cur)
	{
		QNode* next = cur->next;
		free(cur);
		cur = next;
	}
	q->head = q->tail = NULL;
}

2.2 插入和弹出

        进队就像链表的尾插,但由于多了一个尾指针,所以可以节省找尾操作,直接在尾部插入。同时由于没有头节点,所以当链表为空时,要作为一个特殊情况处理。

        出队只要把释放头指针,再往后移一个节点。但是这里面有个比较坑的就是。但队中只剩一个节点时,继续pop。头指针与尾指针位置相同,头指针free完后,移向节点的next域为空。但这时tail指针仍然指向刚刚释放的节点位置,形成野指针的问题。因此我们可以在头指针为空时,将尾指针也设置为空。

void QueuePush(Queue* q, QDataType data)
{
	assert(q);
	QNode* newNode = (QNode*)malloc(sizeof(QNode));
	if (!newNode)
	{
		printf("malloc fail");
		exit(-1);
	}
	newNode->data = data;
	newNode->next = NULL;
	if (q->head == NULL)
	{
		q->head = q->tail = newNode;
	}
	else
	{
		q->tail->next = newNode;
		q->tail = newNode;
	}
}
// 队头出队列 
void QueuePop(Queue* q)
{
	assert(q);
	assert(!QueueEmpty(q));
	QNode* next = q->head->next;
	free(q->head);
	q->head = next;
	if (q->head == NULL)
	{
		q->tail == NULL;
	}
}

2.3其他接口

        其他的接口就比较简单了,大多一两句代码就可以实现。

// 获取队列头部元素 
QDataType QueueFront(Queue* q)
{
	assert(q);
	assert(!QueueEmpty(q));
	return q->head->data;
}
// 获取队列队尾元素 
QDataType QueueBack(Queue* q)
{
	assert(q);
	assert(!QueueEmpty(q));
	return q->tail->data;
}
// 获取队列中有效元素个数 
int QueueSize(Queue* q)
{
	assert(q);
	int count = 0;
	QNode* cur = q->head;
	while (cur)
	{
		count++;
		cur = cur->next;
	}
	return count;
}
// 检测队列是否为空,如果为空返回非零结果,如果非空返回0 
int QueueEmpty(Queue* q)
{
	assert(q);
	return q->head == NULL;
}


总结

        总体来说,队列的链表实现比较容易。可以在一些特定的场合利用队列“先进先出”的特性。

上一篇:洛谷-P1596 [USACO10OCT]Lake Counting S


下一篇:python之访问限制