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

循环队列 C++ 实现

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

循环队列 C++ 实现

文章目录
  • 循环队列
    • 判断入队时队尾指针应该如何变化
    • 判断出队时队头指针应该如何变化
    • 判断队列是否已满或已空
    • 不同情况的实现方式
      • 方式一
      • 方式二
      • 方式三
    • 判空
    • 计算队列元素个数
    • 整体实现
      • 方式一
      • 方式二
      • 方式三

循环队列

为解决假溢出问题,采用循环队列,循环队列即一种逻辑上的环状结构,但在物理空间上仍然为顺序存储,即数组

循环队列示例图
其中 f 为头指针,指向队列的第一个元素,r 为尾指针,指向队尾元素的下一个位置。


由于循环队列的处理有三种方法,此处先不给出具体结构体的定义;详细实现和采用的方式有关;

判断入队时队尾指针应该如何变化

一般情况,队尾指针简单后移 (rear + 1) 即可,队头指针不变

而当出现多次出队列以后,队尾指针到达数组最后一位时 (如下图)

简单的 rear + 1 将不会满足实际情况,此时,rear = (rear + 1) % MAX 将满足实际情况。并且此公式也适用于一般情况。因此可以得出结论,入队列时,在队列未满时,元素入队,队尾元素 rear = (rear + 1) % MAX ;

入队列前需要判断队列是否为满;

判断出队时队头指针应该如何变化

当队列非空时,队头元素出队列,队头指针移动;

出队列的指针变化和入队列一样 front = (front + 1) % MAX

出队需判断队列是否为空;

接下来讨论怎样判断队列的满或者空;

判断队列是否已满或已空

当队列已满时,有如下情况:

左图为一直入队列的情况,右图为出队列一次的情况

从图中可以看出,队满时,front = rear;是否能使用这个条件判断队列已满呢?再看队列为空时;

可见,在这种情况下不能使用 f = r 来判断队列为空,也不能判断队列已满;对此,有一些处理方式;

不同情况的实现方式 方式一

少使用一个存储单元,这样就可以避免队列满时 f = r,并且此时 f = r 可以判断队列为空;

此时,队满:(rear + 1) % MAX = front 队空:rear = front

结构体

typedef int Type;
#define MAX 20
typedef struct {
    Type data[MAX];
    int front, rear;
} SqQueue;

初始化

void InitQueue(SqQueue &Q) {
    Q.front = 0;
    Q.rear = 0;
}

入队列:(Q.rear + 1) % MAX == Q.front 为满

bool EnQueue(SqQueue &Q, Type x) {
    if((Q.rear + 1) % MAX == Q.front) {
        return false;
    }
    Q.data[Q.rear] = x;
    Q.rear = (Q.rear + 1) % MAX;
    return true;
}

出队列:Q.front == Q.rear 时为空

bool DeQueue(SqQueue &Q, Type &x) {
    if(Q.front == Q.rear) {
        return false;
    }
    x = Q.data[Q.front];
    Q.front = (Q.front + 1) % MAX;
    return true;
}
方式二

在结构体中设置一个表示队列大小的变量 size, 入队时加一,出队时减一,指针随之变化;

结构体

typedef struct {
    Type data[MAX];
    int front, rear;
    int size;
} SqQueue;

初始化

void InitQueue(SqQueue &Q) {
    Q.front = 0;
    Q.rear = 0;
    Q.size = 0;
}

入队列代码: size = MAX 时队列已满,不能入队列;

bool EnQueue(SqQueue &Q, Type x) {
    if(Q.size == MAX) {
        return false;
    }
    Q.data[Q.rear] = x;
    Q.rear = (Q.rear + 1) % MAX;
    Q.size++;
    return true;
}

出队列:size = 0 为空,不能出队列;

bool DeQueue(SqQueue &Q, Type &x) {
    if(Q.size == 0) {
        return false;
    }
    x = Q.data[Q.front];
    Q.front = (Q.front + 1) % MAX;
    return true;
}
方式三

在结构体中设置标志 tag, tag = 0 &&Q.front == Q.rear 表示队列为空, tag = 1 && Q.front == Q.rear 表示队列已满。初始时 tag 为 0,此后,若遇入队列后 Q.front == Q.rear 则表示队列必满,置 tag = 1;若遇到出队列后 Q.front == Q.rear 则表示队列必空;由此可写出其入队列和出队列代码;

结构体

typedef struct {
    Type data[MAX];
    int front, rear;
    int tag;
} SqQueue;

入队列:

Q.tag == 1 && Q.front == Q.rear 表示队列已满,若队列未满,则入队列,入队列后若 Q.front == Q.rear 则队列必满,此时置 tag 为 1;

