郝斌数据结构入门---P35---队列(循环队列)

郝斌数据结构入门---P35---队列

 

线性结构的常见应用之一:队列(头部删除,尾部插入)

定义:一种可以实现“ 先进先出 ”的存储结构,队列类似于排队去买票(一端入,一端出)

分类:链式队列(用链表实现),静态队列(用数组实现),静态队列通常都必须是循环队列。 

循环队列: (循环队列的好处:可以重复使用已经废弃的内存!!)

1、静态队列为什么必须是循环队列(f:front前,r:rear后)

r永远指向当前队列的最后一个元素的下一个位置!!!!!

f永远指向第一个元素!!!

如果f指向第一个元素,r指向最后一个元素的下一个元素。

如果f指向第一个元素的前一个元素,r就指向最后一个元素。

它们两个是错开的。

如果是增加元素(入队),r增加。如果是删除元素(出队),f增加。

 

上面是传统的数组实现队列。(只能用一次)

下面是循环队列:(可以多次使用)

初始状态:只有“c”这个元素

增加:增加一个为“中”的元素,现在队列的元素有“c”和“中”:(r增加一个位置,因为循环,到对头部)

删除:现在要删除一个元素,删除了“c”元素,剩下“中”元素(f增加一个位置)

增加:要增加一个为“国”元素,现在队列的元素中有“中”和“国”两个元素(r增加一个位置)

删除:现在要删除一个元素,删除了“中”元素,剩下“国”元素(f增加一个位置,因为循环,到对头部)

 

2、循环队列需要几个参数来确定

需要2个参数来确定

 

3、循环队列各个参数的含义

front:指向第一个元素(队列头)

rear:最后一个的下一个元素(队列尾的下一个)

2个参数在不同场合有不同的含义:

队列初始化:front和rear的值都是零

队列非空:front代表的是队列的第一个元素,rear代表的是队列的最后一个有效元素的下一个元素

队列空:front和rear的值相等,但不一定是零

 

4、循环队列入队伪算法讲解(注意判断r的位置)

第一步:先把将入队的值存入到r所代表的位置

第二步:错误的写法:    r=r+1;

                正确的写法是:r=(r+1) % 数组的长度

 

5、循环队列出队伪算法讲解

一步搞定:f=(f+1) % 数组的长度

 

6、如何判断循环队列是否为空

如果 front 和 rear的值相等,则该队列就一定为空

 

7、如何判断循环队列是否已满

预备知识:

front的值可能比rear大,front的值也可能比rear小,当然也可能两者相等

两种方式:

1、多增加一个标识参数

2、少用一个元素(n-1)【通常使用第二种方式】

如果 r 和 f 的值紧挨着,则队列已满。

用C语言伪算法表示就是:

if ( (r+1)%数组长度 == f )

        已满

else

        不满

 

求链表的长度:

 

 

循环队列的源代码:

关键是取余符号%的理解,相当于走了一圈,然后再回到开始位置,再循环。

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

typedef struct Queue
{
	int *pBase;//数组
	int front;//前 
	int rear;//后 
}QUEUE;

void init(QUEUE *);
int en_queue(QUEUE *, int val);//入队 
void traverse_queue(QUEUE *);//遍历 
int full_queue(QUEUE *);//判断队列是否满了 
int out_queue(QUEUE *, int *);//出队,并且保存出队元素 
int empty_queue(QUEUE *);//判断队列是否空的 

int main(void)
{
	QUEUE Q;
	int val;
	
	init(&Q);
	
	en_queue(&Q, 1);
	en_queue(&Q, 2);
	en_queue(&Q, 3);
	en_queue(&Q, 4);
	en_queue(&Q, 5);
	en_queue(&Q, 6);
	en_queue(&Q, 7);
	en_queue(&Q, 8);
	
	traverse_queue(&Q);
	
	if (out_queue(&Q, &val))
	{
		printf("出队成功,队列出队的元素是:%d\n", val);
	}
	else
	{
		printf("出队失败!\n");
	}
	
	traverse_queue(&Q);
	
	return 0;
}

void init(QUEUE *pQ)
{
	pQ->pBase = (int *)malloc(sizeof(int) * 6);//数组
	pQ->front = 0;
	pQ->rear = 0;
}

int full_queue(QUEUE *pQ)//判断队列是否满了
{
	if ((pQ->rear + 1) % 6 == pQ->front)
		return 1;
	else
		return 0;
}

int en_queue(QUEUE *pQ, int val)//入队 
{
	if (full_queue(pQ))
	{
		return 0;
	}
	else
	{
		//先把值放入rear位置,然后再往后移动一个 
		pQ->pBase[pQ->rear] = val;
		pQ->rear = (pQ->rear+1) % 6;
		return 1;
	}
}

void traverse_queue(QUEUE *pQ)//头部遍历 
{
	int i = pQ->front;
	
	while (i != pQ->rear)
	{
		printf("%d ", pQ->pBase[i]);
		i = (i+1) % 6;
	}
	printf("\n");
	
	return ;
}

int empty_queue(QUEUE *pQ)
{
	if (pQ->front == pQ->rear)
		return 1;
	else
		return 0;
}

int out_queue(QUEUE *pQ, int *pVal)//出队,并且保存出队元素 
{
	if (empty_queue(pQ))
	{
		return false;
	}
	else
	{
		//先保存数据,然后再向后移动一个位置 
		*pVal = pQ->pBase[pQ->front];
		pQ->front = (pQ->front+1) %6;
		
		return 1;
	}
}

 

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值