generic positional containers and double-ended queues

53
Generic Positional Containers and Double-Ended Queues

Upload: julian-singleton

Post on 31-Dec-2015

224 views

Category:

Documents


1 download

TRANSCRIPT

Page 1: Generic Positional Containers and Double-Ended Queues

Generic Positional Containers and

Double-Ended Queues

Page 2: Generic Positional Containers and Double-Ended Queues

Generic Positional Containers

A generic container C<T> which is Organized and accessed by position

vector[i] = ‘a’; list.insert(I, ‘a’);

Can insert any T object at any position in C<T> Can remove any T object at any position in C<T> Can support

push_front(), pop_front(), front() push_back(), pop_back(), back()

Examples: List, Deque

Page 3: Generic Positional Containers and Double-Ended Queues

Double-Ended Queue

Deque (pronounced ‘Deck’)

Deque operations Push/Pop at either end Retrieve data from either end Proper type

Page 4: Generic Positional Containers and Double-Ended Queues

Specifying Deque<T>

Requirements for Deque

O(1) average runtime, O(size()) spacepush_front(t), pop_front(), front()push_back(t), pop_back(), back()

O(1) time and space for iterator operations

Random access iterator ([])

Page 5: Generic Positional Containers and Double-Ended Queues

Deque<T> Implementation Plan

Circular array Protected array content of size content_size

Content wraps around the end of the array to the beginning.

Illusion: content[content_size] == content[0]

Page 6: Generic Positional Containers and Double-Ended Queues

Deque<T> D Illustrated

content_size = 8D.empty() == true

0 1 2 3 4 5 6 7

begin

end

content

Page 7: Generic Positional Containers and Double-Ended Queues

Deque<char> D Illustrated (2)

content_size = 8D.push_back(‘M’)

0 1 2 3 4 5 6 7

M

begin end

content

Page 8: Generic Positional Containers and Double-Ended Queues

Deque<char> D Illustrated (3)

content_size = 8D.push_back(‘e’)

0 1 2 3 4 5 6 7

M e

begin end

content

Page 9: Generic Positional Containers and Double-Ended Queues

Deque<char> D Illustrated (4)

content_size = 8D.push_back(‘r’)

0 1 2 3 4 5 6 7

M e r

begin end

content

Page 10: Generic Positional Containers and Double-Ended Queues

Deque<char> D Illustrated (5)

content_size = 8D.push_back(‘r’)

0 1 2 3 4 5 6 7

M e r r

begin end

content

Page 11: Generic Positional Containers and Double-Ended Queues

Deque<char> D Illustrated (6)

content_size = 8D.push_back(‘y’)

0 1 2 3 4 5 6 7

M e r r y

begin end

content

Page 12: Generic Positional Containers and Double-Ended Queues

Deque<char> D Illustrated (7)

content_size = 8D.pop_front()O(1)

0 1 2 3 4 5 6 7

e r r y

begin end

content

Page 13: Generic Positional Containers and Double-Ended Queues

Deque<char> D Illustrated (8)

content_size = 8D.pop_front()

0 1 2 3 4 5 6 7

r r y

begin end

content

Page 14: Generic Positional Containers and Double-Ended Queues

Deque<char> D Illustrated (9)

content_size = 8D.push_back(‘G’)

0 1 2 3 4 5 6 7

r r y G

begin end

content

Page 15: Generic Positional Containers and Double-Ended Queues

Deque<char> D Illustrated (10)

content_size = 8D.push_back(‘o’)D.size() == (7 – 2 + 8) % 8

0 1 2 3 4 5 6 7

r r y G o

begin end

content

Page 16: Generic Positional Containers and Double-Ended Queues

Deque<char> D Illustrated (11)

content_size = 8D.push_back(‘A’)D.size() = (0 – 2 + 8) % 8

0 1 2 3 4 5 6 7

r r y G o A

beginend

content

Page 17: Generic Positional Containers and Double-Ended Queues

Deque<char> D Illustrated (12)

content_size = 8D.push_back(‘r’)D.size() = (1 – 2 + 8) % 8

0 1 2 3 4 5 6 7

r r r y G o A

beginend

content

