数据结构之“Ordered List and Sorted List”(二)

        本文主要学习“Ordered List”的两种实现——“ListAsArray”(基于动态数组:点击打开链接)和“ListAsLinkedList”(基于指针)。


一、“ListAsArray”(点击打开链接

        基于数组的List,有大小限制。

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

class ListAsArray : public virtual OrderedList
{
public:
    ListAsArray(unsigned int);
    ~ListAsArray();

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

    void Insert(Object &);
    Object & operator[](unsigned int) const;
    Object & operator[](Position const &) const;
    bool IsMemeber(Object const &) const;
    Object & Find(Object const &) const;
    Position & FindPosition(Object const &) const;
    void Withdraw(Object &);
    void Withdraw(Position const &);
    void InsertAfter(Position const &, Object &);
    void InsertBefore(Position const &, Object &);

    friend class Pos;

protected:
    int CompareTo(Object const &) const;

protected:
    Array<Object* > array;
    class Pos;
};


class ListAsArray::Pos : public Position
{
public:
    Pos(ListAsArray const &, unsigned int);
    void Reset();
    bool IsDone() const;
    Object& operator * () const;
    void operator ++();

    friend class ListAsArray;
    friend class SortedListAsArray;

protected:
    const ListAsArray & list;
    unsigned int offset;
};
</span>


        实现代码如下,需要注意的是:

        1,默认插入在List尾部;

        2,“InsertAfter”和“InsertBefore”是通过移位来实现的。

        3,“remove”也是通过移位来实现。


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


ListAsArray::ListAsArray(unsigned int size)
    : array(size)
{
}


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

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

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

void ListAsArray::Insert(Object & object)
{
    if (count == array.Length())
        throw std::domain_error("list is full");

    array[count] = &object;    // insert at the end
    ++count;
}

Object & ListAsArray::operator[](unsigned int offset) const
{
    if (offset > count)
        throw std::out_of_range("invalid offset");

    return *array[offset];
}

Object & ListAsArray::operator[](Position const & arg) const
{
    Pos const & position = dynamic_cast<Pos const &>(arg);

    if (&position.list != this || position.offset >= count)
        throw std::invalid_argument("invalid position");

    return *array[position.offset];
}

bool ListAsArray::IsMemeber(Object const & object) const
{
    for (unsigned int i = 0; i < count; ++i)
        if (array[i] == &object)    // compare with the address of a object
            return true;

    return false;
}

Object & ListAsArray::Find(Object const & object) const
{
    for (unsigned int i = 0; i < count; ++i)
        if (*array[i] == object)    // compares equal to the given object
            return *array[i];

    return NullObject::Instance();
}

Position & ListAsArray::FindPosition(Object const & object) const
{
    unsigned int i = 0;
    while (i < count && *array[i] != object)    // compares equal to the given object
        ++i;

    return *new Pos(*this, i);
}

void ListAsArray::Withdraw(Object & object)
{
    if (count == 0)
        throw std::domain_error("list is empty");

    unsigned int i = 0;
    while (i < count && array[i] != &object)
        ++i;

    if (i == count)
        throw std::invalid_argument("object is not found");

    for (; i < count - 1; ++i)
        array[i] = array[i + 1];

    --count;
}

void ListAsArray::Withdraw(Position const & arg)
{
    Pos const & position = dynamic_cast<Pos const &>(arg);

    if (count == 0)
        throw std::domain_error("list is empty");

    if (&position.list != this || position.offset >= count)
        throw std::invalid_argument("invalid position");

    for (unsigned int i = position.offset; i < count - 1U; ++i)
        array[i] = array[i + 1];

    --count;
}

void ListAsArray::InsertAfter(Position const & arg, Object & object)
{
    Pos const & position = dynamic_cast<Pos const &>(arg);

    if (count == array.Length())
        throw std::domain_error("list is full");

    if (&position.list != this || position.offset >= count)
        throw std::invalid_argument("invalid position");

    unsigned int const insertPosition = position.offset + 1;

    for (unsigned int i = count; i > insertPosition; --i)
        array[i] = array[i - 1];

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

void ListAsArray::InsertBefore(Position const & arg, Object & object)
{
    Pos const & position = dynamic_cast<Pos const &>(arg);

    if (count == array.Length())
        throw std::domain_error("list is full");

    if (&position.list != this || position.offset >= count)
        throw std::invalid_argument("invalid position");

    unsigned int const insertPosition = position.offset;

    for (unsigned int i = count; i >= insertPosition; --i)
        array[i] = array[i - 1];

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

int ListAsArray::CompareTo(Object const & object) const
{
    return -1;
}

// the implement of the ListAsArray::Pos
ListAsArray::Pos::Pos(ListAsArray const & _list, unsigned int _offset)
    : list(_list)
    , offset(_offset)
{}

bool ListAsArray::Pos::IsDone() const
{
    return offset >= list.count;
}

Object&  ListAsArray::Pos::operator * () const
{
    if (offset < list.count)
        return *list.array[offset];
    else
        return NullObject::Instance();
}

void ListAsArray::Pos::operator++()
{
    if (offset < list.count)
        ++offset;
}

void ListAsArray::Pos::Reset()
{
    offset = 0;
}
</span>


二、“ListAsLinkedList”()
        基于链表的实现更加灵活。

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

class ListAsLinkedList : public virtual List
{
public:
    ListAsLinkedList();
    ~ListAsLinkedList();
    void Purge();
    void Accept(Visitor &) const;

    void Insert(Object &);
    Object & operator[](unsigned int) const;
    Object & operator[](Position const &) const;
    bool IsMemeber(Object const &) const;
    Object & Find(Object const &) const;
    Position & FindPosition(Object const &) const;
    void Withdraw(Object &);
    void Withdraw(Position const &);
    void InsertAfter(Position const &, Object &);
    void InsertBefore(Position const &, Object &);

    friend class Pos;

protected:
    int CompareTo(Object const &) const;

protected:
    LinkedList<Object* > linkedList;
    class Pos;
};

class ListAsLinkedList::Pos : public Position
{
public:
    Pos(ListAsLinkedList const &, Node<Object*> const *);
    void Reset();
    bool IsDone() const;
    Object& operator * () const;
    void operator ++();

    friend class ListAsLinkedList;
    friend class SortedListAsLinkedList;

protected:
    const ListAsLinkedList & list;
    Node<Object*> const * ptr;
};
</span>

        基于链表的实现,添加或删除项的时候,直接“打开链接”和“添加链接”或“删除链接”即可。实现代码:

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


ListAsLinkedList::ListAsLinkedList()
{
}


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

void ListAsLinkedList::Purge()
{
    if (IsOwner())
    {
        for (auto ptr = linkedList.Head(); ptr != NULL; ptr = ptr->Next())
            delete ptr->Datum();
    }
    linkedList.Purge();
    count = 0;
}

void ListAsLinkedList::Accept(Visitor & visitor) const
{
    for (auto ptr = linkedList.Head(); ptr != NULL && !visitor.IsDone(); ptr = ptr->Next())
        visitor.Visit(*ptr->Datum());
}

void ListAsLinkedList::Insert(Object & object)
{
    linkedList.Append(&object);
    ++count;
}

Object & ListAsLinkedList::operator[](unsigned int offset) const
{
    if (offset > count)
        throw std::out_of_range("invalid offset");

    unsigned int i = 0;
    auto ptr = linkedList.Head();
    while (i < offset && ptr != NULL)
    {
        ptr = ptr->Next();
        ++i;
    }

    if (ptr == NULL)
        throw std::logic_error("should never happen");

    return *ptr->Datum();
}

Object & ListAsLinkedList::operator[](Position const & arg) const
{
    Pos const & position = dynamic_cast<Pos const &>(arg);

    if (&position.list != this || position.ptr == NULL)
        throw std::invalid_argument("invalid position");

    return *position.ptr->Datum();
}

bool ListAsLinkedList::IsMemeber(Object const & object) const
{
    for (auto ptr = linkedList.Head(); ptr != NULL; ptr = ptr->Next())
        if (ptr->Datum() == &object)    // compare with the address of a object
            return true;

    return false;
}

Object & ListAsLinkedList::Find(Object const & object) const
{
    for (auto ptr = linkedList.Head(); ptr != NULL; ptr = ptr->Next())
        if (*ptr->Datum() == object)    // compares equal to the given object
            return *ptr->Datum();

    return NullObject::Instance();
}

Position & ListAsLinkedList::FindPosition(Object const & object) const
{
    auto ptr = linkedList.Head();
    while (ptr && *ptr->Datum() != object)    // compares equal to the given object
        ptr = ptr->Next();

    return *new Pos(*this, ptr);
}

void ListAsLinkedList::Withdraw(Object & object)
{
    if (count == 0)
        throw std::domain_error("list is empty");

    linkedList.Extract(&object);

    --count;
}

void ListAsLinkedList::Withdraw(Position const & arg)
{
    Pos const & position = dynamic_cast<Pos const &>(arg);

    if (&position.list != this || position.ptr == NULL)
        throw std::invalid_argument("invalid position");

    linkedList.Extract(position.ptr->Datum());
    --count;
}

void ListAsLinkedList::InsertAfter(Position const & arg, Object & object)
{
    Pos const & position = dynamic_cast<Pos const &>(arg);

    if (&position.list != this || position.ptr == NULL)
        throw std::invalid_argument("invalid position");

    linkedList.InsertAfter(position.ptr, &object);
    ++count;
}

void ListAsLinkedList::InsertBefore(Position const & arg, Object & object)
{
    Pos const & position = dynamic_cast<Pos const &>(arg);

    if (&position.list != this || position.ptr == NULL)
        throw std::invalid_argument("invalid position");

    linkedList.InsertBefore(position.ptr, &object);
    ++count;
}

int ListAsLinkedList::CompareTo(Object const & object) const
{
    return -1;
}


// the implement of the ListAsLinkedList::Pos
ListAsLinkedList::Pos::Pos(ListAsLinkedList const & _list, Node<Object*> const * _ptr)
    : list(_list)
    , ptr(_ptr)
{}

bool ListAsLinkedList::Pos::IsDone() const
{
    return ptr == NULL;
}

Object&  ListAsLinkedList::Pos::operator * () const
{
    if (ptr)
        return *ptr->Datum();
    else
        return NullObject::Instance();
}

void ListAsLinkedList::Pos::operator++()
{
    if (ptr)
        ptr = ptr->Next();
}

void ListAsLinkedList::Pos::Reset()
{
    ptr = list.linkedList.Head();
}</span>



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值