队列的链式存储结构


队列的存储结构

队列是只允许在一端进行插入操作,在另一端进行删除操作的线性表,即“先进先出”

typedef struct QNode
{
	int data;
	struct QNode *next;
}QNode,*QueuePtr;
typedef struct
{
	QueuePtr front,rear;
}LinkQue,*LinkQueue;

结点由存放数据元素的数据域和存放放后继结点地址的指针域组成
链队列由指向头结点的front指向队尾的rear组成
同线性表,元素具有相同的类型,相邻元素具有前驱和后继关系。

在这里插入图片描述

对于链栈来说,当队列为空时,front和rear都指向头结点

在这里插入图片描述


一、队列的初始化操作

目的:初始化队列
实现:类比链表创建头结点,让front和rear都指向头结点,初始化一个空队列

void InitQueue(LinkQueue &Q)
{
	Q=(LinkQueue)malloc(sizeof(LinkQue));
	QueuePtr s=(QueuePtr)malloc(sizeof(QNode));
	Q->front=s;
	Q->rear=s;
}

二、队列的相关函数

判断队列是否为空

若队列为空返回true,否则返回false

bool QueueEmpty(LinkQueue Q)
{
	return Q->rear==Q->front;
}

获得队列的长度

创建结点指针s遍历链队列,返回队列长度

int QueueLength(LinkQueue Q)
{
	int len=0;
	QueuePtr s=Q->front;
	while (s->next)
	{
		s=s->next;
		len++;
	}
	return len;
}

三、获得获得队列头元素

功能:输出获得队列头元素
实现:先判断队列是否为空,非空则输出队头(即头结点后的第一个元素的数据)

void GetHead(LinkQueue Q)
{
	if (QueueEmpty(Q))
	{
		cout<<"队列为空!"<<endl;
		return ;
	}
	cout<<"队列头元素是:"<<Q->front->next->data<<endl;
}

四、队列的插入

功能:插入e到队头
实现:①对创建的结点s赋值,使s的next为空
②将s入队,当前队尾的next指向s,并使s成为新的队尾

void EnQueue(LinkQueue Q,int e)
{
	QueuePtr s=(QueuePtr)malloc(sizeof(QNode));
	if(!s) cout<<"error!"<<endl;
	s->data=e;
	s->next=NULL;
	Q->rear->next=s;
	Q->rear=s;
	cout<<"插入数据:"<<e<<"成功!"<<endl;
}
链队列插入数据的方式类似于链表的尾插法

五、队列的删除

功能:删除队列头元素
实现:①判断是否为空,非空则输出队列头元素
②使头结点的next跳过原来的队头,指向新的队头
③释放原来的队头

void DeQueue(LinkQueue Q)
{
	if (QueueEmpty(Q))
	{
		cout<<"队列为空!"<<endl;
		return ;
	}
	QueuePtr p;
	p=Q->front->next;
	int e=p->data;
	Q->front->next=p->next;
	if (Q->rear==p)
	{
		Q->rear=Q->front;
	}
	free(p);
	cout<<"删除数据"<<e<<"成功!"<<endl;
}

还要判断删除的元素是否是队列的最后一个元素,如果是,添加满足空队列的条件front和rear都指向头结点


六、清空队列

功能:将队列清空
实现:只要队列不为空就不断删除队头即可

void ClearQueue(LinkQueue Q)
{
	while (!QueueEmpty(Q))
	{
		DeQueue(Q);
	}
}

七、销毁队列

功能:将队列销毁
实现:清空队列后释放头结点的内存空间,达到彻底销毁的目的

void DestroyQueue(LinkQueue Q)
{
	ClearQueue(Q);
	free(Q);
}

在这里插入图片描述

这里可以看到销毁之后的cr指针指向的内存空间已经被释放,而清空之后的Q仍指向创建的队列内存


总结

本篇介绍了使用链式结构创建队列并进行插入删除元素等操作

测试代码及运行实例

int main()
{
	LinkQueue Q,cr;
	InitQueue(Q);
	InitQueue(cr);
	for (int i = 0; i < 10; i++)
	{
		EnQueue(Q,i+1);
		EnQueue(cr,i+1);
		GetHead(Q);
	}
	cout<<"队列的长度为"<<QueueLength(Q)<<endl;
	for (int i = 0; i < 10; i++)
	{
		DeQueue(Q);
		GetHead(Q);
	}
	ClearQueue(cr);
	GetHead(cr);
	DestroyQueue(cr);
	GetHead(cr);
	return 0;
}

在这里插入图片描述
在这里插入图片描述

  • 2
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
队列链式存储结构实际上就是线性表的单链表,只不过是能尾进头出,简称为链队列。为了操作上的方便,将队头指针指向链队列的头结点,而队尾指针指向终端结点。空队列时,front和rear都指向头结点。链队列的结构可以用以下代码表示: ``` typedef int QElemType; /* QElemType类型根据实际情况而定,这里假设为int */ typedef struct QNode /* 结点结构 */ { QElemType data; struct QNode *next; }QNode,*QueuePtr; typedef struct /* 队列的链表结构 */ { QueuePtr front,rear; /* 队头、队尾指针 */ }LinkQueue; ``` 其中,QNode为队列的结点结构体,QueuePtr为指向QNode的指针类型,LinkQueue为队列的链表结构体,包含队头指针front和队尾指针rear。 队列链式存储结构的入队操作可以用以下代码表示: ``` /* 链式队列的入队操作 */ Status EnQueue(LinkQueue *Q,QElemType e) { QueuePtr s = (QueuePtr)malloc(sizeof(QNode)); if(!s) /* 存储分配失败 */ exit(OVERFLOW); s->data = e; s->next = NULL; Q->rear->next = s; /* 把拥有元素e新结点s赋值给原队尾结点的后继 */ Q->rear = s; /* 把当前的s设置为队尾结点,rear指向s */ return OK; } ``` 其中,EnQueue为入队操作函数,Q为链队列指针,e为要入队的元素。该函数首先创建一个新结点s,将要入队的元素e赋值给s的data域,将s的next指针置为NULL。然后将s赋值给原队尾结点的后继,将rear指向s,完成入队操作。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

新西兰做的饭

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

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

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

打赏作者

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

抵扣说明:

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

余额充值