队列概念及基础操作(附练习题)

队列的顺序存储

1.队列的定义:队列是一种操作受到限制的线性表,它只允许在队列的一段进行插入操作,而在另一端进行删除操作。(就如同在排队一般,先排队的人员先进行办理业务)---即先进先出。

队列示意图:

2.队列的数据结构定义:

define Maxsize 50

 

typedef struct{

      Elemtype data[Maxsize];  //存放队列元素

      int front,rear;          //队头指针与队尾指针

}SqQueue;

注:当Q.front==Q.rear==0时,表示该队列为空队。

当入队时,队尾指针rear=rear+1;当出队时,队头指针front=front+1。

 问题:当不断地入队与出队后,会产生一个问题:当Q.front==Q.rear==Maxsize时,即便只有一个元素时,也无法再进行入队操作。---即“假溢出”

针对这个问题请看循环队列。

循环队列

定义:虽然称之为循环队列,但实际上所谓的循环只是逻辑上的循环,实际上在存储空间中依旧是顺序队列,与顺序队列所不同的是实际上是循环队列的入队操作与出队操作时,队头指针与队列指针的移动规则不同

入队时:Q.rear=(Q.rear+1)%Maxsize;

出队时:Q.front=(Q.front+1)%Maxsize;

判断队满时条件:(Q.rear+1)%Maxsize==Q.front;

判断队空时条件:Q.front==Q.rear;

循环队列基本操作:初始化;判队空;入队;出队

初始化:

void  initQueue(sqQueue Q){

Q.front=Q.rear=0;

        return Q;

}

判队空:

void IsEmpty(sqQueue Q){

     if(Q.front==Q.rear)

        return true;

     else

        return false;

}

入队:

void EnQueue(sqQueue Q,Elemtype x){

        if((Q.rear+1)%Maxsize==Q.front)    //队列已满,无法再入队
             return false;
        else{
             Q.data[Q.rear]=x;
             Q.rear=(Q.rear+1)%Maxsize;
    }
}

出队:

Void GetQueue(sqQueue Q,Elemtype x){

       if(Q.front==Q.rear)

            return false;

       else{
           x=Q.data[Q.front];
           Q.front=(Q.front+1)%Maxsize;   
      }
}

队列的链式存储

1.定义:实际上它是带有头指针和尾指针的单链表,头指针指向的是队头结点,尾指针的指向的是队尾结点。

2.数据结构定义

typedef struct{                             //链式队列结点结构定义

        Elemtype data;                      

        Struct LinkNode *next;

}LinkNode;

Typedef struct{                       //链式队列     

      LinkNode *front,*rear;          //头指针与尾指针定义

}LinkQueue;

3.链式队列的基本操作:初始化;判队空;入队;出队

初始化:

void initQueue(LinkQueue &Q){

      Q.front=Q.rear=(LinkNode *)malloc(sizeof(LinkNode));

      Q.front->next=NULL;

}

判队空:

Void IsEmpty(LinkQueue Q){

   if(Q.front==Q.rear)

      return true;

   else

      return false;

}

入队:

void EnQueue(LinkQueue &Q,Elemtype x){
 
    LinkNode *s=(LinkNode *)malloc(sizeof(LinkNode));

    s->data=x;

    s->next=NULL;

    Q.rear->next=s;

    Q.rear=s;

}

出队:

Void GetQueue(LinkQueue &Q,Elemtype &x){

     if(Q.queue==Q.rear)     return false;   //空队时报错
 
     LinkNode *p=Q.front;

     x=p->data;

     Q.front=p->next;

     if(Q.rear==p)
 
     Q.rear=Q.rear;

     free(p);  

}

双端队列

定义:可以在队列两边都进行插入与删除操作的队列。

衍生:

1.输入受限的双端队列:允许一端进行插入和删除操作,在另一边则只可以进行输出操作。

2.输出受限的双端队列:允许一端进行插入和删除操作,在另一边则只可以进行输入操作。      

 练习题:

42. ( 10 分 ) 请设计一个队列,要求满足: ① 初始时队列为空; ② 入队时,允许增加队列占用空间; ③ 出队后,出队元素所占用的空间可重复使用,即整个队列所占用的空间只增不减; ④ 人队操作和出队操作的时间复杂度始终保持为 O(1) 。请回答下列问题:

( 1 ) 该队列应该选择链式存储结构,还是顺序存储结构?

( 2 ) 画出队列的初始状态,并给出判断队空和队满的条件

( 3 ) 画出第一个元素 入 队后的队列状态。

( 4 ) 给出入队操作和出队操作的基本过程。

1.应该使用链式存储结构。根据条件2的要求需要灵活的增加队列的占用空间。

2.根据条件3元素占用的空间需要可重复使用,所以推断需要的是循环队列。

初始化创建之后,只有一个空白结点及指向其的头指针front和尾指针rear。

队空条件:rear==front

队满条件:rear->next==front

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值