栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

队列文档之顺序队列

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

队列文档之顺序队列

顺序队 定义 概念

队列的顺序实现指分配一块连续的存储单元存放队列中的元素,并附设两个指针:

  • 队头指针 front 指向队头元素。
  • 队尾指针 rear 指向队尾元素的下一个位置。

通常采用数组实现。

关于队列状态和操作如下:

  • 初始状态:将队头指针 front 和队尾指针 rear 都指向 0。

  • 队空状态:queue.front==queue.rear。

  • 队满状态:queue.rear==MAXSIZE。

  • 入队操作:队未满时,先赋值到队尾元素,再将队尾指针加一。

  • 出队操作:队非空时,先取出队头元素值,再将队头指针加一。

注:

  • 对于上面的队空和队满状态的判断实际上是存储错误的,甚至不能作为判断的条件。但是在这里让它条件成立,这里讨论的仅是普通的顺序队列,有缺陷的顺序队列。
  • 一些参考书中是将 queue.front==queue.rear==0 作为队空的条件,这是正确的,而我上面仅仅是 queue.front==queue.rear 作为队空的条件,这是有缺陷的,如『队空状态』图中下方的图,图中 queue.front==queue.rear==3,如果对这个队列进行入队操作,只能入队两次(即 queue.rear=3 和 queue.rear=4 的位置),但实际上下标为 0、1、2 的空间也是空的,也能入队,这就造成了空间浪费,所以书上才说不能作为队空的判定条件。而 queue.front==queue.rear==0 把队头指针和队尾指针都固定在了第一个数组位置,即队列中所有位置都可以入队,不存在空间浪费,才是真正的队空。
  • 说完了队空,再来说说队满,书中说 queue.rear==MAXSIZE 不能作为队满的条件,如『队空状态』图中下方的图,队列中仅有两个元素,但却满足该条件,而另外三个空间却是空的(虽然有值,但不是有效的队列元素值,因为顺序队列删除元素后并不会修改原有空间的值,而只是移动指针)。这时候如果再入队,就会出现“上溢出”,但这种溢出并不是真正的溢出,在 data 数组中仍然存在可以存放元素的空位置,所以这是一种“假溢出”。
  • 队列空间未能充分利用,这就是顺序队列的缺点,但在本节中我们允许这种缺点的存在,在下一节中才讲解决这种缺点的循环队列。
  • 通常我们所说的顺序队列,实际上是循环队列。但本节说的是这种带有缺陷的顺序队列,而非循环队列。
结构体
typedef struct {
    
    int data[MAXSIZE];
    
    int front;
    
    int rear;
} SeqQueue;
特点
  • front 表示队头指针,实际上就是数组下标,指向顺序队列的队头元素;rear 表示队尾指针,指向顺序队列的队尾元素的下一个位置。
  • 当队满(即rear==MAXSIZE)后再入队,就会发生上溢。即使队列中还有空闲空间。
  • 入队操作,如果队不满才能入队,先赋值到队尾元素,再将队尾指针加一。
  • 出队操作,如果队不空才能出队,先取出队头指针所指向的元素,再将队头指针加一。
基本操作

注,完整代码请参考:

  • SeqQueue.c
  • SeqQueue.java
  • SeqQueueTest.java
概述

