【详细剖析】数据结构-队列(queue)

目录

0.引言

1.定义

2.队列结构模型

3.代码细节实现

3.1节点结构和队列结构

3.2初始化队列

3.3检查队列是否已满/为空

3.4队列的项数

3.5队列中项的添加

3.6队列中项的删除

3.7清空队列

4.测试队列

5.总结


0.引言

队列:顾名思义,具有与日常生活中排队的模式的特点,新排队的人在整个队伍的尾巴加入,然后排在队伍前面的人先买票或者进入目的地(在没有插队的理想情况下)。那么我们就要以这种形式去实现队列的这样一种数据结构。

1.定义

队列是具有两个特殊属性的链表(队列与链表紧密联系)。第一,新项只能添加到链表的末尾。第二,只能从链表的开头移除项。  队列采取的是“先进先出”(first in first out)的模式。

2.队列结构模型

第一种实现方式:既然按照先进先出原则,第一位离开时,所有后面的人全部向前挪动一个单位。

 我们在做可变数组的时候其实也遇到了这个问题:如果数据很大时,复制所花费的时间是很多的,这样的做法很不经济。所以我们将用第二种方法。

第二种方法:直接改变头和尾

 但是我们发现这种情况下,原来结构有八个储存空间,但是改变头之后只剩7个了。内存空间减少了,为了处理这个问题我们就可以把整个储存空间变成环形,便可以充分利用了。

3.代码细节实现

3.1节点结构和队列结构

//节点结构 
typedef struct node
{
	int item;
	struct node *next;
 } Node;


//队列结构 
typedef struct queue
{
	Node *front;
	Node *rear;
	int items;
}Queue;

首先定义出节点的结构用于储存数据和指向下一个节点(和链表中的节点完全一致),然后定义出的队列结构:里面包含了(首端(front),尾端(rear),当前队列的节点个数)

3.2初始化队列

//初始化队列 
void InitializeQueue(Queue *pq)
{
	pq->front=pq->rear=NULL;
	pq->items=0;
}

定义一个队列,传进此函数进行初始化:另front 和 rear都为NULL,并且节点个数为0

3.3检查队列是否已满/为空

//检查队列是否已满 
bool QueueIsFull(const Queue *pq)
{
	return pq->items==MAXQUEUE;
}

//检查队列是否为空 
bool QueueIsEmpty(const Queue *pq)
{
	return pq->items==0;
}

这里MAXQUEUE是你预想定义的最大环形队列节点个数(使用宏定义即可实现)bool函数返回的只有1或者0,用于判断。对于QueueIsFull函数,如果达到最大项数,则返回1(true)。对于QueueIsEmpty函数,如果项数为0,则返回1(true)。

3.4队列的项数

//确定队列中的项数
int QueueItemCount(const Queue *pq)
{
	return pq->items;
 } 

这里采用了函数进行队列项数的封装(一种保护措施)

3.5队列中项的添加

//在队列末尾添加项
void EnQueue(int item,Queue *pq)
{
	Node *pnew;
	pnew=(Node*)malloc(sizeof(Node));
	pnew->item=item;
	pnew->next=NULL;
	if(QueueIsEmpty(pq))
	{
		pq->front=pnew;
	}else{
		pq->rear->next=pnew;
	}
	pq->rear=pnew;
	pq->items++;
	
 }

如果对链表的制作非常熟悉的话,这里其实是跟链表的添加是一样的,整体思路是创造一个新的节点,然后将这个节点给补到结构中去,这里为了满足队列的性质自然只能补在尾巴上了。这里存在一个细节:要先判断队列是不是一开始项数为0,如果一开始是空队列,就让头(pq->front=pnew)

3.6队列中项的删除

//从队列首端删除项
void DeQueue(int *pitem,Queue *pq)
{
	Node *pt;
	*pitem=pq->front->item;
	pt=pq->front;
	pq->front=pq->front->next;
	free(pt);
	pq->items--;
	if(pq->items==0)
	{
		pq->rear=NULL;
	}
 } 

这个函数含有两个参数:一个是在队列中首端的数的指针,一个是队列的指针。里面创造一个新节点pt,目的是让pq->front=pq->front->next之后再free原来的那个pq->front。同时也是让首端的数自动变为新首端的数。这里同样要注意清除之后,队列是否被清空了,如果项数为0,要另尾端为NULL;

3.7清空队列

//清空队列
void EmptyTheQueue(Queue *pq)
{
	int dummy;
	while(!QueueIsEmpty(pq))
	   DeQueue(&dummy,pq);
 } 

一直到队列清空,项数为0时,退出循环。

4.测试队列

输入a:添加项

输入d:删除项

输入p:退出 

#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>


#define MAXQUEUE 10;


//节点结构 
typedef struct node
{
	int item;
	struct node *next;
 } Node;


//队列结构 
typedef struct queue
{
	Node *front;
	Node *rear;
	int items;
}Queue;

//初始化队列 
void InitializeQueue(Queue *pq)
{
	pq->front=pq->rear=NULL;
	pq->items=0;
}

//检查队列是否已满 
bool QueueIsFull(const Queue *pq)
{
	return pq->items==MAXQUEUE;
}

//检查队列是否为空 
bool QueueIsEmpty(const Queue *pq)
{
	return pq->items==0;
}

//确定队列中的项数
int QueueItemCount(const Queue *pq)
{
	return pq->items;
 } 


//在队列末尾添加项
void EnQueue(int item,Queue *pq)
{
	Node *pnew;
	pnew=(Node*)malloc(sizeof(Node));
	pnew->item=item;
	pnew->next=NULL;
	if(QueueIsEmpty(pq))
	{
		pq->front=pnew;
	}else{
		pq->rear->next=pnew;
	}
	pq->rear=pnew;
	pq->items++;
	
 }


//从队列首端删除项
void DeQueue(int *pitem,Queue *pq)
{
	Node *pt;
	*pitem=pq->front->item;
	pt=pq->front;
	pq->front=pq->front->next;
	free(pt);
	pq->items--;
	if(pq->items==0)
	{
		pq->rear=NULL;
	}
 } 
 
//清空队列
void EmptyTheQueue(Queue *pq)
{
	int dummy;
	while(!QueueIsEmpty(pq))
	   DeQueue(&dummy,pq);
 } 


int main(void)
{
	Queue line;
	int temp;
	char ch;
	InitializeQueue(&line);
	puts("Testing the Queue interface.Type a to add a value");
	puts("type d to delete a value,and type q to quit.");
	while((ch=getchar())!='q')
	{
		if(ch!='a'&& ch!='d')
		  continue;
	    if(ch=='a')
	    {
	    	printf("Integer to add: ");
	    	scanf("%d",&temp);
	    	if(!QueueIsFull(&line))
	    	{
	    		printf("Putting %d into queue\n",temp);
	    		EnQueue(temp,&line);
			}else{
				puts("Queue is full!");
			}
		}
		else{
			if (QueueIsEmpty(&line))
			  puts("Nothing to delete!");
			else{
				DeQueue(&temp,&line);
				printf("Removing %d from queue\n",temp);
			}
		}
		printf("%d items in queue\n",QueueItemCount(&line));
		puts("Type a to add,d to delete,q to quit:");
	}
	EmptyTheQueue(&line);
	puts("Bye!");
	
	return 0;
	
}

运行结果:

5.总结

队列其实就是一种特殊的链表,如果能够灵活使用链表,队列自然也就是a piece of cake。

但是队列也具有它独有的特殊性(first in first out)所以在添加删除的时候,需要考虑这种独有的数据结构。 

  • 4
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 7
    评论
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

螺丝工人

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值