拓展 : 环形队列的另一种设计

思考:

我们在上一个队列可以进行插入和删除操作 , 但是我们不能直接得出元素个数 , 我们会联想到队首指针和队尾指针 ,元素个数之间的关系 , 知其二 即可知其一 ,并且我们有了 count(计算元素个数的标志) , 就可以知道什么时候队满了 ,然后当 front 和 rear 重合时 , 我们通过队列中元素个数 , 也能区分出队满和 队空了 , 那我们的最大存储容量就是 MaxSize 了

● 问题

        • 如果知道环形队列队头指针 front 队列中元素个数 count , 则可以计算出队尾指针 . 

        • 存储环形队列时 , 可以记录队列中队头指针front 和队列中元素个数count , 而不记录队尾指针 rear;

 

front , rear , count 三者择其一

   ●已知 front , rear , 求队中元素个数 :

                count = (rear - front+MaxSize)%MaxSize


队尾指针 - 队首指针 算出两者距离 , 即为元素个数 , 逻辑上是正确的,但是我们是循环队列 ,所以当 rear 转了一圈,过了 0 位序 ,但是 front 没过零位序 ,会导致两者为负,原因是 rear 变成 0 ,相当于减去了 MaxSize ,所以加上MaxSize 就可以了

然后,我们又取余的含义是 , 当两者循环了很多次后 , count数值会变超过数组位序, 我们要让其变成实际上的个数

● 已知 front , count ,求 rear ;

        rear = (front + count)%MaxSize


如上图所以 , 队首指针加上元素个数 ,即为rear指向的位序

●已知 rear ,count ,求 front

         front = (rear - count + MaxSize)%MaxSize


同理 ,队尾指针减去 元素个数 加上 MaxSize ,防止负数 ,然后取余即可

下面开始 只记录 队头front 和元素个数 count 的方案

定义结构体 

typedef struct
{
	ElemType data[MaxSize];
	int front;
	int count;
}QuType;

我们的队尾指针可以通过运算得到 , 所以不必定义 

● 环形队列的四要素

        • 队空条件: count = 0;


                count 计算元素个数

        • 队满条件 : count = MaxSize


                有了 count, 我们就不依赖于 front 和 rear 来标志队空和队满了 , 那队存储的最大容量也是数组的容量了, count =                 MaxSize

        • 进队操作   :rear = (rear+1)%MaxSize ;将入队元素 e 放在 rear处(rear 由 front 和 count定)


                当队不满时候 ,就可以入队 ,rear 向后移动一位 , 我们的rear虽然没定义 ,但可以由front 和 count 计算得出

        •出队操作 : front =(front + 1)%MaxSize ; 取出front处元素e ;

                 当队列不空时候 , 就代表队列里面有元素 ,就可以出队 

下面开始代码实现:

●初始化队列运算算法

//传入要创建的队列名称的指针地址
void InitQueue(QueType *&qu)
{
    //为队列结构分配空间
    qu = (QuType *)malloc(sizeof(QuType));
     //队列的队首指针和队尾指针指向 0
    qu -> front = 0;
    qu -> count = 0;
}

● 判断队空的运算算法

//队空运算算法
//传入要判断队列的指针
bool QueueEmpty(QuType *qu)
{
    //空则返回true
	return(qu->count == 0);
}

● 判断队满的运算

//队空运算算法
//传入要判断队列的指针
bool QueueFull(QuType *qu)
{
        //满队则返回 true
        return(qu -> count == MaxSize);
}

● 出队运算算法 

//传入要出队的队列 ,和保存存入元素的变量地址
bool DeQueue(QuType *&qu, ElemType &x)
{
    //先判断是否是空队 ,空队则队下溢,返回错误
    if(qu->count == 0)
    {
        //队空返回错误
        return false;
    }
    else
    {
        //队不空则队首指针向后位移一位,然后传出元素,队列元素个数减一
        qu->front = (qu->front+1)%MaxSize;
        //传出元素
        x = qu->data[qu->front];
        //队列个数减一
        qu->count--;
        //出队成功返回true
        return true;
    }
}

● 进队运算算法

//进队运算算法
//传入要进队的队列 , 和存储进队的元素
{
	//进队要用到rear ,我们之前没有定义,所以这里定义运算一下
	int rear;
	//先判断是否队满
	if(qu->count == MaxSize)
	{
		//满则返回错误
		return false;
	}
	else
	{
		//不满则把尾指针算出 ,然后尾指针后移一位,插入新元素 ,队元素个数加一
		rear = (qu->front+qu->count)%MaxSize;
		//尾指针后移一位
		rear = (rear+1)%MaxSize;
		//插入新元素
		qu->data[rear] = x;
		//队元素个数加一
		qu->count++;
		return true;
	}
}

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值