顺序队列的常见操作如下:

  • void init(SeqQueue *queue):初始化顺序队列。其中 queue 表示顺序队列。
  • int isEmpty(SeqQueue queue):判断顺序队列是否为空。其中 queue 表示顺序队列。如果顺序队列为空则返回 1,否则返回 0。
  • int isFull(SeqQueue queue):判断顺序队列是否为满。其中 queue 表示顺序队列。如果顺序队列为满则返回 1,否则返回 0。
  • int enQueue(SeqQueue *queue, int ele):将元素进队。其中 queue 表示顺序队列;ele 表示待插入的新元素值。如果顺序队列为满则不能入队,则返回 0;如果入队成功则返回 1 表示成功。
  • int deQueue(SeqQueue *queue, int *ele):将元素出队。其中 queue 表示顺序队列。ele 用来存放出队的元素。如果顺序队列为空则不能出队,则返回 0;如果出队成功则返回 1 表示成功。
  • int size(SeqQueue queue):获取顺序队列的长度。其中 queue 表示顺序队列。返回顺序队列中元素个数。
  • int getFront(SeqQueue queue, int *ele):获取顺序队列队头元素。其中 queue 表示顺序队列;ele 用来存放队头元素。如果顺序队列为空则无法获取队头元素则返回 0,否则返回 1。
  • int getRear(SeqQueue queue, int *ele):获取顺序队列队尾元素。其中 queue 表示顺序队列;ele 用来存放队尾元素。如果顺序队列为空则无法获取队尾元素则返回 0,否则返回 1。
  • void clear(SeqQueue *queue):清空顺序队列所有元素。其中 queue 表示顺序队列。
  • void print(SeqQueue queue):打印顺序队列中所有元素。其中 queue 表示顺序队列。
init

初始化顺序队列。

实现步骤:

  • 将队头指针 front 和队尾指针 rear 都指向 0,表示空队列。

实现代码如下:

void init(SeqQueue *queue) {
    // 初始化顺序队列,将队头指针和队尾指针都指向 0
    // 有些实现中将队头指针和队尾指针指向 -1,这无所谓,只要能够实现队列功能即可
    queue->front = 0;
    queue->rear = 0;
}
isEmpty

判定顺序队列是否为空。如果为空则返回 1,否则返回 0 表示非空。

实现步骤:

  • 判断队头指针 front 和队尾指针 rear 是否指向同一位置,即 queue.front==queue.rear。

实现代码如下:

int isEmpty(SeqQueue queue) {
    // 如果队头指针和队尾指针都指向同一位置,则表示队列处于空
    // 因为队头指针和队尾指针在不断变化,只要它们相等就表示是空队列,其中 front 和 rear 可能是 0,有可能是 4,而非一直都初始化值
    if (queue.front == queue.rear) {
        return 1;
    } else {
        return 0;
    }
}
isFull

判断顺序队列是否已经满队,如果已满则返回 1,否则返回 0 表示未满。

实现步骤:

  • 如果队尾指针 queue.rear==MAXSIZE 那么就认定它队满。

实现代码如下:

int isFull(SeqQueue queue) {
    // 如果队尾指针指向了 MAXSIZE,即数组的最后一个位置,则表示队满
    // 因为规定在非空队列中,队尾指针始终指向队尾元素的下一位置,所以当元素是队列数组最后一个元素(MAXSIZE-1)时,那么队尾指针一定指向 MAXSIZE
    if (queue.rear == MAXSIZE) {
        return 1;
    } else {
        return 0;
    }
}
enQueue

将元素入队。如果队未满才能入队,否则返回 0 表示入队失败。如果入队成功则返回 1。以 queue=[11, 22, 33]; ele=44 为例如图:

实现步骤:

  • 参数校验,如果队满则不能入队。返回 0 表示入队失败。
  • 将元素入队。首先将队尾指针所指向的位置赋予元素值(因为队尾指针指向队尾元素的下一个位置,所以是空的能够直接赋予值);接着将队尾指针加一。
  • 返回 1 表示入队成功。

实现代码如下:

int enQueue(SeqQueue *queue, int ele) {
    // 0.参数校验,如果队满,则不能入队
    if (queue->rear == MAXSIZE) {
        return 0;
    }
    // 1.将元素入队
    // 1.1 先进行赋值,初始时队头指针指向 0
    queue->data[queue->rear] = ele;
    // 1.2 然后将队尾指针加一
    queue->rear++;
    // 1.3 返回 1 表示入队成功
    return 1;
}
deQueue

将元素出队。如果队空则不能出队,返回 0 表示出队失败。将出队元素保存到 ele,并返回 1 表示出队成功。以 queue=[11, 22, 33] 为例如图所示:

