数据结构之队列

 

在前面我们学习了另一种结构:栈。其特点是,后进先出。对应的,本章我将为大家介绍“队列”,一中先进先出的结构。

 1.队列的概念

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

由于队列的这一特点,所以在对数据进行操作时

在队列的头,取出数据。

在队列的尾,插入数据。

这一特点,在后面我们定义队列结构的时候可以清晰的认识到。

 

从上图,我们可以直观地看到数据如何进出队列。

 2.队列结构的定义

 我们在这里使用链式的结构去实现队列。

原因是,使用链式的结构对数据的删除更加方便,而如果使用数组式结构则会使效率降低。

我们首先确定队列结构中的需要哪些变量。

1.对每一个结点的定义。

2.由于入在队尾,出在队头,所以我们还要有记录队列的对头队尾的变量。

具体代码如下。 


typedef int QueueDatatype;
typedef struct QueueNode
{
	struct QueueNode* next;//指向下一个结点
	QueueDatatype data;//结点存储的数据
}QN;

typedef struct Queue
{
	QueueNode* phead;//记录队列的头
	QueueNode* ptail;//记录队列的尾
}Queue;

我们可以看到,在定义记录队列头和尾的结构体中,phead和ptail都是QueueNode类型,所以实际上这是一个套娃的结构。 每一个结点中都包含data和指向下一个结点的next。

 

3.数据的插入

 从前面的介绍中我们可以知道,队列数据的插入从尾插入。

在进行队列插入前要首先申请空间,我们直接上代码。

void QueueInsert(Queue* pq, QueueDatatype x)
{
	assert(pq);//先判断指针是否为空
	QN* newnode = (QN*)malloc(sizeof(QN));//开辟节点
	newnode->data = x;//定义结点内部
	newnode->next = NULL;
	if (pq->phead == NULL)
	{
		pq->phead =pq->ptail= newnode;//队列为空,则首尾都为开辟的结点
	}
	else
	{
		pq->ptail->next = newnode;//尾插,用尾去链接
		pq->ptail = newnode;//将newnode定义为尾
	}
}

和链表一样,数据的插入前需要队指针进行判空,插入情况分为两种:1.队列为空  2.队列不为空。 

 4.数据的删除

 

void QueuePop(Queue* pq)
{
	assert(pq);
	assert(pq->phead);//如果phead为空则无法进删除操作,所以需要判空
	if (pq->phead->next == NULL)//如果phead->next为空,则不需要关心链接问题,直接删除
	{
		free(pq->phead);
    }
	else
	{
		QN* cur = pq->phead->next;//有多个结点则需要先找phead-> next再free,否则没有新头
		free(pq->phead);//释放旧的头结点
		pq->phead = cur;//将原来保存的phead->next作为新头
	}
}

在对队列数据进行删除操作时,要注意到队列中是多个结点还是只有一个结点,分情况处理。 

5.取出队列中首尾元素 

QueueDatatype QueueBack(Queue* pq)//取队列尾元素
{
	assert(pq);
	assert(pq->phead);//防止队列为空

	return pq->ptail->data;
}
7
QueueDatatype QueueFront(Queue* pq)//取队列首元素
{
	assert(pq);
	assert(pq->phead);
	
	return pq->phead->data;
}

6.队列判空

判空最基础的操作我们就直接上代码了。

bool QueueEmpty(Queue* pq)
{
	assert(pq);
	if (pq->phead == NULL)
	{
		return true;
	}
	else
	{
		return false;
	}
}

7.打印队列 

进行完以上操作,还是要看看我们创建的队列,我们看看如打印。

void QueuePrint(Queue* pq)
{
	assert(pq);
	assert(pq->phead);
	QN* cur = pq->phead;//替换首结点,保证首不动
	while (cur)
	{
		printf("%d ", cur->data);
		cur = cur->next;
	}
}

是不是很熟悉的代码呢,只要是链式的,大家一定要记住首结点不要移动!!! 

8.总结

在队列这一部分我们可以看到很多链表的影子,如果大家对队列疑问较多,可以先学习链表。

此外,队列元素先进先出,栈元素后进先出!!!一定不要混淆哦! 

 

  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值