队列(Queue)是只允许在一端进行插入操作,而在另一端进行删除操作的线性表。是一种先进先出的线性表(FIFO)。允许插入的一端称为队尾,允许删除的一端称为队头。我们在《栈的顺序存储结构》中发现,栈操作的top指针在Push时增大而在Pop时减小,栈空间是可以重复利用的,而队列的front、rear指针都在一直增大,虽然前面的元素已经出队了,但它所占的存储空间却不能重复利用。但大多数程序并不是这样使用队列的,一般情况下出队的元素就不再有保存价值了,这些元素的存储空间应该回收利用,由此想到把队列改造成环形队列(Circular Queue):把queue数组想像成一个圈,front和rear指针仍然是一直增大的,当指到数组末尾时就自动回到数组开头,就像两个人围着操场赛跑,沿着它们跑的方向看,从front到rear之间是队列的有效元素,从rear到front之间是空的存储位置,如果front追上rear就表示队列空了,如果rear追上front就表示队列的存储空间满了。故一般我们将其实现为循环队列,当出队列时就不需要全部进行移动,只需要修改队头指针,也可以解决“假溢出”的问题。

示例程序:(改编自《大话数据结构》)

C++ Code 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
 
#include<iostream>
using namespace std;

#define MAXSIZE 20

typedef int ElemType;

typedef struct
{
    ElemType data[MAXSIZE];
    int front; /* 头指针 */
    int rear; /* 尾指针,若队列不空,指向队列尾元素的下一个位置 */
    int count; //元素个数
} SqQueue;

bool InitQueue(SqQueue &Sq)
{
    cout << "Init Queue ..." << endl;
    Sq.front = 0;
    Sq.rear = 0;
    Sq.count = 0;
    return true;
}

bool ClearQueue(SqQueue &Sq)
{
    cout << "Clear Queue ..." << endl;
    Sq.front = 0;
    Sq.rear = 0;
    Sq.count = 0;
    return true;
}

bool QueueEmpty(SqQueue &Sq)
{
    return Sq.count == 0; /* 队列空的标志 */
}

bool QueueFull(SqQueue &Sq)
{
    return Sq.count == MAXSIZE;
}

int QueueLength(SqQueue &Sq)
{
    if (QueueFull(Sq))
        return MAXSIZE;

/* 队列的当前长度 */
    return (Sq.rear - Sq.front + MAXSIZE) % MAXSIZE;
}
/* 返回头元素 */
bool GetHead(SqQueue &Sq, ElemType *pe)
{
    if (QueueEmpty(Sq))
        return false;
    else
    {
        *pe = Sq.data[Sq.front];
        cout << "Get Head Item " << *pe << endl;
        return true;
    }
}

bool EnQueue(SqQueue &Sq, ElemType Elem)
{
    /* 队列满 */
    if (QueueLength(Sq) == MAXSIZE)
        return false;
    cout << "EnQueue Item " << Elem << endl;
    Sq.data[Sq.rear] = Elem;/* 将元素赋值给队尾 */
    Sq.rear = (Sq.rear + 1) % MAXSIZE;/* rear指针向后移一位置, */
    /* 若到最后则转到数组头部 */
    Sq.count++;
    return true;
}

bool DeQueue(SqQueue &Sq, ElemType *pe)
{
    if (QueueEmpty(Sq))
        return false;
    *pe = Sq.data[Sq.front];/* 将队头元素赋值给*pe */
    cout << "DeQueue Item " << *pe << endl;
    Sq.front = (Sq.front + 1) % MAXSIZE;/* front指针向后移一位置, */
    /* 若到最后则转到数组头部 */

Sq.count--;
    return true;
}

bool QueueTraverse(SqQueue &Sq)
{
    if (QueueEmpty(Sq))
    {
        cout << "Queue is empty" << endl;
        return false;
    }

cout << "Queue Traverse ..." << endl;
    for (int i = 0;  i < Sq.count; i++)
        cout << Sq.data[i + Sq.front] << ' ';
    cout << endl;
    return true;
}

int main(void)
{
    SqQueue Sq;
    InitQueue(Sq);
    for (int i = 0; i < 20; i++)
        EnQueue(Sq, i);
    QueueTraverse(Sq);
    if (!QueueEmpty(Sq))
        cout << "Queue Length: " << QueueLength(Sq) << endl;
    int result;
    GetHead(Sq, &result);
    DeQueue(Sq, &result);
    DeQueue(Sq, &result);
    if (!QueueEmpty(Sq))
        cout << "Queue Length: " << QueueLength(Sq) << endl;
    QueueTraverse(Sq);

return 0;
}

输出为:

单是顺序存储,若不是循环队列,算法的时间性能是不高的,但循环队列也面临着数组可能溢出的问题。

注:上述用 Use a fill count to distinguish the two cases. 的方法实现循环队列。常用的还有 Always keep one slot open. 也就是多申请一个不用的元素

位置,那么判断满时  (cb->end + 1) % cb->size == cb->start;  判断空时 cb->end == cb->start;

参考:

《大话数据结构》

《Data Structures》

