【数据结构】队列(queue)-顺序队列(动态图解、c++、java)

文章目录

  • 什么是队列?
  • 顺序队列概述(图解)
  • 顺序队列的基本操作
    • 1. 初始化
    • 2. 入队
    • 3. 出队
    • 4. 查看队头元素
    • 5. 队列长度
    • 6. 释放空间
  • 完整代码
  • 总结

GitHub同步更新(已分类):Data_Structure_And_Algorithm-Review

公众号:URLeisure 的复习仓库
公众号二维码见文末

提示:以下是本篇文章正文内容,下面案例可供参考


什么是队列?

  • 队列是一种特殊的线性表,特殊之处在于它只允许在表的前端(front)进行删除操作,而在表的后端(rear)进行插入操作,和栈一样,队列是一种操作受限制的线性表。
  • 进行插入操作的端称为队尾,进行删除操作的端称为队头。
  • 这种先进先出(First In First Out,FIFO)的线性序列,称为“队列”。它的操作受限,只能在两端操作:一端进,一端出。
  • 进的一端称为队尾(rear),出的一端称为队头(front)。队列可以用顺序存储,也可以用链式存储。

顺序队列概述(图解)

  • 队列犹如火车穿山洞,先进去的部分先出来。(图片来源:淘宝)
    【数据结构】队列(queue)-顺序队列(动态图解、c++、java)_第1张图片
  • 队列的顺序存储采用一段连续的空间存储数据元素,并用两个整形变量记录对头和队尾元素的下标。

【数据结构】队列(queue)-顺序队列(动态图解、c++、java)_第2张图片

顺序队列的基本操作

  • 首先定义一个结构体(内部类),包含基地址和头尾索引。

c++代码如下(示例):

struct SqQueue{
    int *base;//基地址
    int front,rear;//头索引 尾索引
};

java代码如下(示例):

private class SqQueue{
    int []base;
   	int front,rear;
}

1. 初始化

  • 顺序队列定义好了之后,还要先定义一个最大的分配空间,顺序结构都是如此,需要预先分配空间。

空队

c++代码如下(示例):

bool InitQueue(SqQueue &Q){
    Q.base = new int[Maxsize];//分配空间
    if(!Q.base){//创建失败
        return false;
    }
    Q.front = Q.rear = 0;
    return true;
}

java代码如下(示例):

public boolean initQueue(){
    q = new SqQueue();
    q.base = new int[maxsize];
    if(q.base == null){
        return false;
    }
    q.front = q.rear = 0;
    return true;
}

2. 入队

  • 判断队列是否已满。

  • 元素放入队尾 rear 的位置,然后 rear 后移一位。
    【数据结构】队列(queue)-顺序队列(动态图解、c++、java)_第3张图片

c++代码如下(示例):

bool EnQueue(SqQueue &Q,int e){
    if(Q.rear>Maxsize - 1){//队满
        return false;
    }
    Q.base[Q.rear++] = e;//Q.base[Q.rear] = e; Q.rear++;
    return true;
}

java代码如下(示例):

public boolean enQueue(int e){
    if(q.rear > maxsize-1){
        return false;
    }
    q.base[q.rear++] = e;
    return true;
}

3. 出队

  • 判断队列是否为空。

  • 元素出队,然后队头 front 后移一位。

(在总结时会说明为何 front 后移之后还是队满状态。)

【数据结构】队列(queue)-顺序队列(动态图解、c++、java)_第4张图片

c++代码如下(示例):

bool DeQueue(SqQueue &Q,int &e){//e为出队元素值
    if(Q.front == Q.rear){//队空
        return false;
    }
    e = Q.base[Q.front++];//出队
    return true;
}

java代码如下(示例):

public int deQueue(){
    if(q.rear == q.front){
        return -1;
    }
    return q.base[q.front++];
}

4. 查看队头元素

  • 没什么好说的,太简单了。确保队列含有元素就行。

c++代码如下(示例):

int GetHead(SqQueue Q){
    if(Q.front != Q.rear){//队列非空
        return Q.base[Q.front];
    }
    return -1;
}

java代码如下(示例):

