1 / 56

Generic Positional Containers and Double-Ended Queues

Generic Positional Containers and Double-Ended Queues. Andy Wang Data Structures, Algorithms, and Generic Programming. Generic Positional Containers. A generic container C Stores elements by position vector[i] = ‘a’; list.insert(I, ‘a’); A template class for a proper type T

joylyn
Télécharger la présentation

Generic Positional Containers and Double-Ended Queues

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Generic Positional Containers and Double-Ended Queues Andy Wang Data Structures, Algorithms, and Generic Programming

  2. Generic Positional Containers • A generic container C • Stores elements by position • vector[i] = ‘a’; • list.insert(I, ‘a’); • A template class for a proper type T • C<T> is a proper type • C<T> is capable of storing a number of T objs • C<T> supports an iterater class C<T>::Iterator

  3. More on Generic pContainers • Organized and accessed by position • Can insert any T object at any position in C<T> • Can remove any T object at any position in C<T> • Can support • PushFront(), PopFront(), Front() • PushBack(), PopBack(), Back()

  4. Traditional Double-Ended Queue Class • Deque (pronounced “deck”) • Deque operations • Push/Pop at either end • Retrieve data from either end • Proper type

  5. Traditional Double-Ended Queue Class (2) • Assumptions on element type T (proper type) • Constructor T() and destructor ~T() • Copy constructor • Assignment operator=

  6. Specifying TDeque<T> • Traditional assumptions, plus • O(1) average runtime, O(Size()) space • PushFront(t), PopFront(), Front() • PushBack(t), PopBack(), Back() • O(1) time and space for iterator opeartions • Random access iterators ([], pointer arithmetics)

  7. TDeque<T> Implementation Plan • Circular array • Protected array content of size content_size • Illusion: content[content_size] == content[0]

  8. begin end TDeque<T> D Illustrated • content_size = 8 • D.Empty() == true content

  9. begin end TDeque<char> D Illustrated (2) • content_size = 8 • D.PushBack(‘M’) content

  10. begin end TDeque<char> D Illustrated (3) • content_size = 8 • D.PushBack(‘e’) content

  11. begin end TDeque<char> D Illustrated (4) • content_size = 8 • D.PushBack(‘r’) content

  12. begin end TDeque<char> D Illustrated (5) • content_size = 8 • D.PushBack(‘r’) content

  13. begin end TDeque<char> D Illustrated (6) • content_size = 8 • D.PushBack(‘y’) content

  14. begin end TDeque<char> D Illustrated (7) • content_size = 8 • D.PopFront() • O(1) content

  15. begin end TDeque<char> D Illustrated (8) • content_size = 8 • D.PopFront() content

  16. begin end TDeque<char> D Illustrated (9) • content_size = 8 • D.PushBack(‘G’) content

  17. begin end TDeque<char> D Illustrated (10) • content_size = 8 • D.PushBack(‘o’) • D.Size() == (7 – 2 + 8) % 8 content

  18. begin end TDeque<char> D Illustrated (11) • content_size = 8 • D.PushBack(‘A’) • D.Size() = (0 – 2 + 8) % 8 content

  19. begin end TDeque<char> D Illustrated (12) • content_size = 8 • D.PushBack(‘r’) content

  20. begin end TDeque<char> D Illustrated (13) • D.Size() == content_size – 1 • Return full or • Double the capacity content

  21. TDeque<T> Implementation Plan (2) • Relative Indexing • Protected integers begin, end • Element position relative to begin • Front element is content[begin] • Back element is content[end – 1] • Size is (end – begin + content_size) % content_size

  22. TDeque<T> Implementation Plan (3) • Class Bracket Operator • Similar to TVector • Distinguished from TDeque Iterator bracket operation

  23. TDeque<T>::Iterator Implementation Plan • Public interface • Start with the public interface of TList<T>::Iterator • Add bracket operator • Add “pointer arithmetic” • Protected data • Pointer to a specific TDeque<T> object • A deque index value

  24. Defining TDeque<T> template <typename T> class TDeque { public: typedef T value_type; // type definitions typedef TDequeIterator<T> Iterator; TDeque(); // constructors and deconstructor TDeque(size_t, const T&); TDeque(const TDeque<T>&); ~TDeque(); // display functions void Display(ostream& os, char ofc = ‘\0’) const; void Dump(ostream& os) const;

  25. Defining TDeque<T> (2) int Empty() const; // container read-only routines size_t Size() const; T& Front() const; T& Back() const; T& operator[] (size_t) const; int PushFront(const T&); // container write routines int PopFront(); int PushBack(const T&); int PopBack(); TDeque<T>& operator=(const TDeque<T>&);

  26. Defining TDeque<T> (3) friend class TDequeIterator<T>; // iterator support Iterator Begin() const; Iterator End() const; protected: T* content; size_t content_size, begin, end; };

  27. Defining TDeque<T> (4) // operator overloads (friend status not required) template<class T> ostream& operator<<(ostream& os, const TDeque<T>& a); template<class T> int operator==(const TDeque<T>&, const TDeque<T>&); template<class T> int operator!=(const TDeque<T>&, const TDeque<T>&);

  28. Defining TDequeIterator<T> template <typename T> class TDequeIterator { friend class TDeque<T>; public: typedef T value_type; // terminology support TDequeIterator(); // constructors TDequeIterator(const TDeque<T>& I); TDequeIterator(const TDequeIterator<T>& I); TDequeIterator(const size_t& i); T& Retrieve() const; // return ptr to current Tval int Valid() const; // cursor is valid element

  29. Defining TDequeIterator<T> (2) // various operators int operator==(const TDequeIterator<T>& I2) const; int operator!=(const TDequeIterator<T>& I2) const; T& operator*() const; // return reference to current Tval T& operator[] (size_t i) const; // return ref to Tval at index TDequeIterator<T>& operator=(const TDequeIterator<T>& I); TDequeIterator<T>& operator++(); // prefix TDequeIterator<T> operator++(int); // postfix TDequeIterator<T>& operator--(); // prefix TDequeIterator<T> operator--(int); // postfix

  30. Defining TDequeIterator<T> (3) // pointer arithmetic long operator-(const TDequeIterator<T>& I2) const; TDequeIterator<T>& operator+=(long n); TDequeIterator<T>& operator-=(long n); TDequeIterator<T> operator+(long n) const; TDequeIterator<T>& operator+=(int n); TDequeIterator<T>& operator-=(int n); TDequeIterator<T> operator+(int n) const; TDequeIterator<T>& operator+=(unsigned long n); TDequeIterator<T>& operator-=(unsigned long n); TDequeIterator<T> operator+(unsigned long n) const; TDequeIterator<T>& operator+=(unsigned int n); TDequeIterator<T>& operator-=(unsigned int n); TDequeIterator<T> operator+(unsigned int n) const;

  31. Defining TDequeIterator<T> (3) protected: const TDeque<T>* Qptr; size_t index; };

  32. Implementing TDeque<T> • Default constructor template <typename T> TDeque<T>::TDeque() : content(0), begin(0), end(0), content_size(0) { content = new T[default_content_size]; if (content == 0) { // error } content_size = default_content_size; }

  33. Implementing TDeque<T> (2) • Copy constructor template <typename T> TDeque<T>::TDeque(const TDeque<T>& Q) : content_size(Q.content_size), begin(Q.begin), end(Q.end) { content = new T[content_size]; if (content == 0) { // error } for (size_t j = 0; j < content_size; j++) { content[j] = Q.content[j]; } }

  34. Implementing TDeque<T> (3) • Read-only functions template <typename T> size_t TDeque<T>::Size() const { return (end – begin + content_size) % content_size; } template <typename T> T& TDeque<T>::operator[] (size_t i) const { if (Size() <= i) { // error } return (i + begin) % content_size; }

  35. Implementing TDeque<T> (4) • Display functions template <typename T> void TDeque<T>::Display(ostream& os, char ofc) const { for (size_t j = 0; j < Size(); ++j) { os << operator[](j); if (ofc != ‘\0’) { os << ofc; } } } template <typename T> void TDeque<T>::Dump(ostream& os) const { for (size_t j = 0; j < content_size; ++j) { // print } }

  36. Implementing TDeque<T> (5) • Read-only operator overloads template <typename T> ostream operator<<(ostream& os, const TDeque<T>& Q) { Q.Display(os); return(os); } template <typename T> int operator==(const TDeque<T>& Q1, const TDeque<T>& Q2) { if (Q1.Size() != Q2.Size()) { return 0; } for (size_t j = 0; j < Q1.Size(); ++j) { if (Q1[j] != Q2[j]) { return 0; } } return 1; }

  37. Implementing TDeque<T> (6) • Read-only operator overloads template <typename T> int operator!=(const TDeque<T>& Q1, const TDeque<T>& Q2) { return !(Q1 == Q2); }

  38. Implementing TDeque<T> (7) • Read-only functions template <typename T> int TDeque<T>::Empty() const { return begin == end; } template <typename T> void TDeque<T>::Clear() { begin = end = 0; }

  39. Implementing TDeque<T> (8) • Read-only functions template <typename T> T& TDeque<T>::Front() const { // check for empty TDeque return content[begin]; } template <typename T> T& TDeque<T>::Back() const { // check for empty TDeque return (end – 1 + content_size) % content_size; }

  40. Implementing TDeque<T> (9) • Iterator support template <typename T> TDequeIterator<T> TDeque<T>::Begin() const { TDeque<T>::Iterator I; I.Qptr = this; I.index = 0; return I; } template <typename T> TDequeIterator<T> TDeque<T>::End() const { TDeque<T>::Iterator I; I.Qptr = this; I.index = Size(); return I; }

  41. Implementing TDeque<T> (10) • Assignment template <typename T> TDeque<T>& TDeque<T>::operator=(const TDeque<T>& Q) { if (this != &Q) { T* newcontent = new T[Q.content_size]; // check for allocation delete[] content; content = newcontent; content_size = Q.content_size; begin = Q.begin; end = Q.end; // copy queue elements } return *this; }

  42. Implementing TDeque<T> (11) • PushBack template <typename T> int TDeque<T>::PushBack(const T& Tval) { if (Size() + 1 >= content_size) { // deque is full unsigned j, k; size_t newcontent_size = 2 * content_size; if (content_size == 0) newcontent_size = 2; T* newcontent = new T[newcontent_size]; // check for allocation error for (j = k = begin; j != end; j = (j + 1) % content_size, ++k) { newcontent[k] = content[j]; }

  43. Implementing TDeque<T> (12) • PushBack if (begin < end) { begin += content_size; } delete[] content; content = newcontent; content_size = newcontent_size; } content[end] = Tval; end = (end + 1) % content_size; return 1; }

  44. Implementing TDeque<T> (13) • PushFront template <typename T> int TDeque<T>::PushFront(const T& Tval) { if (Size() + 1 >= content_size) { // deque is full unsigned j, k; size_t newcontent_size = 2 * content_size; if (content_size == 0) newcontent_size = 2; T* newcontent = new T[newcontent_size]; // check for allocation error for (j = k = begin; j != end; j = (j + 1) % content_size, ++k) { newcontent[k] = content[j]; }

  45. Implementing TDeque<T> (14) • PushFront if (begin < end) { begin += content_size; } delete[] content; content = newcontent; content_size = newcontent_size; } begin = (begin – 1 + content_size) % content_size; content[begin] = Tval; return 1; }

  46. Implementing TDeque<T> (15) • Pop routines template <typename T> int TDeque<T>::PopFront() { if (begin == end) return 0; begin = (begin + 1) % content_size; return 1; } template <typename T> int TDeque<T>::PopBack() { if (begin == end) return 0; end = (end – 1 + content_size) % content_size; return 1; }

  47. Implementing TDequeIterator<T> • Constructors template <typename T> TDequeIterator<T>::TDequeIterator() : Qptr(0), index(0) { } template <typename T> TDequeIterator<T>::TDequeIterator(const TDeque<T>& Q) : Qptr(&Q), index(0) { } template <typename T> TDequeIterator<T>::TDequeIterator(const TDequeIterator<T>& I) : Qptr(I.Qptr), index(I.index) { }

  48. Implementing TDequeIterator<T> (2) • Initialization routines template <typename T> void TDequeIterator<T>::Initialize(const TDeque<T>& Q) { Qptr = &Q; index = 0; } template <typename T> void TDequeIterator<T>::rInitialize(const TDeque<T>& Q) { Qptr = &Q; index = Q.Size() – 1; }

  49. Implementing TDequeIterator<T> (3) • Helper functions template <typename T> int TDequeIterator<T>::Valid() const { if (Qptr == 0) return 0; if (index >= Qptr->Size()) return 0; return 1; } template <typename T> T& TDequeIterator<T>::operator[] (size_t i) const { if (!Qptr) { // error } return Qptr->operator[](index + i); }

  50. Implementing TDequeIterator<T> (4) • Helper functions template <typename T> T& TDequeIterator<T>::Retrieve() const { // check for validity return Qptr->operator[](index); } template <typename T> T& TDequeIterator<T>::operator* () const { if (Qptr == 0) { // error } if (Qptr->Size() == 0) { // error } return Qptr->operator[](index); }

More Related