队列

本文介绍了队列的概念,队列是一种先进先出的数据结构,包括队列的顺序存储结构和链式存储结构,以及相应的基本运算如初始化、进队、出队等的实现。讨论了顺序队列在满和空的条件,以及环形队列解决假溢出问题的方法。此外,还阐述了链队的结构及操作,包括链队的初始化、销毁、判断队列是否为空、入队和出队等操作的实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、 队列的定义 

 队列简称队,它也是一种运算受限的线性表,其限制仅允许在表的一端进行插入,而在表的另一端进行删除。
把进行插入的一端称做队尾(rear),进行删除的一端称做队首或队头(front)

向队列中插入新元素称为进队或入队,新元素进队后就成为新的队尾元素;从队列中删除元素称为出队或离队,元素出队后,其后继元素就成为队首元素。 

由于队列的插入和删除操作分别是在各自的一端进行的,每个元素必然按照进入的次序出队,所以又把队列称为先进先出表

队列的基本运算如下:

InitQueue(&q):初始化队列。构造一个空队列q。
DestroyQueue(&q):销毁队列。释放队列q占用的存储空间。
QueueEmpty(q):判断队列是否为空。若队列q为空,则返回真;否则返回假。
enQueue(&q,e):进队列。将元素e进队作为队尾元素。

deQueue(&q,&e):出队列。从队列q中出队一个元素,并将其值赋给e。

二、队列的顺序存储结构及其基本运算的实现

  假设队列的元素个数最大不超过整数MaxSize,所有的元素都具有同一数据类型ElemType,则顺序队列类型SqQueue定义如下:
  typedef struct 
   {   ElemType data[MaxSize]; 
        int front,rear;//队首和队尾指针

   } SqQueue;

1)顺序队的四要素(初始时front=rear=-1)

队空条件:front=rear
队满条件:rear=MaxSize-1
元素e进队:rear++;data[rear]=e;

元素e出队:front++;e=data[front];

2) 顺序队中实现队列的基本运算

(1)初始化队列InitQueue(q)

  构造一个空队列q。将front和rear指针均设置成初始状态即-1值。

void InitQueue(SqQueue *&q)
{ q=(SqQueue *)malloc (sizeof(SqQueue));
  q->front=q->rear=-1;

}

(2)销毁队列DestroyQueue(q)

释放队列q占用的存储空间。

void DestroyQueue(SqQueue *&q)
{
   free(q);

}

(3)判断队列是否为空QueueEmpty(q)

       若队列q满足q->front==q->rear条件,则返回true;否则返回false。

bool QueueEmpty(SqQueue *q)
{
   return(q->front==q->rear);
}
(4)进队列enQueue(q,e) 

       在队列不满的条件下,先将队尾指针rear循环增1,然后将元素添加到该位置。

bool enQueue(SqQueue *&q,ElemType e)
{   if (q->rear==MaxSize-1) //队满上溢出
return false;
q->rear++;
q->data[q->rear]=e;
return true;

}

(5)出队列deQueue(q,e)

      在队列q不为空的条件下,将队首指针front循环增1,并将该位置的元素值赋给e。

bool deQueue(SqQueue *&q,ElemType &e)
{  if (q->front==q->rear) //队空下溢出
return false;
   q->front++;
   e=q->data[q->front];
   return true;
}

3)环形队中实现队列的基本运算

 用rear==MaxSize-1作为队满的条件有缺陷。可能队列为空,但仍满足该条件。这时进队时出现“上溢出”,这种溢出并不是真正的溢出,在data数组中存在可以存放元素的空位置,所以这是一种假溢出

为了能够充分地使用数组中的存储空间,把数组的前端和后端连接起来,形成一个环形的顺序表,即把存储队列元素的表从逻辑上看成一个环,称为环形队列或循环队列


环形队列的四要素:

队空条件:front==rear
队满条件:(rear+1)%MaxSize=front
进队e操作:rear=(rear+1)%MaxSize; 将e放在rear处

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

(1)初始化队列InitQueue(q)

       构造一个空队列q。将front和rear指针均设置成初始状态即0值。

