数据结构与算法——循环队列

今天总结循环队列。

什么是队列?

队列跟栈差不多,也是一种操作受限的线性表,只允许在线性表的一端进行插入操作,在另一端进行删除操作。插入的一端称为队尾,删除的一端称为队头,插入操作称为入队,而删除操作称作出出队,不含任何数据元素的队称为空队。队列也有两种实现方式,一种就是顺序存储,用数组实现,另一种是采用链表形式。今天总结顺序存储的循环队列。

什么是循环队列?

循环队列就是,当队尾指针移动到数组末尾时,下次再有元素入队时,可以将队尾指针重新移到数组前面没有元素的位置。

为什么要使用循环队列?

循环队列解决了,数组空间利用率的问题。设想,如果每将一个队列出队,则将后面的元素都向前移动,那么这个时候的时间复杂度为O(n),但是如果出队时,我们只将队头指针移向下一位,这样时间复杂度就为O(1),只是当队头指不断后移时,出队元素占用的空间就不能用了,这样队列的可用空间越来越少,当队尾指针到达数组末尾时,再插入元素就不行了,而此时出队的空间其实是可以放入元素的,因此我们就采用循环方式,让队尾指针可以移向前面出队元素的位置,并将元素插入。

队列中存在两个指针,一个时队头指针,一个时队尾指针,当队列为空时,则队头与队尾指针相等,均指向数组中的0下标。在队列中,队头所指的元素是不存在队列中,也就是说队头后面的那个元素才是队列的头元素。当队头与队尾指向同一处时(除过数组下标0这个位置),则队已满。

入队:当队列不满时,则将队尾指针向后移一位,将元素插入到这个位置。

出队:当队列不满时,将队头指针指向下一位。

获取队长度:有两种方法。

  • 用rear-front即可得出,但因为是循环队列,所有,有可能rear位置在front前面。当rear在前面时,则QueueSize-(QueueSize-rear-(QueueSize-front))= rear-front+QueueSize

    将两种情况合并可以这样写 (rear-front+QueueSize)%QueueSize

  • 初始化一计数器count,从队头指针开始移动,当rear!=front 就一直循环,计数器不断增1,直到rear==front

具体实现:

<span style="font-family:Courier New;font-size:14px;">#include <iostream>

using namespace std;
const int QueueSize = 10;
template <class T>
class CircleQueue {
public:
    CircleQueue() {
        front = rear = 0; //空队列
    }

    void EnQueue(T x);  //入队操作
    T DeQueue();        //出队操作
    T GetFront();       //查找对头元素
    bool IsEmpty() {    //判空队列
        return rear==front?true:false;
    }
    int GetLength();     //队列长度
    void PrintQueue();   //遍历队列
private:
    T data[QueueSize];
    int front;  //队头指针
    int rear;  //队尾指针
};
template <class T>
void CircleQueue<T>::EnQueue(T x) {
    if((rear+1)%QueueSize==front)
        throw "队列为空";
    rear = (rear+1)%QueueSize;  //队尾指针后移
    data[rear] = x;
}
template <class T>
T CircleQueue<T>::DeQueue() {
    if(rear==front)
        throw "队列为空";
    front = (front+1)%QueueSize;
    return data[front];
}

template <class T>
int CircleQueue<T>::GetLength() {
    int count = 0;
    int p = front;
    while(rear!=front) {
        count++;
        front = (front+1)%QueueSize;
    }
    front = p;
    return count;
    //第二种获取队列长度的方法 这里要分两种请框 rear>front
    //和rear<front 合并后就为下面这个 可以仔细推一下
    // return (rear-front+QueeuSize)%QueueSize;
}

template <class T>
T CircleQueue<T>::GetFront() {
    if(front==rear)
        throw "队列为空";
    return data[(front+1)%QueueSize];
}
template <class T>
void CircleQueue<T>::PrintQueue() {
    int p = front;  //保留头指针
    while(front!=rear) {
        cout<<data[(front+1)%QueueSize]<<" ";
        front = (front+1)%QueueSize;  //移动头指针
    }
    front = p;  //队头指针归位
    cout<<endl;
}
int main()
{
    CircleQueue<int> circleQueue;
    for(int i=0;i<9;i++) {
        circleQueue.EnQueue(i);
    }
    cout<<"队列长度"<<endl;
    cout<<circleQueue.GetLength()<<endl;;
    cout<<"遍历队列"<<endl;
    circleQueue.PrintQueue();
    //出队
    circleQueue.DeQueue();
    circleQueue.DeQueue();
    circleQueue.EnQueue(7);
    circleQueue.EnQueue(11);
    cout<<"遍历队列"<<endl;
    circleQueue.PrintQueue();
    cout<<"获取队头元素"<<endl;
    cout<<circleQueue.GetFront()<<endl;

    return 0;
}</span>
时间: 2024-10-16 11:00:47

