队列和上篇提到的栈类似,本质上都是特殊的线性表,它是在一端(队头)进行删除操作,另一端(队尾)进行插入操作,遵守先进先出的规则。。

既然队列也是线性表,当然也有两种数据存储方式:

顺序存储结构:这种结构事先要基本确定队列的大小,不支持动态分配存储空间,所以插入和删除元素比较省时,但是会造成空间的浪费。

                     为了节省空间,这里引入了循环队列,本质上也是顺序存储结构。

链式存储结构:可以不需要事先知道队列的大小,支持动态和释放空间,但是插入和删除操作比较耗时,也称链队列

建议:当事先基本上确定队列的大小,且插入和删除操作比较频繁时,优先考虑循环队列。。

1.循环队列实现:

头文件声明和定义放一块了,只实现了基本的操作,不是很完善,等看了源码再改。。

头文件:在Queue.h头文件中

#ifndef QUEUE_H
#define QUEUE_H
#include<cassert>
#include<iostream>
using namespace std;
template<typename T>
class Queue
{
public:
    Queue(int maxsize = 10);
    Queue(const Queue<T>& rhs);
    Queue<T>& operator=(const Queue<T>& rhs);
    ~Queue();
public:
    bool empty() const;
    bool IsFull() const;
    int size() const;

    void push(const T& data);
    void pop();
    T& front();
    T   front() const;
    T& back();
    T   back() const;
private:
    T *array;
    int Front;
    int rear;
    int capacity;
};

template<typename T>
Queue<T>::Queue(int maxsize) :Front(0), rear(0),capacity(maxsize)
{
    array = new T[maxsize];
    assert(array != NULL);    //存储分配失败则退出;
}

template<typename T>
Queue<T>::Queue(const Queue<T>& rhs) :Front(rhs.Front), rear(rhs.rear),capacity(rhs.capacity)
{
    array = new T[capacity];
    for (int i = 0; i != (this->size()); i++)
        array[i] = rhs.array[i];
}

template<typename T>
Queue<T>& Queue<T>::operator=(const Queue<T>& rhs)
{
    if (this != &rhs)
    {
        delete[] array;
        capacity = rhs.capacity;
        Front = rhs.Front;
        rear = rhs.rear;
        array = new T[capacity];
        for (int i = 0; i != (this->size()); i++)
            array[i] = rhs.array[i];
    }
    return *this;
}
template<typename T>
Queue<T>::~Queue()
{
        delete[] array;
}

template<typename T>
bool Queue<T>::empty() const
{
    return Front == rear;      //此处为循环队列,当front==rear时为空。
}

template<typename T>
bool Queue<T>::IsFull() const
{
    return(rear + 1) % capacity == Front;   //当(rear+1)%capacity==front为满,因为为满时差一个元素,但是可能rear>front,也可能rear<front.
}

template<typename T>
int Queue<T>::size() const
{
    return (rear - Front + capacity) % capacity;
}

template<typename T>
void Queue<T>::push(const T& data)
{
    if (!IsFull())
    {
        array[rear] = data;
        rear = (rear + 1) % capacity;
    }
    else                                                  //当队列满了之后可进行扩容
    {
        T *newarray=new T[ 2*capacity ];
        for (int i = 0; i != 2*capacity&&!this->empty(); i++)
        {
            newarray[i] =this-> front();
            this->pop();
        }
        delete [ ] array;
        array = newarray;
        Front = 0;
        array[rear] = data;
        rear =this->rear+1;
        capacity = 2*capacity;
    }
}

template<typename T>
void Queue<T>::pop()
{
    if (!empty())
    {
        //array[Front].~T();   //将队头元素析构掉
        Front = (Front + 1) % capacity;
    }
    else
        cout<<"empty queue!"<<endl;
}