Page 18: Generic Positional Containers and Double-Ended Queues

Deque<char> D Illustrated (13)

D.size() == content_size – 1Now what?

Return full or Double the capacity (as with Vector).

0 1 2 3 4 5 6 7

r r r y G o A

beginend

content

Page 19: Generic Positional Containers and Double-Ended Queues

Deque<T> Implementation Plan (2)

Relative Indexing Protected integers

begin, end Bracket [] Operator

Similar to Vector Element position relative to begin Front element is content[begin] Back element is content[end – 1]

Size is

(end – begin + content_size) % content_size

Page 20: Generic Positional Containers and Double-Ended Queues

Deque<T>::iterator Implementation Plan

Public interface Start with the public interface of List<T>::iterator

Add bracket operator

Page 21: Generic Positional Containers and Double-Ended Queues

Defining Deque<T>

template <typename T>

class Deque {

public:

typedef T value_type; // type definitions

typedef DequeIterator<T> iterator;

Deque(); // constructors and deconstructor

Deque(size_t, const T&);

Deque(const Deque<T>&);

~Deque();

// display functions

void Display(ostream& os, char ofc = ‘\0’) const;

void Dump(ostream& os) const;

Page 22: Generic Positional Containers and Double-Ended Queues

Defining Deque<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 push_front(const T&); // container write routines

int pop_front();

int push_back(const T&);

int pop_back();

Deque<T>& operator=(const Deque<T>&);

Page 23: Generic Positional Containers and Double-Ended Queues

Defining Deque<T> (3)

friend class DequeIterator<T>; // iterator support

iterator begin() const;

iterator end() const;

protected:

T* content;

size_t content_size, begin, end;

};

Page 24: Generic Positional Containers and Double-Ended Queues

Defining Deque<T> (4)

// operator overloads (friend status not required)

template<class T>

ostream& operator<<(ostream& os, const Deque<T>& a);

template<class T>

int operator==(const Deque<T>&, const Deque<T>&);

template<class T>

int operator!=(const Deque<T>&, const Deque<T>&);

Page 25: Generic Positional Containers and Double-Ended Queues

Defining DequeIterator<T>

template <typename T>

class DequeIterator {

friend class Deque<T>;

public:

typedef T value_type; // terminology support

DequeIterator(); // constructors

DequeIterator(const Deque<T>& I);

DequeIterator(const DequeIterator<T>& I);

DequeIterator(const size_t& i);

T& retrieve() const; // return ptr to current Tval

int valid() const; // cursor is valid element

Page 26: Generic Positional Containers and Double-Ended Queues

Defining DequeIterator<T> (2)

// various operatorsint operator==(const DequeIterator<T>& I2) const;int operator!=(const DequeIterator<T>& I2) const;T& operator*() const; // return reference to current

Tval

T& operator[] (size_t i) const;//return reference to Tval at index+i

DequeIterator<T>& operator=(const DequeIterator<T>& I);DequeIterator<T>& operator++(); // prefixDequeIterator<T> operator++(int); // postfixDequeIterator<T>& operator--(); // prefixDequeIterator<T> operator--(int); // postfix

Page 27: Generic Positional Containers and Double-Ended Queues

Defining DequeIterator<T> (3)

// pointer arithmeticlong operator-(const DequeIterator<T>& I2) const;DequeIterator<T>& operator+=(long n);DequeIterator<T>& operator-=(long n);DequeIterator<T> operator+(long n) const;DequeIterator<T>& operator+=(int n);DequeIterator<T>& operator-=(int n);DequeIterator<T> operator+(int n) const;DequeIterator<T>& operator+=(unsigned long n);DequeIterator<T>& operator-=(unsigned long n);DequeIterator<T> operator+(unsigned long n) const;DequeIterator<T>& operator+=(unsigned int n);DequeIterator<T>& operator-=(unsigned int n);DequeIterator<T> operator+(unsigned int n) const;

Page 28: Generic Positional Containers and Double-Ended Queues

Defining DequeIterator<T> (3)

protected:

const Deque<T>* Qptr;

size_t index;

};

Page 29: Generic Positional Containers and Double-Ended Queues

Implementing Deque<T>