数据结构与算法——循环队列的相关文章

【Java数据结构学习笔记之二】Java数据结构与算法之队列(Queue)实现

  本篇是数据结构与算法的第三篇,本篇我们将来了解一下知识点: 队列的抽象数据类型 顺序队列的设计与实现 链式队列的设计与实现 队列应用的简单举例 优先队列的设置与实现双链表实现 队列的抽象数据类型   队列同样是一种特殊的线性表,其插入和删除的操作分别在表的两端进行,队列的特点就是先进先出(First In First Out).我们把向队列中插入元素的过程称为入队(Enqueue),删除元素的过程称为出队(Dequeue)并把允许入队的一端称为队尾,允许出的的一端称为队头,没有任何元素的队列

数据结构学习之循环队列(顺序存储)

[摘要]队列特性:先进先出(FIFO)--先进队列的元素先出队列.来源于我们生活中的队列(先排队的先办完事). 这样有个缺陷,空间利用率不高,所以我们直接学习循环队列(基于连续内存的). (1)设计队列数据结构 typedef struct _QUEUE_NODE { int* pData; int length;//队列长度 int head ;//队头指针 int tail;//队尾指针 int count;//队列元素当前个数 }QUEUE_NODE; (2)申请队列内存 QUEUE_NO

数据结构与算法(六)--队列

一.学习大纲 队列的定义.分类.基本方法 队列的实现代码 队列的底层实现(数组.链表) 队列的的分类:顺序队列.循环队列 二.队列 队列的定义:先进者先出的一种操作受限的线性表数据结构,它包含入队enqueue()和dequeue()两个基本的操作: 作为一种非常基础的数据结构,队列的应用也非常广泛,特别是一些具有某些额外特性的队列,比如循环队列.阻塞队列.并发队列.它们在很多偏底层系统.框架.中间件的开发中,起着关键性的作用.比如高性能队列 Disruptor.Linux 环形缓存,都用到了循

数据结构基础(7) --循环队列的设计与实现

队列 队列简称队, 也是一种操作受限的线性表, 只允许在表的一端进行插入, 而在表的另一端进行删除.其特点为"先进先出(FIFO)",故又称为先进先出的线性表,简单队列如图所示: 循环队列 顺序队列有一个先天不足, 那就是空间利用率不高, 会产生"假溢出"现象,即:其实队列中还有空闲的空间以存储元素, 但我们在判断队列是否还有空间时, 队列告诉我们队列已经满了, 因此这种溢出并不是真正的溢出, 在data数组中依然存在可以放置元素的空位置, 所以说这是一种"

Java数据结构和算法(五)——队列

队列,queqe,就是现实生活中的排队. 1.简单队列: public class Queqe { private int array[]; private int front; private int end; private int number; private int max; private Queqe(int maxsize){ array = new int[maxsize]; max = maxsize; front = 0; end = 0; number = 0; } pri

数据结构与算法之队列、栈

除了数组.链表,线性的数据结构中还有很重要的几种结构:队列.栈. 队列,一种先进先出的数据结构(FIFO),其实队列可以看成是一个两个口的管道,从一个口进,另一个口出,先进去的必定得在另一个口先出去,否则后面的都出不去:栈,一种后进先出的数据结构(LIFO),栈更像是只有一个口的管道,只有一个开口可以进出,先进去的在底部,所以必须得让后进去的先出去,它才能出去. 实现队列和栈可以用顺序存储结构,也可以用链式存储结构.这里采用的是链表来实现,同时还有用两个栈实现一个队列和用两个队列实现一个栈的算法

Java数据结构与算法(3):队列

队列也是一种表,不同的是队列在一端进行插入而在另一端进行删除. 队列模型 队列的基本操作包括入队.出队操作.在表的末端插入元素,在表的开头删除元素,即先进先出(FIFO). 队列的数组实现 对于每一个队列数据结构,保留一个数组items以及位置front和back,分别表示队列的两端,还要记录元素的个数size.操作过程应该是:当一个元素x入队,size和back增1,置items[back]=x:出队时,返回items[front],size减1,然后front增1. 初始队列: 入队: 出队

数据结构和算法-007 队列

堆栈,另一个经典的数据结构.先进先出. 直接看代码吧,实现以下功能: 创建队列 插入值 取出值 值查看当前值 顺序插入 public class TheQueue {          private String[] queueArray;          private int queueSize;          private int front, rear, numberOfItems =0;          TheQueue(int size){                

数据结构与算法——链队列

总结链队列 什么是链队? 队列的链式存储结构称为链队列.链队也有两个指针,队头指针和队尾指针,这样队头删除和队尾插入操作就会很方便,链式队列一般像单链表一样,有一个头结点. 图示: 具体实现: <span style="font-family:Courier New;font-size:14px;">#include <iostream> using namespace std; template <class T> struct Node { T