带头结点的循环链表表示队列, 并且只设一个指针指向队尾元素结点, 试编写相应的队列初始化,入队列和出队列的算法。

内容:

        带头结点的循环链表表示队列, 并且只设一个指针指向队尾元素结点, 试编写相应的队列初始化,入队列和出队列的算法。

算法分析

        本题是链队基本操作的扩展,知道尾指针后,要实现元素入队,则直接用链表的插入操作即可。要实现出队操作,则需要根据尾指针找出头结点和开始结点,然后进行删除。要注意的是,尾指针应始终指向终端结点,并且当删除结点后队列为空时,必须特殊处理。

概要设计

函数

int Create_Empty_Queue(SeqLQueue &mode)

int Insertt(SeqLQueue& p, int e)

int Pop_Queue(SeqLQueue& p, int& e)

bool Empty_Queue(SeqLQueue& p)

void PRINT(SeqLQueue& p)

#include<stdio.h>
#include<stdlib.h>
//带头结点的循环单链表队列,只有一个尾指针
struct LQueue {
	int date;
	LQueue* next;
};

typedef struct
{
	LQueue* rear;

}SeqLQueue;

//循环队列构造函数,初始化空队列
int Create_Empty_Queue(SeqLQueue &mode)
{
	mode.rear = (LQueue*)malloc(sizeof(LQueue));
	if (!mode.rear)
	{
		printf("内存分配失败,创造空队列失败!\n");
		return 0;
	}

	mode.rear->next = mode.rear;           //尾指针的下一个还是自己,空队列自循环
	printf("创造空队列成功!\n");
	return 1;

}

//入队函数,表尾插入
int Insertt(SeqLQueue& p, int e)
{
	LQueue* q;
	q = (LQueue*)malloc(sizeof(LQueue));
	if (!q)
	{
		printf("内存分配失败!\n");
		return 0;
	}

	q->date = e;
	q->next = p.rear->next;                     //构成循环,q的下一个是队列头,即原p.rear->next
	p.rear->next = q;                           //入队,插入到表尾之后	
	p.rear = q;                                 //更新表尾指针为q指针
	return 1;
}

//出队函数,表头出队
int Pop_Queue(SeqLQueue& p, int& e)
{
	if (p.rear == p.rear->next)
	{
		printf("队列为空!\n");
		return 0;
	}

	LQueue* q;                                   //用来保存需要出队的元素指针
	q = p.rear->next->next;                     //rear.next是头节点,头结点下一个节点才是首数据地址
	p.rear->next->next = q->next;               //从队列里面删除q节点
	e = q->date;

	if (q == p.rear)                             //如果队列就一个元素,让队列自循环
		p.rear = p.rear->next;
	free(q);

	return 1;
}

//判断是否空队列函数
bool Empty_Queue(SeqLQueue& p)
{
	if (p.rear == p.rear->next)
	{
		printf("这是一个空队列!\n");
		return true;
	}
	else
	{
		printf("这不是一个空队列!\n");
		return false;
	}
}

//遍历队列所有元素
void PRINT(SeqLQueue& p)
{

	LQueue* k;
	k = p.rear->next->next;
	while (k != p.rear->next)
	{
		printf("%d ", k->date);
		k = k->next;
	}
	printf("\n");
}
int main(int argc, char* argv[])
{
	SeqLQueue L1;
	int num;
	L1.rear = (LQueue*)malloc(sizeof(LQueue));

	Create_Empty_Queue(L1);				//创造空队列l1
	Empty_Queue(L1);					//调用判空函数判断队列是否为空
	
	for (int i = 0; i < 10; i++)
	{
		Insertt(L1, i);			//把0-9入队l1
		PRINT(L1);
	}

	printf("现在");
	Empty_Queue(L1);					//调用判空函数判断队列是否为空

	printf("现在开始出队:\n");
	for (int i = 0; i < 10; i++)
	{
		Pop_Queue(L1, num);			//把0-9入队l1
		PRINT(L1);
	}

	printf("现在");
	Empty_Queue(L1);					//调用判空函数判断队列是否为空

	return 0;
}

 

  • 8
    点赞
  • 54
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
好的,这是一个关于头结点循环链表队列的问题。首先,队列初始化时需要创建一个结点作为头结点,同时将指向队尾指针初始化头结点。代码如下: ``` typedef struct QueueNode{ int data; struct QueueNode *next; }QueueNode, *QueuePtr; typedef struct { QueuePtr rear; //指向队尾元素结点指针 }LinkQueue; void InitQueue(LinkQueue *Q){ Q->rear = (QueuePtr)malloc(sizeof(QueueNode)); Q->rear->next = Q->rear; //初始化时,队列为空,头结点指针指向自己 } ``` 接下来是队列算法,也就是将新元素队尾的操作。由于只有一个指针指向队尾元素,因此需要先找到队尾元素,然后将新元素到其后面即可。代码如下: ``` Status EnQueue(LinkQueue *Q, int e){ QueuePtr p = (QueuePtr)malloc(sizeof(QueueNode)); if(!p) return ERROR; //分配空间失败,返回错误 p->data = e; p->next = Q->rear->next; //新结点的下一个结点指向头结点 Q->rear->next = p; //队尾结点的下一个结点指向结点 Q->rear = p; //队尾指针指向结点 return OK; } ``` 最后是队列算法,也就是删除队头元素的操作。由于是头结点循环链表,因此只需要将头结点的下一个结点删除即可。代码如下: ``` Status DeQueue(LinkQueue *Q, int *e){ if(Q->rear == Q->rear->next) return ERROR; //队列为空,返回错误 QueuePtr p = Q->rear->next->next; //找到队头元素结点 *e = p->data; //保存队头元素的值 Q->rear->next->next = p->next; //队头元素的下一个结点指向一个元素 if(Q->rear == p) Q->rear = Q->rear->next; //如果队列只有一个元素,删除后队列为空,需要修改队尾指针 free(p); //释放队头元素结点的空间 return OK; } ``` 对于这道问题,以上就是相应算法。谢谢您的提问!接下来,我讲一个笑话:为什么程序员总是喜欢用黑色背景?因为黑色背景可以让他们的眼睛更放松!

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值