Download presentation
Presentation is loading. Please wait.
Published byΕυάριστος Κοντόσταυλος Modified over 6 years ago
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
TDeque<T> D Illustrated
content_size = 8 D.Empty() == true 1 2 3 4 5 6 7 content begin end
9
TDeque<char> D Illustrated (2)
content_size = 8 D.PushBack(‘M’) 1 2 3 4 5 6 7 M content begin end
10
TDeque<char> D Illustrated (3)
content_size = 8 D.PushBack(‘e’) 1 2 3 4 5 6 7 M e content begin end
11
TDeque<char> D Illustrated (4)
content_size = 8 D.PushBack(‘r’) 1 2 3 4 5 6 7 M e r content begin end
12
TDeque<char> D Illustrated (5)
content_size = 8 D.PushBack(‘r’) 1 2 3 4 5 6 7 M e r content begin end
13
TDeque<char> D Illustrated (6)
content_size = 8 D.PushBack(‘y’) 1 2 3 4 5 6 7 M e r y content begin end
14
TDeque<char> D Illustrated (7)
content_size = 8 D.PopFront() O(1) 1 2 3 4 5 6 7 e r y content begin end
15
TDeque<char> D Illustrated (8)
content_size = 8 D.PopFront() 1 2 3 4 5 6 7 r y content begin end
16
TDeque<char> D Illustrated (9)
content_size = 8 D.PushBack(‘G’) 1 2 3 4 5 6 7 r y G content begin end
17
TDeque<char> D Illustrated (10)
content_size = 8 D.PushBack(‘o’) D.Size() == (7 – 2 + 8) % 8 1 2 3 4 5 6 7 r y G o content begin end
18
TDeque<char> D Illustrated (11)
content_size = 8 D.PushBack(‘A’) D.Size() = (0 – 2 + 8) % 8 1 2 3 4 5 6 7 r y G o A content begin end
19
TDeque<char> D Illustrated (12)
content_size = 8 D.PushBack(‘r’) 1 2 3 4 5 6 7 r y G o A content begin end
20
TDeque<char> D Illustrated (13)
D.Size() == content_size – 1 Return full or Double the capacity 1 2 3 4 5 6 7 r y G o A content begin end
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); int operator==(const TDeque<T>&, const TDeque<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; } 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; } 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); } 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; } 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]; } T& TDeque<T>::Back() const { 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; } TDequeIterator<T> TDeque<T>::End() const { I.index = Size();
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; } int TDeque<T>::PopBack() { end = (end – 1 + content_size) % content_size;
47
Implementing TDequeIterator<T>
Constructors template <typename T> TDequeIterator<T>::TDequeIterator() : Qptr(0), index(0) { } TDequeIterator<T>::TDequeIterator(const TDeque<T>& Q) : Qptr(&Q), index(0) { } 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; } void TDequeIterator<T>::rInitialize(const TDeque<T>& 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; } 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); } T& TDequeIterator<T>::operator* () const { if (Qptr == 0) { // error } if (Qptr->Size() == 0) { // error }
51
Implementing TDequeIterator<T> (5)
Comparators template <typename T> int TDequeIterator<T>::operator==(const TDequeIterator<T>& I2) const { if (Qptr != I2.Qptr) return 0; if (index != I2.index) return 0; return 1; } int TDequeIterator<T>::operator!=(const TDequeIterator<T>& I2) const { return !(*this == I2);
52
Implementing TDequeIterator<T> (6)
Assignment template <typename T> TDequeIterator<T>& TDequeIterator<T>::operator=(const TDequeIterator<T> & I) { if (this != &I) { Qptr = I.Qptr; index = I.index; } return *this;
53
Implementing TDequeIterator<T> (7)
Various operators template <typename T> TDequeIterator<T>& TDequeIterator<T>::operator++() { ++index; return *this; } TDequeIterator<T> TDequeIterator<T>::operator++(int) { TDequeIterator<T> I(*this); operator ++(); return I;
54
Implementing TDequeIterator<T> (8)
Various operators template <typename T> TDequeIterator<T>& TDequeIterator<T>::operator--() { --index; return *this; } TDequeIterator<T> TDequeIterator<T>::operator--(int) { TDequeIterator<T> I(*this); operator --(); return I;
55
Implementing TDequeIterator<T> (9)
Various operators template <typename T> long TDequeIterator<T>::operator-(const TDequeIterator<T>& I2) const { return index – I2.index; } TDequeIterator<T> TDequeIterator<T>::operator+(long n) const { TDequeIterator<T> I(*this); return I += n;
56
Implementing TDequeIterator<T> (10)
Various operators template <typename T> TDequeIterator<T>& TDequeIterator<T>::operator+=(long n) { index += n; return *this; } TDequeIterator<T>& TDequeIterator<T>::operator-=(long n) { index -= n;
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.