Default constructortemplate <typename T>

Deque<T>::Deque() : content(0), begin(0), end(0), content_size(0) {

content = new T[default_content_size];

if (content == 0) {

// error

}

content_size = default_content_size;

}

Page 30: Generic Positional Containers and Double-Ended Queues

Implementing Deque<T> (2)

Copy constructortemplate <typename T>

Deque<T>::Deque(const Deque<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];

}

}

Page 31: Generic Positional Containers and Double-Ended Queues

Implementing Deque<T> (3)

Read-only functionstemplate <typename T>

size_t Deque<T>::size() const {

return (end – begin + content_size) % content_size;

}

template <typename T>

T& Deque<T>::operator[] (size_t i) const {

if (size() <= i) {

// error

}

return content[(i + begin) % content_size];

}

Page 32: Generic Positional Containers and Double-Ended Queues

Implementing Deque<T> (4)

Display functionstemplate <typename T>void Deque<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 Deque<T>::Dump(ostream& os) const {

for (size_t j = 0; j < content_size; ++j) { // print }}

Page 33: Generic Positional Containers and Double-Ended Queues

Implementing Deque<T> (5)

Read-only operator overloadstemplate <typename T>

ostream operator<<(ostream& os, const Deque<T>& Q) {

Q.Display(os);

return(os);

}

template <typename T>

int operator==(const Deque<T>& Q1, const Deque<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;

}

Page 34: Generic Positional Containers and Double-Ended Queues

Implementing Deque<T> (6)

Read-only operator overloadstemplate <typename T>

int operator!=(const Deque<T>& Q1, const Deque<T>& Q2) {

return !(Q1 == Q2);

}

Page 35: Generic Positional Containers and Double-Ended Queues

Implementing Deque<T> (7)

Read-only functionstemplate <typename T>

int Deque<T>::empty() const {

return begin == end;

}

template <typename T>

void Deque<T>::Clear() {

begin = end = 0;

}

Page 36: Generic Positional Containers and Double-Ended Queues

Implementing Deque<T> (8)

Read-only functionstemplate <typename T>

T& Deque<T>::front() const {

// check for empty Tdeque…

return content[begin];

}

template <typename T>

T& Deque<T>::back() const {

// check for empty Tdeque…

if (end == 0)

return content[content_size - 1];

return content[end - 1];

}

Page 37: Generic Positional Containers and Double-Ended Queues

Implementing Deque<T> (9)

Iterator supporttemplate <typename T>

DequeIterator<T> Deque<T>::begin() const {

Deque<T>::iterator I;

I.Qptr = this;

I.index = 0;

return I;

}

template <typename T>

DequeIterator<T> Deque<T>::end() const {

Deque<T>::iterator I;

I.Qptr = this;

I.index = size();

return I;

}

Page 38: Generic Positional Containers and Double-Ended Queues

Implementing Deque<T> (10)

Assignmenttemplate <typename T>

Deque<T>& Deque<T>::operator=(const Deque<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;

}

Page 39: Generic Positional Containers and Double-Ended Queues

Implementing Deque<T> (11)

push_backtemplate <typename T>

int Deque<T>::push_back(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];

}

Page 40: Generic Positional Containers and Double-Ended Queues

Implementing Deque<T> (12)

push_back

if (end < begin) {end += content_size; }

delete[] content;

content = newcontent;

content_size = newcontent_size;

}

content[end] = Tval;

end = (end + 1) % content_size;

return 1;

}

Page 41: Generic Positional Containers and Double-Ended Queues

Implementing Deque<T> (13)

push_fronttemplate <typename T>

int Deque<T>::push_front(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];

}

Page 42: Generic Positional Containers and Double-Ended Queues

Implementing Deque<T> (14)

push_frontif (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;

}

Page 43: Generic Positional Containers and Double-Ended Queues

Implementing Deque<T> (15)

Pop routinestemplate <typename T>

int Deque<T>::pop_front() {

if (begin == end) return 0;

begin = (begin + 1) % content_size;

return 1;

}

template <typename T>

int Deque<T>::pop_back() {

if (begin == end) return 0;

end = (end – 1 + content_size) % content_size;

return 1;

}

