队列的相关知识与代码实现

一、队列的相关概念和定义

试想一下,有的时候电脑像死机一样,鼠标点什么都没用。而过了一会却好像酒醒了一样把你刚才的操作都顺序执行了一遍。这其实是因为操作系统中的多个程序因需要通过一个通道输出,而按先后次序排队等待造成的。这实际上是一种先进先出的思想,我们称之为队列
队列的应用非常广泛:
举例:键盘输入,显示器上记事本软件的输出等等。。包括操作系统的各种准备队列,就绪队列。。都是先进先出的典型。
队列的定义:是只允许在一端进行插入操作,而在另一端进行删除操作的线性表(First in first out,FIFO,先进先出)。

循环队列

队列作为一个线性表,也有顺序存储链式存储两种方式。
队列顺序存储的不足

  • 首先,队列顺序存储一个固定长度的序列,并向其中添加n个元素。若再添加元素只需加到队尾即可,时间复杂度为O(1)。
  • 然而,出栈时是队头出栈。因此,如果下次想再让队头出栈,则需要把所有元素往前移动一位,即把下标为1的元素移动到下标为0的地方,时间复杂度为O(n),并且是每次出栈一个元素就要重复执行一次。
  • 为避免这种情况,我们就引入两个指针front和rear分别指向队头和队尾。令front==rear时,队列为空。rear指向末尾元素的后面一位。这样可以避免队列满时也会出现front==rear的情况

问题1:当最后一个元素插到分配地址的末尾,而前面有空位置,那么rear指针何去何从?
:再重头开始,将rear指针插到最前面的分配的地址空间。
我们将这种队列称之为循环队列
问题2:rear可能比front大,也可能比front小,那么如何判断?
:两者最少相差1的内存空间(可能只相差1个位置,也可能是一圈,看rear在前面还是后面),这个时间我们就判断是满了。若队列的最大尺寸是Queuesize,那么队列满了的条件是(rear+1)%Queuesize==front(取模以后就整合了rear与front的大小前后两个位置各自的问题)。
问题3:队列长度计算公式:

  • rear>front时,长度为rear-front。
  • rear<front时,分两段。第一段为Queuesize-front,第二段为0+rear,合起来就是rear-front+Queuesize。
    因此通用计算长度为(rear-front+Queuesize)%Queuesize。

注意:此为顺序存储结构的方法。

链式队列

链式队列实际上就是线性表的单链表,只不过它只能尾进头出而已。尾进就用尾插法,头出可以参考一下栈的Pop()函数。
此时,rear没有必要空出一个元素,因为链式队列存储空间一般是用不完的,除非内存已满。

二、队列的代码实现

循环队列

//SeqQueue.h

#ifndef SEQQUEUE_H_
#define SEQQUEUE_H_
const int Queuesize = 10;
class SeqQueue
{
private:
    int num[Queuesize];
    int front;
    int rear;
public:
    SeqQueue();
    ~SeqQueue();
    void EnQueue(int e);
    void DeQueue();
    int length();
    void Print();
};
#endif

//SeqQueue.cpp

#include<iostream>
#include"SeqQueue.h"
using std::cout;
using std::endl;
SeqQueue::SeqQueue()
{
    front = rear = 0;
}
SeqQueue::~SeqQueue()
{
}
void SeqQueue::EnQueue(int e)
{
    if((rear+1)%Queuesize == front)//判断是否为满队列
        return;
    num[rear] = e;//把尾部加上元素
    rear = (rear+1)%Queuesize;//尾部向后一位
}
void SeqQueue::DeQueue()
{
    if(front == rear)//判断是否为空队列
        return;
    front = (front+1)%Queuesize;//front向后一位
}
int SeqQueue::length()
{
    return (rear-front+Queuesize)%Queuesize;
}
void SeqQueue::Print()
{
    for (int i=front;i!=rear;i=(i+1)%Queuesize)
    {
        cout << num[i] << " ";
    }
    cout << endl;
    cout << "Length: " << length() << endl;
}

//Test.cpp

#include<iostream>
#include"SeqQueue.h"
using namespace std;
int main()
{
    SeqQueue S;
    for (int i=0;i<5;i++)
    {
        S.EnQueue(i);
        S.Print();
    }
    for (int i=0;i<2;i++)
    {
        S.DeQueue();
        S.Print();
    }
    return 0;
}

输出结果:

输出结果.png

链式队列回来再补。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容