bool EnQueue(SqQueue &Q, Type x) {
    if(Q.tag == 1 && Q.front == Q.rear) {
        return false;
    }
    Q.data[Q.rear] = x;
    Q.rear = (Q.rear + 1) % MAX;
    if(Q.front == Q.rear) {			//若入栈后相等,此时队列必满
        Q.tag = 1;
    }
    return true;
}

出队列:

Q.tag == 0 && Q.front == Q.rear 表示队列已空,若队列未满,则入队列,出队列后若 Q.front == Q.rear 则队列必空,此时置 tag 为 0;

bool DeQueue(SqQueue &Q, Type &x) {
    if(Q.tag == 0 && Q.front == Q.rear) { //队列为空时
        return false;
    }
    x = Q.data[Q.front];
	Q.front = (Q.front + 1) % MAX;
    if(Q.front == Q.rear) {			//若出队列后相等,此时队列必空
        Q.tag = 0;
    }
    return true;
}
判空
  1. 空一个位置

    只有空的时候会出现 Q.front == Q.rear

    bool QueueEmpty(SqQueue Q) {
        if(Q.front == Q.rear) {
            return true;
        }
        return false;
    }
    
  2. 设置 size

    bool QueueEmpty(SqQueue Q) {
        if(Q.size == 0) {
            return true;
        }
        return false;
    }
    
  3. 设置 tag

    bool QueueEmpty(SqQueue Q) {
        if(Q.front == Q.rear && Q.tag == 0) {
            return true;
        }
        return false;
    }
    
计算队列元素个数
  1. 方式一

    int length(SqQueue Q) {
        return (Q.rear + MAX - Q.front) % MAX;
    }
    
  2. 方式二

    int length(SqQueue Q) {
        return Q.size;
    }
    
  3. 方式三

    由于队列满时 Q.front == Q.rear,故需单独对队列满时进行处理

    int length(SqQueue Q) {
        if(Q.tag == 1 && Q.front == Q.rear) {
            return MAX;
        }
        return (Q.rear + MAX - Q.front) % MAX;
    }
    
整体实现

由于有三种不同的循环队列处理方式,因此也使用三种不同方式

方式一

数组空一个位置

测试方案

测试方案:依次入队列至如下情况,此时将不能入队列, rear = 7,front = 0;

出队列四次,入队列两次,此时队头为 4,队尾指针为 1;

出队列置队列为空,进行判空

#include
using namespace std;

typedef char Type;
#define MAX 8
typedef struct {
    Type data[MAX];
    int front, rear;
} SqQueue;


void InitQueue(SqQueue &Q) {
    Q.front = 0;
    Q.rear = 0;
}

bool EnQueue(SqQueue &Q, Type x) {
    if((Q.rear + 1) % MAX == Q.front) {
        return false;
    }
    Q.data[Q.rear] = x;
    Q.rear = (Q.rear + 1) % MAX;
    return true;
}


bool DeQueue(SqQueue &Q, Type &x) {
    if(Q.front == Q.rear) {
        return false;
    }
    x = Q.data[Q.front];
    Q.front = (Q.front + 1) % MAX;
    return true;
}


bool QueueEmpty(SqQueue Q) {
    if(Q.front == Q.rear) {
        return true;
    }
    return false;
}

int length(SqQueue Q) {
    return (Q.rear + MAX - Q.front) % MAX;
}


int main() {
    SqQueue queue;
    InitQueue(queue);
    char chs[7] = {'a', 'b', 'c', 'd', 'e', 'f', 'g'};
    for(int i = 0; i < 7; i++) {
        EnQueue(queue, chs[i]);
    }
    if(!EnQueue(queue, 'x')) {
        cout << "队列已满,入队失败" << endl;
    }
    cout << queue.front << " " << queue.rear << endl;

    //出队四次
    Type x;
    DeQueue(queue, x);
    cout << x << endl;
    DeQueue(queue, x);
    cout << x << endl;
    DeQueue(queue, x);
    cout << x << endl;
    DeQueue(queue, x);
    cout << x << endl;

    cout << "队列元素个数为 " << length(queue) << endl;
    //入队两次
    EnQueue(queue, 'h');
    EnQueue(queue, 'i');
    cout << "队列元素个数为 " << length(queue) << endl;

    cout << queue.front << " " << queue.rear << endl;

    while(!QueueEmpty(queue)) {
        DeQueue(queue, x);
        cout << x << " ";
    }

    return 0;
}


通过结果分析,和手动模拟一致;

方式二

结构体中设置 size

由于此类情况可以使用全部空间,对此进行检验

测试方案

测试方案:依次入队列至如下情况,此时, rear = 7,front = 0;

出队列四次,入队列五次,此时队列已满;将不能继续入队,指针均为 4

出队列置队列为空,进行判空

#include
using namespace std;

