数据与结构—队列

1、队列的概念

    队列(Queue)是一种常见的数据结构,用于存储按照先进先出(First In First Out,FIFO)原则管理的元素集合。在队列中,新元素被添加到队列的末尾(称为入队),而元素被移除时则从队列的前端移除(称为出队)。这意味着最先入队的元素会最先出队,因此队列类似于排队等候的行为,如在超市排队结账,先来的人先被服务。

    队列通常支持两种基本操作:

  1. 入队(Enqueue):向队列末尾添加一个元素。
  2. 出队(Dequeue):从队列的前端移除一个元素。

除了这两个基本操作之外,队列还可能支持其他操作,如检查队列是否为空、获取队列中的元素数量等。

队列的应用非常广泛,例如在计算机科学中,队列被广泛应用于各种算法和数据结构中,如广度优先搜索(Breadth-First Search, BFS)、作业调度、消息传递等。在现实生活中,队列的概念也被用于模拟各种排队场景,例如排队买票、排队进入公交车等。

2、队列的实现

初始化队列

首先我们需要创建一个结点类型,类型包含了该结点的数据和指向下一结点的指针。

typedef int QDataType;//队列中存储的元素类型(这里用整型举例)

typedef struct QListNode
{
	struct QListNode* next;//指针域
	QDataType data;//数据域
}QListNode;

队列与普通链表又有所不同,普通链表只需要知道链表的头指针,而队列的信息包括了队头和队尾,所以我们需要再创建一个结构体用于存放队列的队头和队尾。

typedef struct Queue
{
	QListNode* head;//队头
	QListNode* tail;//队尾
}Queue;

然后,我们需要一个初始化函数,对刚创建的队列进行初始化。

//初始化队列
void QueueInit(Queue* pq)
{
	assert(pq);
	//起始时队列为空
	pq->head = NULL;
	pq->tail = NULL;
}

销毁队列

队列中的每一个结点所占用的内存空间都是动态开辟的,当我们使用完队列后需要及时释放队列中的每一个结点。

//销毁队列
void QueueDestroy(Queue* pq)
{
	assert(pq);

	QListNode* cur = pq->head;//接收队头
	//遍历链表,逐个释放结点
	while (cur)
	{
		QListNode* next = cur->next;
		free(cur);
		cur = next;
	}
	pq->head = NULL;//队头置空
	pq->tail = NULL;//队尾置空
}

队尾入队列

入队列,即申请一个新结点并将其链接到队尾,然后改变队尾的指针指向即可。需要注意的是:若队列中原本无数据,那么我们只需让队头和队尾均指向这个新申请的结点即可。

//队尾入队列
void QueuePush(Queue* pq, QDataType x)
{
	assert(pq);

	QListNode* newnode = (QListNode*)malloc(sizeof(QListNode));//申请新结点
	if (newnode == NULL)
	{
		printf("malloc fail\n");
		exit(-1);
	}
	newnode->data = x;//新结点赋值
	newnode->next = NULL;//新结点指针域置空
	if (pq->head == NULL)//队列中原本无结点
	{
		pq->head = pq->tail = newnode;//队头、队尾直接指向新结点
	}
	else//队列中原本有结点
	{
		pq->tail->next = newnode;//最后一个结点指向新结点
		pq->tail = newnode;//改变队尾指针指向
	}
}

队头出队列

//队头出队列
void QueuePop(Queue* pq)
{
	assert(pq);
	assert(!QueueEmpty(pq));//检测队列是否为空

	if (pq->head->next == NULL)//队列中只有一个结点
	{
		free(pq->head);
		pq->head = NULL;
		pq->tail = NULL;
	}
	else//队列中有多个结点
	{
		QListNode* next = pq->head->next;
		free(pq->head);
		pq->head = next;//改变队头指针指向
	}
}

获取队列头部元素

获取队列头部元素,即返回队头指针指向的数据即可。

//获取队列头部元素
QDataType QueueFront(Queue* pq)
{
	assert(pq);
	assert(!QueueEmpty(pq));//检测队列是否为空

	return pq->head->data;//返回队头指针指向的数据
}

获取队列尾部元素

获取队列尾部元素,即返回队尾指针指向的数据即可。

//获取队列尾部元素
QDataType QueueBack(Queue* pq)
{
	assert(pq);
	assert(!QueueEmpty(pq));//检测队列是否为空

	return pq->tail->data;//返回队尾指针指向的数据
}

检测队列是否为空

获取队列中有效元素个数检测队列是否为空,即判断队头指针指向的内容是否为空。

//检测队列是否为空
bool QueueEmpty(Queue* pq)
{
	assert(pq);

	return pq->head == NULL;
}

获取队列中有效元素个数

队列中有效元素个数,即队列中的结点个数。我们只需遍历队列,统计队列中的结点数并返回即可。

//获取队列中有效元素个数
int QueueSize(Queue* pq)
{
	assert(pq);

	QListNode* cur = pq->head;//接收队头
	int count = 0;//记录结点个数
	while (cur)//遍历队列
	{
		count++;
		cur = cur->next;
	}
	return count;//返回队列中的结点数
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值