void InitQueue(SqQueue *&q)
{   q=(SqQueue *)malloc (sizeof(SqQueue));
    q->front=q->rear=0;

}

(2)进队列enQueue(q,e) 

        在队列不满的条件下,先将队尾指针rear循环增1,然后将元素添加到该位置。

bool enQueue(SqQueue *&q,ElemType e)
{  if ((q->rear+1)%MaxSize==q->front)  //队满上溢出
return false;
   q->rear=(q->rear+1)%MaxSize;
   q->data[q->rear]=e;
   return true;
}
(3)出队列deQueue(q,e)

  在队列q不为空的条件下,将队首指针front循环增1,并将该位置的元素值赋给e。

bool deQueue(SqQueue *&q,ElemType &e)
{  if (q->front==q->rear) //队空下溢出
return false;
   q->front=(q->front+1)%MaxSize;
   e=q->data[q->front];
   return true;
}
三、 队列的链式存储结构及其基本运算的实现

   链队组成:
        (1)存储队列元素的单链表

        (2) 指向队头和队尾指针的链队头节点    

单链表中数据节点类型QNode定义如下:
typedef struct qnode
{  ElemType data; //数据元素
   struct qnode *next;
} QNode;
链队中头节点类型LiQueue定义如下:
typedef struct
{  QNode *front; //指向单链表队头节点
   QNode *rear; //指向单链表队尾节点

} LiQueue; 

链队的4要素:

队空条件:front=rear=NULL
队满条件:不考虑
进队e操作:将包含e的节点插入到单链表表尾
出队操作:删除单链表首数据节点

在链队存储中,队列的基本运算算法如下。
(1)初始化队列InitQueue(q)

       构造一个空队列,即只创建一个链队头节点,其front和rear域均置为NULL,不创建数据元素节点。对应算法如下:

void InitQueue(LiQueue *&q)
{  q=(LiQueue *)malloc(sizeof(LiQueue));
   q->front=q->rear=NULL;

}


(2)销毁队列DestroyQueue(q)

      释放队列占用的存储空间,包括链队头节点和所有数据节点的存储空间。对应算法如下:   

void DestroyQueue(LiQueue *&q)
{  QNode *p=q->front,*r;  //p指向队头数据节点
   if (p!=NULL)   //释放数据节点占用空间
   {  r=p->next;
while (r!=NULL)
{   free(p);
    p=r;r=p->next;
}
   }
   free(p);
   free(q);    //释放链队节点占用空间
}

(3)判断队列是否为空QueueEmpty(q)

      若链队节点的rear域值为NULL,表示队列为空,返回true;否则返回false。对应算法如下:     

bool QueueEmpty(LiQueue *q)
{
  return(q->rear==NULL);
}

(4) 入队enQueue(q,e)
       创建data域为e的数据节点*s。

   若原队列为空,则将链队节点的两个域均指向*s节点,否则将*s链到单链表的末尾,并让链队节点的rear域指向它。

void enQueue(LiQueue *&q,ElemType e)
{  QNode *p;
   p=(QNode *)malloc(sizeof(QNode));
   p->data=e;
   p->next=NULL;
   if (q->rear==NULL) //若链队为空,新节点是队首节点又是队尾节点
q->front=q->rear=p;
   else
   {  q->rear->next=p;//将*p节点链到队尾,并将rear指向它
q->rear=p;
   }

}

(5)出队deQueue(q,e)
      若原队列不为空,则将第一个数据节点的data域值赋给e,并删除之。

   若出队之前队列中只有一个节点,则需将链队节点的两个域均置为NULL,表示队列已为空。对应的算法如下:

bool deQueue(LiQueue *&q,ElemType &e)
{  QNode *t;
   if (q->rear==NULL) return false; //队列为空
   t=q->front;    //t指向第一个数据节点
   if (q->front==q->rear)  //队列中只有一个节点时
q->front=q->rear=NULL;
   else    //队列中有多个节点时
q->front=q->front->next;
   e=t->data;
   free(t);
   return true;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值