队列--C++类的实现

一.队列的定义

队列是只允许一端在进行插入操作,而另一端进行删除操作的线性表

First In First Out的线性表,简称FIFO,允许插入的一段称为队尾,允许删除的一端称为队头

二.循环队列

1.队列顺序存储的不足

假设一个队列有n个元素,则顺序存储的队列需要建立一个大于n的数组

入队列操作,就是在队尾追加一个元素,因此时间复杂度为O(1)

与栈不同的是,队列的元素是在队头出列,队列中的所有元素都得向前移动,所以时间复杂度为O(n)

我们引入两个指针,front指向队头元素,rear指向队尾元素的下一个位置

出队时,front向后移动

入队时,rear向后移动

当front==rear时,表示队空

但是数组元素个数正好等于数组内存空间时,会出现rear移动到数组之外的错误,而front之前移动过的地方还是空闲的

为了解决这种假溢出的问题,我们使用循环队列

2.循环队列的定义

为了区别队空和队满的条件,我们一般会保留一个元素空间

也就是说,队满的时候,数组中还有一个空闲单元

毕竟是循环链表,循环过程中rear可能会加到大于数组大小maxSize的值

所以我们的队满条件改为如下:

(rear+1)%maxSize==front

在计算队列长度的时候,我们也要考虑到各种情况

当rear>front的时候,len=rear-front

当rear<front的时候,len=rear-front+maxSize

所以通用的计算队列长度公式为:

(rear-front+maxSize)%maxSize

有了这些知识储备,我们开始写循环队列的顺序储存类代码:

template <class T>
class SeqQueue{
private:
  int front,rear;
  int maxSize;
  T *element;
public:
  SeqQueue(int sz=20); //构造函数
  ~SeqQueue(){delete []elements;}
  bool EnQueue(T x);//若队列不满,则将x进队,否则队溢出处理 
    bool DeQueue(T& x);
    //若队列不空,则退出队头元素x并由函数返回true;否则队列空,返回false 
    bool getFront(T& x);
    //若队列不为空, 则返回true及队头元素的值, 否则返回false 
    bool IsEmpty() const { return (front==rear); }
    bool IsFull() const
    { return ((rear+1)%maxSize == front); } 
    int getSize()const  //求队长的函数
    { return (rear-front+maxSize)%maxSize; }
    void makeEmpty() { front=rear=0; }
    void output();
}

入队操作算法思路:

  • 判断是否队满

  • 赋值操作,然后将rear的指针向后移动一位

  • 一定要记得%maxSize

template <class T>
bool EnQueue(T x){
  if((rear+1)%maxSize == front){
    return false;
  }
  elements[rear]=x;
  rear=(rear+1)%maxSize;
  return true;
}

出队操作算法思路:

  • 判断是否队空

  • 将删除元素赋值带出,front指针向后移动一位

  • 一定要记得%maxSize

template <class T>
bool DeQueue(T &x){
  if(front==rear){
    return false;
  }
  x=elemens[front];
  front=(front+1)%maxSize;
  return true;
}

三.队列的链式存储形式

队列的链式存储结构,其实就是单链表,只不过只能尾进头出

直接上代码

template <class T>
struct LinkNode //链表结点类的定义
{
    T data; //数据域
    LinkNode<T>* link; //指针域
    LinkNode() { link = NULL; } //构造函数1
    LinkNode(const T& item, LinkNode<T>* ptr = NULL)
    {
        data = item; link = ptr;
    } //构造函数2
};

template <class T>
class ListQueue{
private:
  LinkNode<T>* front,rear; //头指针
}

出队操作

template <class T>
bool EnQueue(T x){
  LinkNode<T>* s;
  s.data=x;      //给新节点赋值
  s.next=NULL;     
  rear.next=s;     //将新结点插入,相当于把rear指针移到最后
  rear=s;
  return true;
}

入队操作

template <class T>
bool DeQueue(T &x){
  LinkNode<T>* p;   
  if(front==rear){  //判断是否队空
    return false;
  }
  p=front.next;   //把p指向front之后
  x=p.data;       //赋值带出
  front.next=p.next;    //
  if(rear==p){
    rear=front;
  }
  delete p;
  return true;
}

总的来说,确定队列长度最大值的情况下,建议使用循环队列

如果无法预估队列长度的时候,则使用链队列

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值