本文主要学习“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>