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