数据结构之队列(一)

        本系列文章主要学习“队列”这种数据结构的基本操作、实现方式、应用和扩展(双端队列)。其中,本文将介绍队列这种数据结构的特点和一种实现方式。


一、Queue(点击打开链接

        前面学习的Stack是在“pile”的同一端添加或删除元素,是一种FILO型的线性表;而Queue是在“pile”的一端添加元素,在“pile”的另一端删除元素,是一种FIFO型的线性表,如下图。


        队列的基本操作就是“入队”和“出队”。基础类接口如下:

<span style="font-size:14px;">#pragma once
#include "Container.h"
class Queue : public virtual Container
{
public:
    virtual Object & Head() const = 0;
    virtual void Enqueue(Object &) = 0;
    virtual Object & Dequeue() = 0;
};</span>


二、QueueAsArray

        同Stack一样,Queue既可以用动态数组实现,也可以用链表实现。先看它的数组实现:

<span style="font-size:14px;">#pragma once
#include "Queue.h"
#include "DynamicArray.h"
using namespace FoundationalDataStructure;

class QueueAsArray : public virtual Queue
{
public:
    QueueAsArray(unsigned int);
    ~QueueAsArray();

    void Purge();
    void Accept(Visitor &) const;

    Object & Head() const ;
    void Enqueue(Object &) ;
    Object & Dequeue() ;

protected:
    int CompareTo(Object const &) const;

protected:
    Array<Object*> array;
    unsigned int head;
    unsigned int tail;
};
</span>

        用数组来实现的队列,它包含了三个成员:head、tail和array。其中array就是存放元素指针的数组,而head和tail是数组元素的两个跟踪index。事实上,还有一个成员继承自“Container”,即“count”,元素计数。

        关于这三个int型成员的关系,如下:


        图a表示,一般情况下,head表示队列最左端元素的下标,tail表示队列最右端元素的下标。“count = tail - head + 1”。

        图b演示某些情况下,tail和head都增长,出现交叉(生成者 vs. 消费者)

        图c表示只有一个数组元素的情况,“head = tail”,注意元素的实际位置可以在数组的任一位置。

        图d展示了一种判断空队列的方法,“head越过了tail”。

<span style="font-size:14px;">#include "stdafx.h"
#include "QueueAsArray.h"


QueueAsArray::QueueAsArray(unsigned int size)
    : array(size)
    , head(0)
    , tail(size - 1)
{
}


QueueAsArray::~QueueAsArray()
{
    Purge();
}

void QueueAsArray::Purge()
{
    if (IsOwner())
    {
        for (unsigned int i = 0; i < count; ++i)
        {
            delete array[head];
            if (++head == array.Length())
                head = 0;
        }
    }
    count = 0;
}

void QueueAsArray::Accept(Visitor & visitor) const
{
    for (unsigned int i = 0; i < count && !visitor.IsDone(); ++i)
        visitor.Visit(*array[i]);
}

Object & QueueAsArray::Head() const
{
    if (count == 0)
        throw std::domain_error("queue is empty");

    return *array[head];
}

void QueueAsArray::Enqueue(Object & object)
{
    if (count == array.Length())
        throw std::domain_error("queue is full");

    if (++tail == array.Length())
        tail = 0;

    array[tail] = &object;
    ++count;
}

Object & QueueAsArray::Dequeue()
{
    if (count == 0)
        throw std::domain_error("queue is empty");

    Object &result = *array[head];
    if (++head == array.Length())
        head = 0;

    --count;
    return result;
}

int QueueAsArray::CompareTo(Object const & object) const
{
    return -1;
}
</span>

注:

        1)这是一个固定长度的队列,队列的size即数组的size。观察Enqueue和Dequeue的实现代码,它们分别对tail和head与数组长度进行比较,如果相等,则清零。

        2)head和tail只进行++运算。这样,也就很容易出现图b所示的情况。故,对队列来说左右两端是不交叉的,而它的实现数组是可以交叉的。

        3)Stack只有一个成员,即count,它可以++,也可以--运算。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值