抽象数据类型之容器(四)

        本文将继续学习容器的特性:容器元素的关联性和容器元素的索引。


一、Associations(点击打开链接)

        An association is an ordered pair of objects. The first element of the pair is called the key ; the second element is the value  associated with the given key.

        关联容器中存储的元素是有序对(键值对,key-value),典型的代表是std::map;非关联容器中的元素则没有键值对的区别,如stack、queue等。

<span style="font-size:14px;">#pragma once
#include "Object.h"
#include "OwnerShip.h"

class Association : public Object, public OwnerShip
{
public:
    Association(Object &);
    Association(Object &, Object &);
    ~Association();

    Object & Key() const;
    Object & Value() const;

    //std::hash<Object> Hash() const;
    void Put(std::ostream &)const;

protected:
    int CompareTo(Object const &) const;
    Object * key;
    Object * value;
};</span>

        上述定义的类Association就是一个键值对,类似于std::map中的std::pair。它有两个成员——key and value,它们都是指针。因此,类Association采用的是简介容器的实现方式。

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


Association::Association(Object & _key)
 : key(&_key)
 , value(NULL)
{
}

Association::Association(Object & _key, Object & _value)
 : key(&_key)
 , value(&_value)
{
}


Association::~Association()
{
    if (IsOwner())
    {
        delete key;
        key = NULL;
        delete value;
        value = NULL;
    }
}

Object & Association::Key() const
{
    return *key;
}

Object & Association::Value() const
{
    if (value == 0)
        return NullObject::Instance();
    else
        return *value;
}

int Association::CompareTo(Object const & object) const
{
    Association const & association = dynamic_cast<Association const &> (object);
    return Key().Compare(association.Key());
}

void Association::Put(std::ostream & s) const
{
    s << "Association { " << *key;
    if (value != NULL)
        s << ", " << *value;
    s << " }";
}
</span>


二、Searchable Container

        在介绍完前面几篇的内容后,现在可以来探讨容器的元素操作:添加、删除、索引等。Searchable Container就是对基础抽象容器的功能扩展,增加了如下四个接口:

<span style="font-size:14px;">class SearchableContainer : public virtual Container
{
public:
    virtual bool IsMemeber(Object const &) const = 0;
    virtual void Insert(Object &) = 0;
    virtual void Withdraw(Object &) = 0;
    virtual Object & Find(Object const &) const = 0;
};</span>

        这四个接口分别代表四个功能,即“It adds to the interface provided for containers functions for putting objects in and taking objects out, for testing whether a given object is in the container, and a routine to search the container for a given object.”

        需要注意的是,该容器是指针容器,“Find”的语义是找相等值,然后从容器中返回值相等的Object。此外,“Insert”函数没有指定位置,目前来说,容器还没有位置的概念,后面讲到具体的数据结构的时候会定义位置的概念。

下面展示全部代码和一个具体的类。

<span style="font-size:14px;">#pragma once
#include "Container.h"

class SearchableContainer : public virtual Container
{
public:
    virtual bool IsMemeber(Object const &) const = 0;
    virtual void Insert(Object &) = 0;
    virtual void Withdraw(Object &) = 0;
    virtual Object & Find(Object const &) const = 0;
};

class TransferingVisitor : public Visitor
{
public:
    TransferingVisitor(SearchableContainer & container)
        : destination(container)
    {}

    void Visit(Object & object)
    {
        destination.Insert(object);
    }

private:
    SearchableContainer & destination;
};</span>

注:这里定义了一个“转移Visitor”,它可以将一个容器的元素复制到另一容器,用到了插入操作。

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


//Methods of class SearchableContainer
bool SearchableContainer::IsMemeber(Object const & object) const
{
    MatchingVisitor visitor(object);
    this->Accept(visitor);
    return visitor.IsDone();
}

Object & SearchableContainer::Find(Object const & object) const
{
    //MatchingVisitor visitor(object);
    //this->Accept(visitor);
    //// visitor.Found();
    //return NullObject::Instance();
    Iterator & iter = this->NewIterator();
    while (!iter.IsDone())
    {
        if (*iter == object)
            break;
        ++iter;
    }
    return *iter;
}
</span>

注:这里展示了两种方法来实现SearchableContainer的接口。它既可以使用Visitor,也可以使用Iterator。


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

typedef Wrapper<char> SomeObject;
class Bag : public SearchableContainer
{
public:
    class BagIterator : public Iterator
    {
    public:
        BagIterator(Object *& ptr) : _ptr(ptr){}
        BagIterator(BagIterator& iter) : _ptr(&*iter){}
        BagIterator& operator = (BagIterator& iter) { _ptr = &*iter; }
        void Reset() { _ptr = NULL; }
        bool IsDone() const { return _ptr == NULL; }
        Object& operator * () const { return *_ptr; }
        void operator ++() { ++_ptr; }

    private:
        Object* _ptr;
    };

    Bag();
    ~Bag();
    Iterator & NewIterator() const;

    void Purge();
    void Accept(Visitor &) const;
    bool IsMemeber(Object const &) const;
    void Insert(Object &);
    void Withdraw(Object &);
    Object & Find(Object const &) const;

protected:
    int CompareTo(Object const &) const;

private:
    Array<SomeObject> array;     //Array<Object> array;
};
</span>

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


Bag::Bag()
{
}


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

Iterator & Bag::NewIterator() const
{
    Object * pObject = dynamic_cast<Object*>(const_cast<SomeObject*>(array.Data()));
    return *(new BagIterator(pObject));
}

void Bag::Purge()
{
    if (IsEmpty())
        return;

    if (IsOwner())
    {
        SomeObject* pObject = const_cast<SomeObject*>(array.Data());
        delete pObject;
        pObject = NULL;
    }
    else
    {
        for (unsigned int i = 0; i < array.Length(); ++i)
        {
            Withdraw(array[i]);
        }
    }

    count = 0;
}

void Bag::Accept(Visitor & visitor) const
{
    for (unsigned int i = 0; i < array.Length(); ++i)
    {
        if (visitor.IsDone())
            return;

        Object * pObject = dynamic_cast<Object*>(const_cast<SomeObject*>(&array[i]));

        visitor.Visit(*pObject);
    }
}

bool Bag::IsMemeber(Object const & object) const
{
    return SearchableContainer::IsMemeber(object);
}

void Bag::Insert(Object & object)
{
    unsigned int length = array.Length();
    array.SetLength(length + 1);
    array[length] = *dynamic_cast<SomeObject*>(&object);
}

void Bag::Withdraw(Object & object)
{
    Array<SomeObject> newArray;
    newArray.SetLength(array.Length() - 1);
    for (unsigned int i = 0; i < array.Length(); ++i)
    {
        if (array[i] == object)
            break;

        newArray[i] = array[i];
    }

    array = newArray;
}

Object & Bag::Find(Object const & object) const
{
    return SearchableContainer::Find(object);
}

int Bag::CompareTo(Object const & object) const
{
    Bag const & bag = dynamic_cast<Bag const &> (object);
    return 0;
}
</span>


        

你可能感兴趣的:(抽象数据类型之容器(四))