数据结构——队列

195 阅读2分钟

队列的性质

1 只允许在一端进行插入数据操作,另一端进行删除数据操作的特殊线性表.

2 队列的数据遵循先进先出的原则,先入队列的数据先出队列.

3 进行插入操作【入队列】的一端叫队尾,进行删除操作【出队列】的一端叫队头.

image.png

队列的实现

因为数组的头插头删效率较低,所以用链表更优。

队列只需要在头尾进行删除和插入,所以可以考虑用单链表,多增加一个尾指针.

定义队列的节点

typedef int QDataType;
typedef struct QueueNode//定义队列的节点
{
	QDataType data;
	struct QueueNode* next;
}QNode;

定义队列的结构体

用尾指针方便在队尾入数据

typedef struct Queue//定义队列
{
	QNode* phead;//队头
	QNode* tail;//队尾   在队尾入数据,队头出数据
}Queue;

队列的初始化和销毁

void QueueInit(Queue* queue)//队列的初始化
{
	assert(queue);
	queue->phead = queue->tail = NULL;
}

void QueueDestroy(Queue* queue)//队列销毁
{
	assert(queue);
	QNode* cur = queue->phead;//从队列的头指针开始遍历队列的所有节点
	while (cur != NULL)
	{
        //在free掉节点时保留它的下一个节点地址
		QNode* next = cur->next;
		free(cur);
		cur = next;
	}
}

入队列

情况1:队列没有数据,phead和tail都为空,此时入数据,应该把头尾指针都指向新节点

情况2:队列有数据,在tail后面插入节点,最后更新tail.

void QueuePush(Queue* queue, QDataType x)//入队列
{
	assert(queue);
	QNode* newNode = buyQNode(x);
	if (QueueEmpty(queue))//判断队列是否为空的函数
	{
		queue->tail = queue->phead = newNode;
	}
	else
	{
		queue->tail->next = newNode;//尾插节点
		queue->tail = newNode;//更新尾指针
	}
}

出队列

情况1:队列无数据;

情况2:队列只有1个节点,free掉头节点指针后,要同时把tail和phead置空,不然tail就是野指针。

情况3:队列有多个节点,保存phead->next,

free掉头节点后,把头节点指针更新成之前的phead->next.

void QueuePop(Queue* queue)//出队列
{
	assert(queue);
	assert(!QueueEmpty(queue));//队列不为空
	//只有一个节点
	//有多个节点
	if (queue->phead == queue->tail)
	{
		free(queue->phead);
		queue->phead = queue->tail = NULL;
	}
	else
	{
		QNode* newHead = queue->phead->next;
		free(queue->phead);
		queue->phead = newHead;
	}
}

取队头或队尾的数据

QDataType QueueFront(Queue* queue)//取队头数据
{
	assert(queue);
	assert(!QueueEmpty(queue));
	return queue->phead->data;
}

QDataType QueueBack(Queue* queue)//取队尾数据
{
	assert(queue);
	assert(!QueueEmpty(queue));
	return queue->tail->data;
}

获取队列的节点数

int QueueSize(Queue* queue)//获取队列的节点数
{
	assert(queue);
	QNode* cur = queue->phead;
	int num = 0;
	while (cur != NULL)
	{
		num++;
		cur = cur->next;
	}
	return num;
}

判断队列是否为空

bool QueueEmpty(Queue* queue)
{
	assert(queue);
	return queue->phead == NULL;//头或尾为空说明队列一定为空
}