template<typename T>
T& Queue<T>::front()
{
    if (empty())
        cerr << "Error, queue is empty!";
    return array[Front];
}
template<typename T>
T Queue<T>::front() const
{
    if (empty())
        cerr << "Error, queue is empty!";
    return array[Front];
}
template<typename T>
T& Queue<T>::back()
{
    if (empty())
        cerr << "Error, queue is empty!";
    return array[rear-1];                             //rear类似与尾后指针
}
template<typename T>
T Queue<T>::back() const
{
    if (empty())
        cerr << "Error, queue is empty!";
    return array[rear-1];
}
#endif // QUEUE_H

测试代码:

 网上找的代码:

#include<iostream>
#include"Queue.h"
using namespace std;

int main()
{
    Queue<int> q(10); //声明队列
    int n;
    cin >> n;
    for (int i = 0; i<n; i++)
        q.push(i + 1);
    while (!q.empty())
    {
        cout << q.front() << " ";
        q.pop();
        if (!q.empty()) //此处需要判断此时队列是否为空
        {
            q.push(q.front());
            q.pop();
        }
    }
    cout << endl;
    return 0;
}

 

2.链队列的实现:

头文件:

 在Queue1.h头文件中

#ifndef QUEUE_H1
#define QUEUE_H1
/**********在队头删除节点,队尾添加节点*************/
#include<iostream>
using namespace std;
template<typename T>
class Queue
{
public:
    Queue();
    ~Queue();
    bool empty() const;
    int size() const;
    void clear();
    void push(const T & node);
    void pop();
    T&  front();
    T   front() const;
private:       //也可以直接用来链表list直接构造
    struct  QueueNode
    {
        T data;
        QueueNode* next;
        QueueNode(const T& Newdata, QueueNode* nextnode=NULL) :data(Newdata), next(nextnode)
        { }
       // QueueNode() = default;
    };
    QueueNode * Front;  //队头指针
    QueueNode * rear;  // 队尾指针
    int count;
};
//此处不设头节点
template<typename T>
Queue<T>::Queue() :Front (NULL),  rear (NULL), count(0)
{}
template<typename T>
Queue<T>::~Queue()
{
    clear();
}
template<typename T>
void Queue<T>::push(const T & node)
{
    if(Front==NULL)
        Front=rear=new QueueNode(node);
    else
    {
     QueueNode * newqueuenode = new QueueNode(node);
    rear->next = newqueuenode;
    rear = newqueuenode;
    }
    count++;
}
template<typename T>
bool Queue<T>::empty() const
{
    return Front==NULL;
}

template<typename T>
int Queue<T>::size() const
{
    return count;
}

template<typename T>
void Queue<T>::clear()
{
    while (Front)
    {
        QueueNode * FrontofQueue = Front;
        Front = Front->next;
        delete FrontofQueue;
    }
    count = 0;
}

template<typename T>
void Queue<T>::pop()
{
    if (empty())
    {
        cerr << "Error, queue is empty!";
    }
    QueueNode * FrontofQueue = Front;
    Front = Front->next;
    delete FrontofQueue;
    count--;
}

template<typename T>
T& Queue<T>::front()
{
    if (empty())
    {
        cerr << "Error, queue is empty!";
    }
    return Front->data;
}

template<typename T>
T Queue<T>::front() const
{
    if (empty())
    {
        cerr << "Error, queue is empty!";
    }
    return Front->data;
}
#endif // QUEUE_H1

测试代码:

 

#include<iostream>
#include"Queue1.h"
using namespace std;

int main()
{
    Queue<int> q; //声明队列
    int n;
    cin >> n;
    for (int i = 0; i<n; i++)
        q.push(i + 1);
    while (!q.empty())
    {
        cout << q.front() << " ";
        q.pop();
        if (!q.empty()) //此处需要判断此时队列是否为空
        {
            q.push(q.front());
            q.pop();
        }
    }
    cout << endl;
    return 0;
}

 

两种方法运行结果是一样的。。

 

posted on 2017-03-14 15:12  liuamin  阅读(23321)  评论(0编辑  收藏  举报