数据结构——线性结构(5)——顺序队列的实现

queue.h文件

其实这部分文件跟我们的栈的头文件定义是一样的,就是我们的pop和push换成了enqueue跟dequeue

/*
 *这部分文件实现我们之前所使用的queue类
 *它主要的原理为 后进后出(LILO)
 */

 #ifndef _Queue_h
 #define _Queue_h

 /*
  *类型: Queue<ValueType>
  *此类建立一个称为队列的线性结构,其中仅从一端添加和删除值。
  *这个规定产生了一个(LILO)的行为,它是队列的定义特征。 
  *基本堆栈操作是dequeue·(把元素从队列中移除)和enqueue(把元素添加到队列中)。
  */
 template <typename ValueType>
 class Queue{
    public:
        /*
         *构造函数:Queue
         *用法:Queue <ValueType> queue
         *-----------------------------
         *初始化一个空队列
         */
        Queue();
        //析构函数
        ~Queue();
        /*
         *方法:size()
         *用法:int n = queue.size();
         *--------------------------
         *返回队列中元素的个数
         */
        int size();
        /*
         *方法:isEmpty()
         *用法:queue.isEmpty();
         *--------------------------
         *判断队列中元素是否为空 
         */ 
        bool isEmpty();
        /*
         *方法:clear()
         *用法:queue.clear();
         *--------------------------
         *清空队列中的所有元素 
         */ 
        void clear();
        /*
         *方法:enqueue()
         *用法:stack.enqueue();
         *--------------------------
         *向队尾插入一个元素 
         */ 
        void enqueue(ValueType);
        /*
         *方法:pop()
         *用法:queue.dequeue();
         *--------------------------
         *移除队头的一个元素,并返回其值,如果队空 则返回一个错误 
         */
        ValueType dequeue(); 
        /*
         *方法:peek()
         *用法:queue.peek();
         *--------------------------
         *返回队头的值,但是不移除,peek 偷看的意思,如果队空 则返回一个错误
         */ 
         ValueType peek(); 

         #include "queuepriv.h" //私有成员部分


 };

 #include "queueimpl.cpp" //将实现文件包含进来 

#endif

queuepriv.h文件

这部分定义我们的数组结构:

private:
    /*栈的链表结构*/
    struct Cell{
        ValueType data;
        Cell *link;
    };
    /*实例化变量*/
    Cell *stack; /*定义一个cell类型的指针,指向栈顶*/
    int count;   /*用返回栈中的元素个数*/

    /* Make it illegal to copy stacks */
    Stack(const Stack & value) { }
    const Stack & operator=(const Stack & rhs) { return *this; }

queueimpl.cpp文件

#ifdef _Queue_h
#include "error.h"

/*
 *构造函数,这个函数要为队列的元素分配存储空间,并为所有的对象进行初始化元素赋值
 */
template <typename ValueType>
Queue<ValueType>::Queue(){
    capacity = INITIAL_CAPACITY;
    array = new ValueType [capacity];
    head = 0;
    tail = 0;
}

/*
 *析构函数:释放我们之前分配的内存
 */
template <typename ValueType>
Queue<ValueType>::~Queue(){
    delete []array;
}

/*
 *返回队列中的元素个数,
 */
template<typename ValueType>
Queue<ValueType>::size(){
    return (tail + capacity - head) % capacity;
}

/*
 *判断队列是否为空,这个判断标准,无论是使用指针还是我们的数组
 *判断标准都是tail == head,请注意,这种解释意味着不能允许队列完全填写容量,
 *并且必须始终留下一个未使用的空间。
 */
template <typename ValueType>
bool Queue<ValueType>::isEmpty(){
    return tail == head;
}

/*
 *清空队列,清除方法不需要考虑环形缓冲区(即循环队列)中存在的任何现有数据的位置,
 *并且可以简单地重置头部和尾部索引。
 */
template <typename ValueType>
void Queue<ValueType>::clear(){
    head = tail = 0;
}

/*
 *入队列,此方法必须首先检查以确定元素是否有足够的空间供其插入,并在必要时
 *扩展数组存储空间。否则不可能区分队列为空的情况与队列完全充满时的情况,
 *当该大小小于容量时,该实现会扩展队列
 */
template <typename ValueType>
void Queue<ValueType>::enqueue(ValueType element){
    if(size = capacity - 1) {expandCapacity();}
    array[tail] = element;
    tail = (tail + 1) % capacity;
}

/*
 *出队列,这个方法必须检查我们的队列是否为空,如果是,那就报错
 */
template <typename ValueType>
ValueType Queue<ValueType>::dequeue(){
    if (isEmpty())
    {
        error("dequeue: Attempting to dequeue an empty queue");
    }
    ValueType result = array[head];
    head = (head + 1) % capacity;
    return result;
}

/*
 *查看队头元素
 */
template <typename ValueType>
ValueType Queue<ValueType>::peek(){
    if (isEmpty())
    {
        error("peek: Attempting to peek at an empty queue");
    }
    return array[head];
}

/*
 *扩展容量,只要空间不足,这个私有方法将动态数组的容量加倍。
 *为此,它必须分配一个新数组,将所有元素从旧数组复制到新的数组,并释放旧存储。 
 *请注意,此实现还将所有元素都移回数组的开头。
 */
template <typename ValueType>
void expandCapacity(){
    ValueType *oldArray = array;
    int count = Size();
    capacity = capacity *2;
    array = new ValueType[capacity];
    for (int i = 0; i <= count; i++)
    {
        array[i] = oldArray[(head + i) % capacity];
    }
    head = 0;
    tail = count;
    delete []oldArray;
}
#endif

这里有个算法,size的算法,如下:

return (tail + capacity - head) % capacity;

我们来看看为什么会有这个算法,假设一开始的队列如下’
这里写图片描述
这里写图片描述
也就是这种情况:
这里写图片描述

最后模上我们的容量 就完成了。

猜你喜欢

转载自blog.csdn.net/redrnt/article/details/78054127