队列的简介与C++模板实现

何为队列?

队列(Queue)也是一种线性存储结构,它具有如下特点:

队列中的数据元素遵守“先进先出”(First In First Out)的原则,简称FIFO结构。
在队尾添加元素,在对首删除元素。

队列的相关概念与操作

1.对头与队尾:允许元素插入的一端称为队尾,允许删除元素的一端称为对首。
2.入队:队列的插入操作。
3.出队:队列的删除操作。
4.求队列的大小
5.求对首元素的值
6.判断队列是否为空


栈是一种线性结构,能以数组或链表作为底层数据结构来实现。

基于数组的队列实现

以数组做为底层数据结构时,一般将队列实现为循环队列。这是因为:
1.如果采用顺序存储,每次从数组头部删除元素后,其后的元素都要依次往前移一个位置,时间复杂度为O(n);
2.对于上述问题,有人提议将对首标志往后移就不用移动元素了,可是这回造成空间的浪费。
所以为了实现队列的插入删除都是O(1)的时间复杂度,同时不造成空间的流失,我们采用循环队列。

何为循环队列?
即把数组看成一个首尾相连的圆环,删除元素时将队首标志往后移动,添加元素时若数组尾部已经没有空间,则考虑数组头部的空间是否空闲,如果是,则在数组头部进行插入。

这里写图片描述

如上图所示,我们以begin和end分别代表队首和队尾标志,end后面还有一个空位但是我们不存储元素,那么如何判断队满或者队空呢?
1.当begin==end时,表示队空。
2.当(end+1)%maxsize==begin时,表示队满。

/*队列的抽象数据类型*/
template <typename T>
class ArrayQueue
{
public:
    //构造函数
    ArrayQueue(int s): maxsize(s),begin(0),end(0),array(NULL) {
        array = new T[maxsize];
    }
    //析构函数
    ~ArrayQueue()
    {
        delete []array;
    }


    T front();          //对首元素
    bool pop();         //出对
    bool push(T t);     //入队
    bool isEmpty();     //判空
    int size();         //队列的大小
private:
    int begin;      //对首元素
    int end;        //对尾
    T *array;       //数组
    int maxsize;    //容量
};
具体实现
template <typename T>
T ArrayQueue<T>::front()
{
    if(begin != end)
        return array[begin];
};

template <typename T>
bool ArrayQueue<T>::pop()
{
    if(begin == end)
        return false;
    begin = (begin+1)%maxsize;
    return true;
};

template <typename T>
bool ArrayQueue<T>::push(T t)
{
    if((end+1)%maxsize == begin)
        return false;
    array[end] = t;
    end = (end+1) % maxsize;
    return true;
};

template <typename T>
bool ArrayQueue<T>::isEmpty()
{
    if(begin == end)
        return true;
    else
        return false;
};

template <typename T>
int ArrayQueue<T>::size()
{
    return (end - begin + maxsize) % maxsize;
};
主函数
int main()
{
    ArrayQueue<string> queue(6);
    queue.push("one");
    queue.push("two");
    queue.push("three");
    queue.push("four");
    queue.push("five");

    cout << "队列长度:" << queue.size() << endl;

    while(!queue.isEmpty())
    {
        cout << queue.front() << endl;
        queue.pop();
    }
    return 0;
}

输出结果:

这里写图片描述


基于链表的栈实现

基于链表的队列不存在上述问题,我们只需考虑哪头做队首,哪头做队尾。如下图所示,很清晰直观,不再啰嗦。

这里写图片描述

链表结点
/*链表结点,即队列中的元素*/
template <typename T>
struct Node
{
    Node(T t):value(t),next(NULL) {}
    Node() = default;
public:
    T value;        //队列中元素的值
    Node<T>* next;  //链表节点指针
};
队列的抽象数据类型
/*基于链表的队列的ADT*/
template <typename T>
class LinkQueue
{
public:
    LinkQueue(): phead(NULL),pend(NULL),count(0){
        phead = new Node<T>();
        pend = phead;
        count = 0;
    }

    T front();          //对首元素
    bool pop();         //出对
    bool push(T t);     //入队
    bool isEmpty();     //判空
    int size();         //队列的大小
private:
    Node<T>* phead;
    Node<T>* pend;
    int count;    //队列元素的数量
};
具体实现
template <typename T>
T LinkQueue<T>::front()
{
    if(count != 0)
        return phead->next->value;
};

template <typename T>
bool LinkQueue<T>::pop()
{
    if(count == 0)
        return false;
    Node<T>* pdel = phead-> next;
    phead -> next = pdel -> next;
    delete pdel;
    count--;
    return true;
};

template <typename T>
bool LinkQueue<T>::push(T t)
{
    Node<T>* pnode = new Node<T>(t);
    pend -> next = pnode;
    pend = pnode;
    count++;
    return true;
};

template <typename T>
bool LinkQueue<T>::isEmpty()
{
    if(count == 0)
        return true;
    else
        return false;
};

template <typename T>
int LinkQueue<T>::size()
{
    return count;
};
主函数实例
int main()
{
    LinkQueue<string> lqueue;
    lqueue.push("one");
    lqueue.push("two");
    lqueue.push("three");
    lqueue.push("four");
    lqueue.push("five");

    cout << "队列长度:" << lqueue.size() << endl;

    while(!lqueue.isEmpty())
    {
        cout << lqueue.front() << endl;
        lqueue.pop();
    }
    return 0;
}
输出结果:

这里写图片描述

  用C++模板实现基于数组和链表的队列,和上节实现栈相似,希望对大家有所帮助。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值