Page 44: Generic Positional Containers and Double-Ended Queues

Implementing DequeIterator<T>

Constructorstemplate <typename T>

DequeIterator<T>::DequeIterator() : Qptr(0), index(0) { }

template <typename T>

DequeIterator<T>::DequeIterator(const Deque<T>& Q) : Qptr(&Q), index(0) { }

template <typename T>

DequeIterator<T>::DequeIterator(const DequeIterator<T>& I) : Qptr(I.Qptr), index(I.index) { }

Page 45: Generic Positional Containers and Double-Ended Queues

Implementing DequeIterator<T> (2)

Initialization routinestemplate <typename T>

void DequeIterator<T>::Initialize(const Deque<T>& Q) {

Qptr = &Q;

index = 0;

}

template <typename T>

void DequeIterator<T>::rInitialize(const Deque<T>& Q) {

Qptr = &Q;

index = Q.size() – 1;

}

Page 46: Generic Positional Containers and Double-Ended Queues

Implementing DequeIterator<T> (3)

Helper functionstemplate <typename T>

int DequeIterator<T>::valid() const {

if (Qptr == 0) return 0;

if (index >= Qptr->size()) return 0;

return 1;

}

template <typename T>

T& DequeIterator<T>::operator[] (size_t i) const {

if (!Qptr) { // error }

return Qptr->operator[](index + i);

}

Page 47: Generic Positional Containers and Double-Ended Queues

Implementing DequeIterator<T> (4)

Helper functionstemplate <typename T>

T& DequeIterator<T>::retrieve() const {

// check for validity

return Qptr->operator[](index);

}

template <typename T>

T& DequeIterator<T>::operator* () const {

if (Qptr == 0) { // error }

if (Qptr->size() == 0) { // error }

return Qptr->operator[](index);

}

Page 48: Generic Positional Containers and Double-Ended Queues

Implementing DequeIterator<T> (5)

Comparatorstemplate <typename T>

int DequeIterator<T>::operator==(const DequeIterator<T>& I2) const {

if (Qptr != I2.Qptr) return 0;

if (index != I2.index) return 0;

return 1;

}

template <typename T>

int DequeIterator<T>::operator!=(const DequeIterator<T>& I2) const {

return !(*this == I2);

}

Page 49: Generic Positional Containers and Double-Ended Queues

Implementing DequeIterator<T> (6)

Assignmenttemplate <typename T>

DequeIterator<T>& DequeIterator<T>::operator=(const DequeIterator<T> & I) {

if (this != &I) {

Qptr = I.Qptr;

index = I.index;

}

return *this;

}

Page 50: Generic Positional Containers and Double-Ended Queues

Implementing DequeIterator<T> (7)

Various operatorstemplate <typename T>

DequeIterator<T>& DequeIterator<T>::operator++() {

++index;

return *this;

}

template <typename T>

DequeIterator<T> DequeIterator<T>::operator++(int) {

DequeIterator<T> I(*this);

operator ++();

return I;

}

Page 51: Generic Positional Containers and Double-Ended Queues

Implementing DequeIterator<T> (8)

Various operatorstemplate <typename T>

DequeIterator<T>& DequeIterator<T>::operator--() {

--index;

return *this;

}

template <typename T>

DequeIterator<T> DequeIterator<T>::operator--(int) {

DequeIterator<T> I(*this);

operator --();

return I;

}

Page 52: Generic Positional Containers and Double-Ended Queues

Implementing DequeIterator<T> (9)

Various operatorstemplate <typename T>

long DequeIterator<T>::operator-(const DequeIterator<T>& I2) const {

return index – I2.index;

}

template <typename T>

DequeIterator<T> DequeIterator<T>::operator+(long n) const {

DequeIterator<T> I(*this);

return I += n;

}

Page 53: Generic Positional Containers and Double-Ended Queues

Implementing DequeIterator<T> (10)

Various operatorstemplate <typename T>

DequeIterator<T>& DequeIterator<T>::operator+=(long n) {

index += n;

return *this;

}

template <typename T>

DequeIterator<T>& DequeIterator<T>::operator-=(long n) {

index -= n;

return *this;

}