数据结构 栈与队列 --循环队列

栈和队列 --循环队列



前言

前情提要:之前的文章讲了队列和栈的基本概念 ,今天来讲队列的具体实现

一、队列是什么?

队列的定义
队列定义:队列是只允许在一端进行插入操作,而在另一端进行删除操作的线性表。

在这里插入图片描述

队列是先进先出(first in first out)的数据结构。
既可以头部插入尾部删除,也可以头部删除尾部删除。
队列最好的实现方式为循环链表。
原因:指针指向尾节点则尾节点的next 则为头节点。
典型例子为操作系统中的作业排队。

入队的称为队尾(rear),出队的称为队头(front)。当其中无元素时为空队。

1.2时间复杂度比较

队列
队尾插入 时间复杂度为0(n)
出的时候不挪动数据0(1)
与栈作比较
顺序栈 :入栈时间复杂度0(1)
出栈时间复杂度0(1)
链栈 :入栈时间复杂度0(1)
出栈时间复杂度0(1)

1.3 难题及解决

1.入队和出队的时间复杂度降低为0(1)?
措施 :循环队列

在这里插入图片描述

引发问题 :空 front 0 rear 0 --满 front 0 rear 0

图示方案一 :判断 (rear+1)%size(有效个数)==0;即 用(4+1)%5= =0来判断;
方案二: 多申请一个变量来记录有效节点的个数。能简化代码,便于理解。但实际应用要再行考虑。

————————————————

二、队列的实现

2.1 循环队列结构体实现

代码如下(示例):

#define MAXSIAZE 100
typedef struct Queue
{
   ELEM_TYPE *base;
   int front;//队列不空,队头元素
   int rear;//队列不空,队尾的下一个位置
   
  // int length;// 保存有效长度(可选)
}Queue,PQueue;

2.2 循环队列基本操作

初始化
入队
出队
获取顶部元素
获取有效元素个数
判空
判满
清空
销毁
(没有有效值个数则不存在扩容操作)

代码如下(示例):

void Init_Queue(PQueue pq)
{
  pq->base=(ELEM_TYPE *)malloc(sizeof(ELEM_TYPE)*MAXQSIZE);
  assert(pq->base!=NULL);
  pq->front=0;
  pq->rear =0;
 
}


bool push(PQueue pq ,ELEM_TYPE val);
{ //assert
  if(isfull(pq)) return false;
  pq->base[pq->rear]=val;
  if((rear+1)%MAXQSIZE==0){
  printf("NO ROOM")return false;
  }//没空间了,要覆盖的话可以考虑修改代码
    pq->rear = (pq->rear + 1) % MAXQSIZE;
    return true; // 成功添加元素

}

bool pop(PQueue pq ,ELEM_TYPE *r)
{  
   //assert pq
   if(isempty(pq))
   {return false;}
   *r=pq->base[pq->front];
   pq->front=(pq->front+1)%MAXSIAZE;
   return true;
}
bool top(PQueue pq ,ELEM_TYPE *r){
  //assert pq
   if(isempty(pq))
   {return false;}
   *r=pq->base[pq->front];
   //pq->front=(pq->front+1)%MAXSIAZE; 
   //与pop区别 :不用改指针
   return true;


}
//********重难点理解****************//
int Get_length(PQueue pq)
{ //assert pq
  //判断rear 和 front的大小有点繁琐。
  int length =(pq->rear-pq->front+MAXSIZE)%MAXSIZE;
  // 第一个maxsize  防止负数的影响  
  //第二个maxsize 防止正数的多加
  return length;
}
///
bool isempty(PQueue pq){
    return pq->front==pq->rear;
}

bool isfull(PQueue pq){
return (pq->rear+1)%MAXSIZE ==pq->front;
}
void clear(PQueue pq)
{
   pq->front=pq->rear =0;

}
void Destory(PQueue pq)
{
free(pq->base);
pq->base=NULL;
pq->front=pq->rear=0;
}

循环队列测试用例


void ahow(PQueue pq)
{
  for(int i=pq->front;i!=pq->rear;i=(i+1)%MAXSIZE)
  {printf("%d",pq->base[i]);}
  printf("\n");
}
int main(){
 Queue pq;
 for(int i;i<20;i++)
 {
 Push(&pq,i+1);
 show(&pq);
 }
//后面的根据各位想法 



return 0;
}


总结

为了使队列的时间复杂度降低,臆想其为环型。
但环型带来的判空判满问题也要进行进一步处理,来浪费部分空间做标记。
此外对于有效个数的求解也有十足的理解难度,但胜在简洁。两个maxsize的使用更是比较重要,诸位注意理解。
不足和错误之处诸位多多包涵。 天予不取,反受其咎,与诸君共勉。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值