public int getHead(){
    if(q.rear != q.front){
        return q.base[q.front];
    }
    return -1;
}

5. 队列长度

c++代码如下(示例):

int QueueLength(SqQueue Q){
    return (Q.rear-Q.front);
}

java代码如下(示例):

public int queueLength(){
    return q.rear-q.front;
}

6. 释放空间

  • java 自动释放,c++ 需手动释放。

c++代码如下(示例):

void DestroyList(SqQueue &Q​){
  if(Q.base​){
    delete []Q.base​;
  }
}

完整代码

c++代码如下(示例):

#include

#define Maxsize 7
using namespace std;
struct SqQueue {
    int *base;
    int front, rear;
};

bool InitQueue(SqQueue &Q) {
    Q.base = new int[Maxsize];
    if (!Q.base) {
        return false;
    }
    Q.front = Q.rear = 0;
    return true;
}

bool EnQueue(SqQueue &Q, int e) {
    if (Q.rear > Maxsize - 1) {
        return false;
    }
    Q.base[Q.rear++] = e;
    return true;
}

bool DeQueue(SqQueue &Q, int &e) {
    if (Q.front == Q.rear) {
        return false;
    }
    e = Q.base[Q.front++];
    return true;
}

int GetHead(SqQueue Q) {
    if (Q.front != Q.rear) {
        return Q.base[Q.front];
    }
    return -1;
}

int QueueLength(SqQueue Q) {
    return (Q.rear - Q.front);
}

void DestroyList(SqQueue &Q) {
    if (Q.base) {
        delete []Q.base;
    }
}

int main() {
    SqQueue Q;
    int n, e;
    InitQueue(Q);
    cout << "输入元素个数" << endl;
    cin >> n;
    cout << "依次输入元素入队" << endl;
    while (n--) {
        cin >> e;
        EnQueue(Q, e);
    }
    cout << "队列长度:" << QueueLength(Q) << endl;
    cout << "队头元素:" << GetHead(Q) << endl;
    cout << "开始出队:" << endl;
    while (DeQueue(Q, e)) {
        cout << "出队元素:" << e << endl;
    }
    cout << "队列长度:" << QueueLength(Q) << endl;
    DestroyList(Q);
    return 0;
}

java代码如下(示例):

import java.util.Scanner;

public class A {
    private static Scanner input = new Scanner(System.in);
    private static final int maxsize = 7;

    private static class SqQueue {
        int[] base;
        int front, rear;
    }

    private static SqQueue q;

    public static boolean initQueue() {
        q = new SqQueue();
        q.base = new int[maxsize];
        if (q.base == null) {
            return false;
        }
        q.front = q.rear = 0;
        return true;
    }

    public static boolean enQueue(int e) {
        if (q.rear > maxsize - 1) {
            return false;
        }
        q.base[q.rear++] = e;
        return true;
    }

    public static int deQueue() {
        if (q.rear == q.front) {
            return -1;
        }
        return q.base[q.front++];
    }

    public static int getHead() {
        if (q.rear != q.front) {
            return q.base[q.front];
        }
        return -1;
    }

    public static int queueLength() {
        return q.rear - q.front;
    }

    public static void main(String[] args) {
        int n, x;
        initQueue();
        System.out.println("输入元素个数");
        n = input.nextInt();
        System.out.println("请输入每个元素");
        while (n-- > 0) {
            x = input.nextInt();
            enQueue(x);
        }

        System.out.println("队列元素个数:" + queueLength());
        System.out.println("队头元素是:" + getHead());
        System.out.println("开始出队:");
        while ((x = deQueue()) != -1) {
            System.out.println("队头元素为:" + x);
        }
        System.out.println("队列元素个数:" + queueLength());
    }
}

总结

  • 从图解和代码不难看出,当rear指向Maxsize位置时,有元素出队,但当前还是队满状态。这种情况称为“假溢出”

  • 解决的方法也很简单,如图。需要用到简单的循环操作,在下下下下下一篇的文章中会有另一种队列——循环队列,来实现此方法。
    循环队列


关注公众号,感受不同的阅读体验

请添加图片描述

下期预告: 顺序栈

你可能感兴趣的:(数据结构,c++,java,队列,图解法)