当前位置:   article > 正文

队列(Queue)(数据结构与算法基础)_queue的结构体怎么定义

queue的结构体怎么定义

目录

队列(queue)

顺序队列

顺序队列的定义

循环队列的几个问题

循环顺序队列的初始化

求循环队列长度

循环队列入队

循环队列出队

循环顺序队列取队头元素

链队列

链队列的定义

链队列的初始化

链队列的销毁

链队列的入队

链队列出队

链队列的取队头元素


队列(queue)

特点

  • 是一个特殊的线性表,在表一端插入(表尾),在另一端(表头)删除。

  • 队列 又称为 先进先出(First In First Out)的线性表,简称FIFO结构。

  • 表尾称为 队尾 Top,表头称为 队头 Base。

  • 插入元素到 队尾 的操作,称为 入队

  • 队头 删除第一个元素的操作,称为 出队

逻辑结构

  • 与线性表相同,仍为一对一关系。

存储结构

  • 顺序队链队,以循环顺序队列更常见。

实现方式

  • 主要是入队出队函数,链队和顺序队不同。

顺序队列

队列的顺序存储:同一般线性表的顺序存储结构完全相同。

和栈不太一样的是,队列的头,尾指针都需要移动,以循环顺序队列为常见。

顺序队列的定义

  1.  #define MAXQSIZE 100 //最大队列长度
  2.  typedef struct {
  3.      QElemType *base;//初始化的动态分配存储空间
  4.      int front; //头“指针”
  5.      int rear; //尾“指针”
  6.  }SqQueue;

这里的头尾指针存放的不是真正意义上的指针,而是数组下标,是一个整数,目的是为了方便操作。

循环队列的几个问题

溢出

  • 加溢出:当rear = MAXQSIZE但front不为0时,是假溢出。

  • 真溢出:当rear = MAXQSIZE且front为0时,还要入队,是真溢出。

解决假溢出的方法是引入 循环队列。

将b[0]接在b[MAXQSIZE-1]之后。

方法:用%运算。

所以当我们入队时,不再是

  1.  Q.base[Q.rear] = x;
  2.  Q.rear++;

而是

  1.  Q.base[Q.rear] = x;
  2.  Q.rear = (Q.rear+1)%MAXQSIZE;

同样,出队时,不再是

  1.  x = Q.base[Q.front];
  2.  Q.front++;

而是

  1.  x = Q.base[Q.front];
  2.  Q.front = (Q.front+1)%MAXQSIZE;

但此时又出现了一个新的问题——队空和队满的条件都为

Q.rear == Q.front;

那么如何分辨是队空还是队满呢?

有三种方案:

  1. 另设一个标志以区别队空、队满。

  2. 另设一个变量,记录元素个数。(设置一个计数器)

  3. 少用一个元素空间。(常用)

用了第三种方案后:

  • 队空:Q.front == Q.rear;

  • 队满:(Qrear+1)%MAXSIZE == Q.front;

于是解决。

循环顺序队列的初始化

算法描述:

  1.  Status InitQueue(SqQueue &Q) {
  2.      Q.base = new QElemType[MAXQSIZE];//分配空间
  3.      if(!Q.base) exit(OVERFLOW); //存储分配失败
  4.      Q.front = Q.rear = 0; //头尾指针置为0,队列为空
  5.      return OK;
  6.  }

求循环队列长度

算法描述:

  1.  int QueueLength(SqQueue Q) {
  2.      return (Q.rear - Q.front + MAXQSIZE)%MAXQSIZE;
  3.  }

循环队列入队

算法思路:

  1. 判断是否栈满

  2. 元素插入队尾

  3. 尾指针+1

算法描述:

  1.  Status EnQueue(SqQueue &Q, QElemType e) {
  2.      if((Q.rear+1)%MAXQSIZE == Q.front) return ERROR; //队满
  3.      Q.base[Q.rear] = e; //元素插入队尾
  4.      Q.rear = (Q.rear+1)%MAXQSIZE; //尾指针+1
  5.      return OK;
  6.  }

循环队列出队

算法思路:

  1. 判断是否栈空

  2. 元素出队

  3. 头指针+1

算法描述:

  1.  Status DeQueue(SqQueue &Q, QElemType &e) {
  2.      if(Q.front == Q.rear) return ERROR; //队空
  3.      e = Q.base[Q.front]; //保存头元素
  4.      Q.front = (Q.front+1)%MAXQSIZE; //队头指针+1
  5.      return OK;
  6.  }

循环顺序队列取队头元素

算法描述:

  1.  SElemType GetHead(SqQueue Q) {
  2.      if(Q.front != Q.rear) //队列不为空
  3.          return Q.base[Q.front]; //返回队头指针元素的值,队头指针不变
  4.  }

链队列

链栈不需要头结点,链队列需要头结点。

链队列的定义

  • 结点的定义:

  1.  #define MAXQSIZE 100 //最大队列长度
  2.  typedef struct Qnode {
  3.      QElemType data;
  4.      struct Qnode *next;
  5.  } QNode, *QueuePtr;
  • 头尾指针的定义:

  1.  typedef struct {
  2.      QueuePtr front;//队头指针
  3.      QueuePtr rear;//队尾指针
  4.  } LinkQueue;

当 LinkQueue Q; 后就可以和之前一样用Q.front,Q.rear进行操作了。

链队列的初始化

算法描述:

  1.  Status InitQueue(LinkQueue &Q) {
  2.      Q.front = Q.rear = (QueuePtr)malloc(sizeof(QNode));
  3.      if(!Q.front) exit(OVERFLOW); //一般不用判断
  4.      Q.front->next = NULL;
  5.      return OK;
  6.  }

链队列的销毁

算法思路:从头开始依次释放。

算法描述:

  1.  Status DestroyQueue(LinkQueue &Q) {
  2.      while(Q.front) {
  3.          p = Q.front->next;
  4.          free(Q.front);
  5.          Q.front = p;
  6.     }//Q.rear = Q.front->next; free(Q.front) ; Q.front = Q.rear;
  7.      return OK;
  8.  }

链队列的入队

算法思路:

  1. 生成新节点p

  2. e存进p->data

  3. 修改队尾指针

算法描述:

  1.  Status EnQueue(LinkQueue &Q, QElemType e) {
  2.      p = (QueuePtr)malloc(sizeof(QNode));
  3.      if(!p) exit(OVERFLOW);
  4.      p->data = e; p->next = NULL;
  5.      Q.rear->next = p;
  6.      Q.rear = p;
  7.      return OK;
  8.  }

链队列出队

算法思路:

  1. 保存首元结点地址(可以顺便把data用e返回)

  2. 修改队头指针

  3. 释放之前的首元结点

算法描述:

  1.  Status DeQueue(LinkQueue &Q, QElemType &e) {
  2.      if(Q.front == Q.rear) return ERROR;
  3.      p = Q.front->next;
  4.      e = p->data;
  5.      Q.front->next = p->next;
  6.      if(Q.rear == p) Q.rear = Q.front;
  7.      delete p;
  8.      return OK;
  9.  }

链队列的取队头元素

算法描述:

  1.  Status GetHead(LinkQueue Q, QElemType &e) {
  2.      if(Q.front == Q.rear) return ERROR;
  3.      e = Q.front->next->data;
  4.      return OK;
  5.  }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小舞很执着/article/detail/975031
推荐阅读
相关标签
  

闽ICP备14008679号