typedef char Type;
#define MAX 8
typedef struct {
    Type data[MAX];
    int front, rear;
    int size;
} SqQueue;


void InitQueue(SqQueue &Q) {
    Q.front = 0;
    Q.rear = 0;
    Q.size = 0;
}




bool EnQueue(SqQueue &Q, Type x) {
    if(Q.size == MAX) {
        return false;
    }
    Q.data[Q.rear] = x;
    Q.rear = (Q.rear + 1) % MAX;
    Q.size++;
    return true;
}


bool DeQueue(SqQueue &Q, Type &x) {
    if(Q.size == 0) {
        return false;
    }
    x = Q.data[Q.front];
    Q.front = (Q.front + 1) % MAX;
    Q.size--;
    return true;
}


bool QueueEmpty(SqQueue Q) {
    if(Q.size == 0) {
        return true;
    }
    return false;
}

int length(SqQueue Q) {
    return Q.size;
}


int main() {
    SqQueue queue;
    InitQueue(queue);
    char chs[7] = {'a', 'b', 'c', 'd', 'e', 'f', 'g'};
    for(int i = 0; i < 7; i++) {
        EnQueue(queue, chs[i]);
    }
    cout << queue.front << " " << queue.rear << endl;

    //出队四次
    Type x;
    DeQueue(queue, x);
    cout << x << endl;
    DeQueue(queue, x);
    cout << x << endl;
    DeQueue(queue, x);
    cout << x << endl;
    DeQueue(queue, x);
    cout << x << endl;

    cout << "队列元素个数为 " << length(queue) << endl;
    //入队五次
    EnQueue(queue, 'h');
    EnQueue(queue, 'i');
    EnQueue(queue, 'j');
    EnQueue(queue, 'k');
    EnQueue(queue, 'l');
    cout << "队列元素个数为 " << length(queue) << endl;
    cout << queue.front << " " << queue.rear << endl;
    if(!EnQueue(queue, 'x')) {
        cout << "队列已满,入队失败" << endl;
    }

    while(!QueueEmpty(queue)) {
        DeQueue(queue, x);
        cout << x << " ";
    }

    return 0;
}

方式三

此处和方式二使用同样的测试方案;

#include
using namespace std;

typedef char Type;
#define MAX 8
typedef struct {
    Type data[MAX];
    int front, rear;
    int tag;
} SqQueue;


void InitQueue(SqQueue &Q) {
    Q.front = 0;
    Q.rear = 0;
    Q.tag = 0;
}

bool EnQueue(SqQueue &Q, Type x) {
    if(Q.tag == 1 && Q.front == Q.rear) {
        return false;
    }
    Q.data[Q.rear] = x;
    Q.rear = (Q.rear + 1) % MAX;
    if(Q.front == Q.rear) {			//若入栈后相等,此时队列必满
        Q.tag = 1;
    }
    return true;
}


bool DeQueue(SqQueue &Q, Type &x) {
    if(Q.tag == 0 && Q.front == Q.rear) { //队列为空时
        return false;
    }
    x = Q.data[Q.front];
	Q.front = (Q.front + 1) % MAX;
    if(Q.front == Q.rear) {			//若出栈后相等,此时队列必空
        Q.tag = 0;
    }
    return true;
}


bool QueueEmpty(SqQueue Q) {
    if(Q.front == Q.rear && Q.tag == 0) {
        return true;
    }
    return false;
}
int length(SqQueue Q) {
    if(Q.tag == 1 && Q.front == Q.rear) {
        return MAX;
    }
    return (Q.rear + MAX - Q.front) % MAX;
}


int main() {
    SqQueue queue;
    InitQueue(queue);
    char chs[7] = {'a', 'b', 'c', 'd', 'e', 'f', 'g'};
    for(int i = 0; i < 7; i++) {
        EnQueue(queue, chs[i]);
    }
    cout << queue.front << " " << queue.rear << endl;

    //出队四次
    Type x;
    DeQueue(queue, x);
    cout << x << endl;
    DeQueue(queue, x);
    cout << x << endl;
    DeQueue(queue, x);
    cout << x << endl;
    DeQueue(queue, x);
    cout << x << endl;

    cout << "队列元素个数为 " << length(queue) << endl;
    //入队五次
    EnQueue(queue, 'h');
    EnQueue(queue, 'i');
    EnQueue(queue, 'j');
    EnQueue(queue, 'k');
    EnQueue(queue, 'l');
    cout << "队列元素个数为 " << length(queue) << endl;
    cout << queue.front << " " << queue.rear << endl;
    if(!EnQueue(queue, 'x')) {
        cout << "队列已满,入队失败" << endl;
    }

    while(!QueueEmpty(queue)) {
        DeQueue(queue, x);
        cout << x << " ";
    }

    return 0;
}

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

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

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