实现步骤:

  • 参数校验,如果队空,则不能出队。返回 0 表示出队失败。
  • 将元素出队。用 ele 保存队头指针所指向的元素;然后将队头指针加一,保证队头指针始终指向队头元素。
  • 返回 1 表示出队成功。

实现代码如下:

int deQueue(SeqQueue *queue, int *ele) {
    // 0.参数校验,如果队空则不能出队
    if (queue->front == queue->rear) {
        return 0;
    }
    // 1.将元素出队
    // 1.1 用 ele 保存队头元素
    *ele = queue->data[queue->front];
    // 1.2 将队头指针加一,表示删除队头元素,使得队头指针始终指向队头元素
    queue->front++;
    // 1.3 返回 1 表示出队成功
    return 1;
}
size

获取顺序队列中实际的元素个数。

实现步骤如下:

  • 用队尾指针 rear 减去队头指针 front,即为元素个数。虽然队头指针和队尾指针都是数组下标,但队尾指针是指向队尾元素的下一个位置,所以相减的结果就是队列的实际元素个数。

实现代码如下:

int size(SeqQueue queue) {
    // 由于队头指针始终指向队头元素,队尾指针指向队尾元素的下一个位置,所以元素个数是之差
    return queue.rear - queue.front;
}
getFront

读取队头元素,但并不出队。如果队空则不能读取,则返回 0,否则用 ele 保存队头元素,返回 1 表示读取成功。以 queue=[22, 33] 为例如图:

实现步骤:

  • 参数校验,如果队空则没有队头元素,自然也无法获取。返回 0 表示读取失败。

  • 直接读取队头指针所指向的元素。因为队头指针始终指向队头元素。

实现代码如下:

int getFront(SeqQueue queue, int *ele) {
    // 0.参数校验,如果是空队列,则不能获取到队头元素
    if (queue.front == queue.rear) {
        return 0;
    }
    // 1.用 ele 保存队头元素,即队头指针所指向的元素
    *ele = queue.data[queue.front];
    return 1;
}
getRear

读取顺序队列的队尾元素。如果顺序队空为空则返回 0 表示读取失败。否则用 ele 保存队尾元素,并返回 1 出队成功。以 queue=[11, 22, 33] 为例如图所示:

实现步骤:

  • 参数校验,如果队空,则不能读取队尾元素。返回 0 表示读取失败。
  • 读取队尾指针所指向位置的前一个位置的元素,用 ele 保存。因为队尾指针始终指向队尾元素的下一个位置,所以要读取队尾元素,需要读取到队尾指针的前一个位置的元素。
  • 返回 1 表示读取成功。

实现代码如下:

int getRear(SeqQueue queue, int *ele) {
    // 0.参数校验,如果是空队列,则不能获取到队尾元素
    if (queue.front == queue.rear) {
        return 0;
    }
    // 1.获取队尾元素,由于队尾指针指向队尾元素的下一个位置,所以需要将队尾指针减一来获取队尾元素
    *ele = queue.data[queue.rear - 1];
    return 1;
}
clear

清空顺序队列。以 queue=[11, 22, 33] 为例如图:

实现步骤:

  • 将顺序队列的队头指针 front 和队尾指针 rear 都指向 0,表示空队列。但实际上队列中原有的元素仍然存在,并没有被重置为某个值。

实现代码如下:

void clear(SeqQueue *queue) {
    // 清空顺序队列,将队头指针和队尾指针都置为 0
    queue->front = 0;
    queue->rear = 0;
}
print

打印队列中的所有有效元素。

实现步骤:

  • 从队头指针开始扫描整个顺序队列,直到队尾指针结束,但不包括队尾指针所指向的元素。

实现代码如下:

void print(SeqQueue queue) {
    printf("[");
    for (int i = queue.front; i < queue.rear; i++) {
        printf("%d", queue.data[i]);
        if (i != queue.rear - 1) {
            printf(", ");
        }
    }
    printf("]n");
}
注意事项

一道数据结构题,请问,顺序队列中,初始时front=-1,rear=0,这个什么情况?

顺序队列-百度百科

练习题

无。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/873379.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号