循环队列 - 顺序存储结构相关推荐

  1. 循环队列 (顺序存储)

    数组 和 链表是最基本的数据结构,栈.队列.树.图等复杂数据结构都是基于数组或链表方式存储 队列(Queue)特征: 循环队列的顺序存储是基于数组来实现的 队列是一种操作受限的线性表.队列只能在表的一 ...

  2. 8 线性表-循环队列-顺序存储

    这几天犹豫了一下要不要上机实现数据结构的代码 一轮复习已经结束了 第二次看还是觉得光看书实在太无感了 于是决定来上机 顺便加深印象 即使考不上 记录一些基础的知识 以后找工作也有用-- 好 就这样决定 ...

  3. 数据结构(C语言第二版)严蔚敏编,数据结构电子教材,线性表,栈,队列,顺序存储结构,初始化,入栈,出栈,入队,出队,c++

    前言 提示:本篇文章收录严蔚敏编写的数据结构C语言版本 简单介绍一下顺序表,顺序栈,循环队列,的顺序存储结构之间的区别 代码参考严蔚敏编写的<数据结构>,二维码动态演示可扫码可观看. - ...

  4. 数据结构(8)----栈与队列之循环队列

    循环队列的使用 循环队列顺序存储结构 #define MAXSIZE 100 typedef int QElemType; typedef struct SqQueue{QElemType data[ ...

  5. 循环队列(队列头尾相接的顺序存储结构)

    循环队列(头尾相接的循环) 1.引出循环队列 解决上一篇博客当中:队列顺序存储结构出现的问题 现在通过将 rear 指针重新指向下标为 0 的位置,来解决上述问题 rear+1之后跑到了数组末尾后一位 ...

  6. 环形队列的输出_循环队列的基本操作详细讲解

    实验学时: 2 实验类型: (设计型) 一.实验目的 1. 理解并掌握队列的逻辑结构和顺序存储结构,了解循环队列的特点: 2. 掌握循环队列中基本操作的相关算法: 3. 编程实现相关算法: 4. 学会 ...

  7. 数据结构与算法(3-2)队列(顺序队列、循环队列与链队列)

    目录 一.顺序队列 1.存储结构 2.入队和出队 总代码 二.循环队列 总代码: 三.链队列 1.存储结构 2.入队和出队 总代码 一.顺序队列 队列特征:先进后出.后进后出. 1.存储结构 //队列 ...

  8. 【swjtu】数据结构实验3_基于循环队列的排队买票模拟程序

    实验内容及要求: 编程建立循环队列存储结构,对排队买票过程进行模拟.要求程序在控制台屏幕上显示字符菜单: 1. 排队--输入新到达的买票人姓名,加入买票队列中: 2. 售票--排队队列中最前面的人购票 ...

  9. 数据结构笔记(十)-- 循环队列

    队列的顺序表示和实现 一.循环队列概述 循环队列 是把顺序队列首尾相连,把存储队列元素的表从逻辑上看成一个环,成为循环队列. 队头指针(front) 指向队列的队头元素. 队尾指针(rear) 指向队 ...

最新文章

  1. 第二课 --- git的(管理修改和撤销修改、删除文件)
  2. Oracle之索引、权限
  3. mysql001创建数据库
  4. (原創) 如何使用C++/CLI读/写jpg檔? (.NET) (C++/CLI) (GDI+) (C/C++) (Image Processing)
  5. Python3 爬虫学习笔记 C09【数据储存系列 — 文件储存】
  6. Ubuntu下安装Gerrit
  7. java 合并流_Java Stream 流实现合并操作示例
  8. win10安装pytorch简易教程
  9. 【Java编程】建立一个简单的JDBC连接-Drivers, Connection, Statement and PreparedStatement
  10. java 自己的 pid_Java获取自身PID方法搜集
  11. 用 Java 实现人脸识别功能
  12. 哈工大密码学实验(CA证书认证系统)
  13. HTML5标准制定完成,浏览器大战能消停吗?
  14. 内部收益率计算公式用计算机,使用EXCEL函数公式计算内部收益率,请请人解决,非常感谢! ! !...
  15. Small RNA测序
  16. 数学通道的应用(六)-补偿气缸压力
  17. spring cloud alibaba全家桶集合
  18. IP地址和域名之间的转换
  19. 计算机学院开学标语,新学期开学宣传标语大全
  20. python函数笔记_小白学习笔记之Python函数(一)

热门文章

  1. Winodws 10中pyCharm 2017安装
  2. 11 种方法教你用 Python 高效下载资源
  3. CentOS被攻击的分析过程
  4. 详解Linux上iptables配置命令及常见的生产环境防火墙规则
  5. android 学习 解决R.java不能自动生成问题,编译时adb.exe 找不到问题
  6. datatable行内内容太长,有时不自动换行解决方法
  7. java虚拟机内存不足,“Could not create the Java Virtual Machine”问题解决方案
  8. Android 启动APP时黑屏白屏的三个解决方案
  9. 我应该如何验证电子邮件地址?
  10. 找不到元数据文件“ .dll”