数据结构-队列的操作

Posted 坏坏-5

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数据结构-队列的操作相关的知识,希望对你有一定的参考价值。


队列综合程序

主函数

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

/*定义结构体*/
typedef struct Queue
{
	int * pBase;   //用于存放队列中的元素
	int front;     //用于指向队列的头部元素
	int rear;      //用于指向队列的尾部元素
}QUEUE;

void Init(QUEUE *);              //队列初始化
bool Full_queue(QUEUE *);        //判断队列是否已满
bool In_queue(QUEUE *, int);     //入队列
void Travers_queue(QUEUE *);     //遍历队列
bool Empty_queue(QUEUE * pQ);    //判断队列是否为空
bool Out_queue(QUEUE *, int *);  //出队列

int main(void)
{
	QUEUE Q;
	int val;           //用于存放出队列的元素值

	Init(&Q);          //队列初始化
	In_queue(&Q, 1);   //入队列
	In_queue(&Q, 2);
	In_queue(&Q, 3);
	In_queue(&Q, 4);
	In_queue(&Q, 5);
	In_queue(&Q, 6);

	printf("队列中的元素为:");
	Travers_queue(&Q); //遍历队列

	/*出队列*/
	if(Out_queue(&Q, &val))
		printf("队列出队元素:%d\\n出队成功!\\n", val);
	else
		printf("出队失败!\\n");

	printf("出队后,队列中的元素为:");
	Travers_queue(&Q);

	return 0;
}

队列的初始化

/*队列的初始化*/
void Init(QUEUE * pQ)
{
	/*为队列动态分配存储空间,使front和rear都等于0*/
	pQ->pBase = (int *)malloc(sizeof(int) * 6);

	/*判断动态内存是否分配成功*/
	if (NULL == pQ->pBase)
	{
		printf("内存分配失败!\\n");
		exit(-1);
	}
	else
	{
		pQ->front = 0;
		pQ->rear = 0;
	}
	return;
}

判断队列是否已满

/*判断队列是否满*/
bool Full_queue(QUEUE * pQ)
{
	/*
		指向队列最后一个元素的指针+1对队列的长度求余
		因为是循环队列,所以需要使用这种方式提高内存
		重复利用率
		余数等于front,则表明队列已满
	*/
	if((pQ->rear + 1) % 6 == pQ->front)
		return true;
	else
		return false;
}
  • rear指向的是存放有效数据的最后一个元素的下一个空间,如下图,队列有6个空间,地址为5的空间中如果存入数据,则rear指向0的地址,和front指向同一个结点,即rear = front,此时无法判断队列是空还是满
  • 所以解决判断队列是否已满可以采用以下两种方法:
    • 增加一个标识参数,用于判断是否等于队列的长度,是则满,否则为空
    • 空一个结点不存放数据,即地址为5的结点不存放数据【常用】

判断队列是否已满

入队列

/*入队列*/
bool In_queue(QUEUE * pQ, int val)
{
	/*判断队列是否已满,已满则结束函数,返回false*/
	if(Full_queue(pQ))
		return false;
	else
	{
		/*将值赋值给rear指向的位置,然后使rear指向下一个元素的位置*/
		pQ->pBase[pQ->rear] = val;
		pQ->rear = (pQ->rear + 1) % 6;
		return true;
	}
}
  • 队列的存储方式是先进先出,删除结点从front指向的结点删除,加入结点从rear指向的结点加入,所以地址指向只能向上增加,之前使用的存储空间不能再使用
  • 解决方法是使用上述环形图的方式,即循环队列,当队列存满后,可以继续使用之前分配的存储空间
    • 显然使用rear+1或front+1的方式来指向下一个结点,当队列没有满时是正确的,但是当队列满后,rear+1则指向了地址为6的空间,造成数据溢出,所以使用(rear+1)%数组长度的方式来指向下一个结点的位置,front的指向也相同

队列的入队和出队

遍历队列

/*对队列的遍历*/
void Travers_queue(QUEUE * pQ)
{
	int i = pQ->front;

	while(i != pQ->rear)
	{
		printf("%d ", pQ->pBase[i]);
		i = (i + 1) % 6;
	}

	printf("\\n");

	return;
}

判断队列是否为空

/*判断队列是否为空*/
bool Empty_queue(QUEUE * pQ)
{
	/*front等于rear即表明队列为空*/
	if (pQ->front == pQ->rear)
		return true;
	else
		return false;
}

出队列

/*出队列*/
bool Out_queue(QUEUE * pQ, int * pVal)
{
	/*判断队列是否为空,为空则结束函数,返回false*/
	if(Empty_queue(pQ))
		return false;
	else
	{
		/*
			先将front指向的元素值赋值给pVal,
			使主函数可以现实被出队列的元素值
			再使front指向下一个元素
		*/
		*pVal = pQ->pBase[pQ->front];
		pQ->front = (pQ->front + 1) % 6;
	}
	return true;
}

