数据结构 学习总结4 队列

概述

只能在表的一端进行插入运算,在表的另一端进行删除运算的线性表 (头删尾插)
与同线性表相同,仍为一对一关系。
顺序队或链队,以循环顺序队更常见
只能在队首和队尾运算,且访问结点时依照先进先出(FIFO)的原则。
关键是掌握入队和出队操作,具体实现依顺序队或链队的不同而不同。
基本操作有入队或出队,建空队列,判队空或队满等操作。
队列 (Queue)是仅在表尾进行插入操作,在表头进行删除操作的线性表。
表尾即 an 端,称为 队尾 ; 表头即 a1 端,称为队头。
插入元素称为入队;删除元素称为出队。
它是一种先进先出(FIFO)的线性表。
队列的存储结构为链队或顺序队
(常用循环顺序队)
讨论:
空队列的特征?front=rear
队列会满吗?一般不会,因为删除时有free动作。除非内存不足
怎样实现入队和出队操作?
入队(尾部插入):rear->next=S; rear=S;
出队(头部删除):front->next=p->next;

操作

构造一个空队列

Status  InitQuene( LinkQuene  &Q ) 
{
    Q.front = Q.rear = new QNode;
    if  ( !Q.front )    exit ( OVERFLOW);
    Q.front —>next = NULL;
     return  OK;
 }

销毁队列

Status  DestroyQuene ( LinkQuene &Q)
{
     while ( Q.front ) 
   {  
       Q.rear = Q.front—>next;
       delete Q.front;
       Q.front = Q.rear;
    }
     return  OK;
}

入队

Status  EnQuene ( LinkQuene &Q, QElemType e)
{ //插入元素e为Q的新的队尾元素
    p = new Qnode;
    if ( !p)     exit (OVERFLOW);
    p—>data = e;   p—>next = NULL;
    Q.rear—>next = p;
    Q.rear = p;
    return  OK;
 }

出队

Status  DeQuene ( LinkQuene &Q, QElemType &e)
{ //若队列不空,则删除Q的队头元素,用e返回其值,并返回OK;
    // 否则返回ERROR
     if ( Q.front = = Q.rear )  return ERROR;
     p = Q.front —>next;
     e = p —>data;
     Q.front —>next = p —>next;
     if ( Q.rear = = p)   Q.rear = Q.front;
     delete p;
     return  OK;
}

顺序队

#define  MAXSIZE      100;
typedef  struct {
   SElemType   *base;
   int   front;
   int   rear;
}SqQueue;

假溢出与循环队列

什么叫“假溢出” ?如何解决?
在顺序队中,当尾指针已经到了数组的上界,不能再有入队操作,但其实数组中还有空位置,这就叫“假溢出”。
解决假溢出的途径———采用循环队列
在这里插入图片描述

新问题:在循环队列中,空队特征是front=rear;队满时也会有front=rear;判决条件将出现二义性!
解决方案有三:
① 加设标志位,让删除动作使其为1,插入动作使其为0,则可识别当前 front=rear
② 使用一个计数器记录队列中元素个数(即队列长度);
③ 人为浪费一个单元,令队满特征为front=(rear+1)%N;

循环队列中的“长度”到底是指总长度还是数据元素个数?

答:一般情况下的长度(L)是指元素个数(不含头结点或空闲单元),而maxsize N 才是指所有单元总数,即“容量”。

为什么要设计队列?它有什么独特用途?
离散事件的模拟(模拟事件发生的先后顺序);
操作系统中多道作业的处理(一个CPU执行多个作业);
简化程序设计。

循环队列的操作

初始化一空队列

Status   InitQueue (   SqQueue    &q )
{//初始化空循环队列  q
   q . base=(QElemType *)malloc(sizeof(QElemType)
* QUEUE_MAXSIZE);      
   //分配空间
   if (!q.base)  exit(OVERFLOW);  //失败,退出程序
   q.front =q.rear=0;   //置空队列
    return OK;
 }//InitQueue;

入队操作

Status   EnQueue(SqQueue  &q,    QElemType e)
{//向循环队列  q 的队尾加入一个元素 e
   if (   (q.rear+1) %  QUEUE_MAXSIZE = =  q.front  ) 
                    return  ERROR ;
      q.base [ q.rear ] = e; //存储
  q.rear = ( q . rear + 1 ) %  QUEUE_MAXSIZE;//指针后移
      return  OK;
 }// EnQueue;

出队操作
在删除前应当判断队列是否空;
if (q.front = q.rear ) return ERROR;
插入动作分析;
因为队头指针front指向队头元素的位置,所以:
e = q.base [ q.front ] ;
q.front = ( q . front + 1 ) % QUEUE_MAXSIZE;

Status     DeQueue ( SqQueue  &q,    QElemType &e)
 {//若队列不空,删除循环队列 q 的队头元素,
        //由 e 返回其值,并返回OK
      if ( q.front = = q.rear )   return ERROR;//队列空
      e = q.base [ q.front ] ;  //队头元素出队
     q.front=(q.front+1) % QUEUE_MAXSIZE ;   
                                                          //指针后移
     return OK;
    }// DeQueue

小结

线性表、栈与队的异同点
相同点:逻辑结构相同,都是线性的;都可以用顺序存储或链表存储;栈和队列是两种特殊的线性表,即受限的线性表(只是对插入、删除运算加以限制)。
不同点:
① 运算规则不同,线性表为随机存取,而栈是只允许在一端进行插入和删除运算,因而是后进先出表LIFO;队列是只允许在一端进行插入、另一端进行删除运算,因而是先进先出表FIFO。
② 用途不同,线性表比较通用;堆栈用于函数调用、递归和简化设计等;队列用于离散事件模拟、多道作业处理和简化设计等。

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值