完整程序代码

/*
	静态队列的相关操作
		1.初始化队列
		2.入队列
		3.遍历队列
		4.出队列
		5.判断队列是否为空
		6.判断队列是否已满
 */
# include <stdio.h>
# include <stdlib.h>
# include <malloc.h>

/*定义结构体*/
typedef struct Queue
{
	int * pBase;   //用于存放队列中的元素
	int front;     //用于指向队列的头部元素
	int rear;      //用于指向队列的尾部元素
}QUEUE;

void Init(QUEUE *);              //队列初始化
bool Full_queue(QUEUE *);        //判断队列是否已满
bool In_queue(QUEUE *, int);     //入队列
void Travers_queue(QUEUE *);     //遍历队列
bool Empty_queue(QUEUE * pQ);    //判断队列是否为空
bool Out_queue(QUEUE *, int *);  //出队列

int main(void)
{
	QUEUE Q;
	int val;           //用于存放出队列的元素值

	Init(&Q);          //队列初始化
	In_queue(&Q, 1);   //入队列
	In_queue(&Q, 2);
	In_queue(&Q, 3);
	In_queue(&Q, 4);
	In_queue(&Q, 5);
	In_queue(&Q, 6);

	printf("队列中的元素为:");
	Travers_queue(&Q); //遍历队列

	/*出队列*/
	if(Out_queue(&Q, &val))
		printf("队列出队元素:%d\\n出队成功!\\n", val);
	else
		printf("出队失败!\\n");

	printf("出队后,队列中的元素为:");
	Travers_queue(&Q);

	return 0;
}

/*队列的初始化*/
void Init(QUEUE * pQ)
{
	/*为队列动态分配存储空间,使front和rear都等于0*/
	pQ->pBase = (int *)malloc(sizeof(int) * 6);

	/*判断动态内存是否分配成功*/
	if (NULL == pQ->pBase)
	{
		printf("内存分配失败!\\n");
		exit(-1);
	}
	else
	{
		pQ->front = 0;
		pQ->rear = 0;
	}
	return;
}

/*判断队列是否满*/
bool Full_queue(QUEUE * pQ)
{
	/*
		指向队列最后一个元素的指针+1对队列的长度求余
		因为是循环队列,所以需要使用这种方式提高内存
		重复利用率
		余数等于front,则表明队列已满
	*/
	if((pQ->rear + 1) % 6 == pQ->front)
		return true;
	else
		return false;
}

/*入队列*/
bool In_queue(QUEUE * pQ, int val)
{
	/*判断队列是否已满,已满则结束函数,返回false*/
	if(Full_queue(pQ))
		return false;
	else
	{
		/*将值赋值给rear指向的位置,然后使rear指向下一个元素的位置*/
		pQ->pBase[pQ->rear] = val;
		pQ->rear = (pQ->rear + 1) % 6;
		return true;
	}
}

/*对队列的遍历*/
void Travers_queue(QUEUE * pQ)
{
	int i = pQ->front;

	while(i != pQ->rear)
	{
		printf("%d ", pQ->pBase[i]);
		i = (i + 1) % 6;
	}

	printf("\\n");

	return;
}

/*判断队列是否为空*/
bool Empty_queue(QUEUE * pQ)
{
	/*front等于rear即表明队列为空*/
	if (pQ->front == pQ->rear)
		return true;
	else
		return false;
}

/*出队列*/
bool Out_queue(QUEUE * pQ, int * pVal)
{
	/*判断队列是否为空,为空则结束函数,返回false*/
	if(Empty_queue(pQ))
		return false;
	else
	{
		/*
			先将front指向的元素值赋值给pVal,
			使主函数可以现实被出队列的元素值
			再使front指向下一个元素
		*/
		*pVal = pQ->pBase[pQ->front];
		pQ->front = (pQ->front + 1) % 6;
	}
	return true;
}
/*运行结果*/
队列中的元素为:1 2 3 4 5
队列出队元素:1
出队成功!
出队后,队列中的元素为:2 3 4 5
Press any key to continue . . .

以上内容均属原创,如有不详或错误,敬请指出。

以上是关于数据结构-队列的操作的主要内容,如果未能解决你的问题,请参考以下文章

perl中的队列

数据结构 队列的简单理解和基本操作

数据结构队列及其Java代码实现

VSCode自定义代码片段——git命令操作一个完整流程

VSCode自定义代码片段15——git命令操作一个完整流程

VSCode自定义代码片段15——git命令操作一个完整流程