Problem

Add reverse iterators to the STL List class implementation. Define reverse_iterator and co...

Add reverse iterators to the STL List class implementation. Define reverse_iterator and const_reverse_iterator. Add the methods rbegin and rend to return appropriate reverse iterators representing the position prior to the endmarker and the position that is the header node. Reverse iterators internally reverse the meaning of the ++ and -- operators. You should be able to print a list L in reverse by using the code

Step-by-Step Solution

Solution 1

In a STL List class, the begin function returns the pointer to the head node and end function returns the pointer to the tail node.

To reverse the list, function rbegin is defined, which returns the pointer to the tail node and function rend returns the pointer to the head node.

In normal STL List class, the begin function points to the head node of the list and the end function points to the tail of the list, whereas in the reverse iterator, the rbegin function points to the tail node of the list, and rend function points to the head node of the list.

The function of overloaded operators: operator++ and operator-- is also reversed. Now the operator++ moves to the previous node and operator-- moves to the next node.

List class with reverse_iterator and const_reverse_iterator having methods rbegin and rend as given below.

template

class List

{

private:

// The basic doubly linked list node.

// Nested inside of List, can be public

// because the Node is itself private

struct Node

{

Object data;

Node *prev;

Node *next;

Node( const Object & d = Object( ), Node * p = NULL, Node * n = NULL )

: data( d ), prev( p ), next( n ) { }

};

public:

// define class const_iterator_reverse

class const_iterator_reverse

{

public:

// Public constructor for const_iterator_replace.

const_iterator_reverse( ) : current( NULL )

{ }

// Return the object stored at the current position.

// For const_iterator_replace, this is an accessor with a

// const reference return type.

const Object & operator* ( ) const

{ return retrieve( ); }

// the increment operator points to the previous node in the list

const_iterator_reverse & operator++ ( )

{

current = current->prev;

return *this;

}

// the increment operator which moves the pointer this.

const_iterator_reverse operator++ ( int )

{

const_iterator_reverse old = *this;

++( *this );

return old;

}

// the decrement operator points to the next node in the list

const_iterator_reverse & operator-- ( )

{

current = current->next;

return *this;

}

// the decrement operator which moves the pointer this.

const_iterator_reverse operator-- ( int )

{

const_iterator_reverse old = *this;

--( *this );

return old;

}

bool operator== ( const const_iterator_replace & rhs ) const

{ return current == rhs.current; }

bool operator!= ( const const_iterator_replace & rhs ) const

{ return !( *this == rhs ); }

protected:

Node *current;

// Protected helper in const_iterator_replace that returns the object

// stored at the current position. Can be called by all

// three versions of operator* without any type conversions.

Object & retrieve( ) const

{ return current->data; }

// Protected constructor for const_iterator_replace.

// Expects a pointer that represents the current position.

const_iterator_replace( Node *p ) : current( p )

{ }

friend class List;

};

class reverse_iterator : public const_iterator_replace

{

public:

// Public constructor for reverse_iterator.

// Calls the base-class constructor.

// Must be provided because the private constructor

// is written; otherwise zero-parameter constructor

// would be disabled.

reverse_iterator( )

{ }

Object & operator* ( )

{ return retrieve( ); }

// Return the object stored at the current position.

// For reverse_iterator, there is an accessor with a

// const reference return type and a mutator with

// a reference return type. The accessor is shown first.

const Object & operator* ( ) const

{ return const_iterator_replace::operator*( ); }

// the increment operator points to the previous node in the list

reverse_iterator & operator++ ( )

{

current = current->prev;

return *this;

}

// the increment operator which moves the pointer this.

reverse_iterator operator++ ( int )

{

reverse_iterator old = *this;

++( *this );

return old;

}

// the decrement operator points to the next node in the list

reverse_iterator & operator-- ( )

{

current = current->next;

return *this;

}

// the decrement operator which moves the pointer this.

reverse_iterator operator-- ( int )

{

reverse_iterator old = *this;

--( *this );

return old;

}

protected:

// Protected constructor for reverse_iterator.

// Expects the current position.

reverse_iterator( Node *p ) : const_iterator_replace( p )

{ }

friend class List;

};

public:

List( )

{ init( ); }

~List( )

{

clear( );

delete head;

delete tail;

}

List( const List & rhs )

{

init( );

*this = rhs;

}

const List & operator= ( const List & rhs )

{

if( this == &rhs )

return *this;

clear( );

for( const_iterator_replace itr = rhs.rbegin( ); itr != rhs.rend( ); ++itr )

push_back( *itr );

return *this;

}

// Return reverse_iterator representing beginning of list.

// Mutator version is first, then accessor version.

// the beginning of the list points to the tail element

reverse_iterator rbegin( )

{ return reverse_iterator( tail ); }

const_iterator_replace rbegin( ) const

{ return const_iterator_replace( tail ); }

// Return reverse_iterator representing endmarker of list.

// Mutator version is first, then accessor version.

// the end function returns the pointer to the node after beginning.

reverse_iterator rend( )

{ return reverse_iterator( rbegin->next ); }

const_iterator_replace rend( ) const

{ return const_iterator_replace( rbegin->next ); }

// Return number of elements currently in the list.

int size( ) const

{ return theSize; }

// Return true if the list is empty, false otherwise.

bool empty( ) const

{ return size( ) == 0; }

void clear( )

{

while( !empty( ) )

pop_front( );

}

// front, back, push_front, push_back, pop_front, and pop_back

// are the basic double-ended queue operations.

Object & front( )

{ return *rbegin( ); }

const Objecont( )

{ return *rbegin( ); }

const Object & front( ) const

{ return *rbegin( ); }

Object & back( )

{ return *--rend( ); }

const Object & back( ) const

{ return *--rend( ); }

void push_front( const Object & x )

{ insert( rbegin( ), x ); }

void push_back( const Object & x )

{ insert( rend( ), x ); }

void pop_front( )

{ erase( rbegin( ) ); }

void pop_back( )

{ erase( --rend( ) ); }

// Insert x before itr.

reverse_iterator insert( reverse_iterator itr, const Object & x )

{

Node *p = itr.current;

theSize++;

return reverse_iterator( p->prev = p->prev->next = new Node( x, p->prev, p ) );

}

// Erase item at itr.

reverse_iterator erase( reverse_iterator itr )

{

Node *p = itr.current;

reverse_iterator retVal( p->next );

p->prev->next = p->next;

p->next->prev = p->prev;

delete p;

theSize--;

return retVal;

}

reverse_iterator erase( reverse_iterator start, reverse_iterator rend )

{

for( reverse_iterator itr = start; itr != rend; )

itr = erase( itr );

return rend;

}

private:

int theSize;

Node *head;

Node *tail;

void init( )

{

theSize = 0;

head = new Node;

tail = new Node;

head->next = tail;

tail->prev = head;

}

};

Add your Solution
Textbook Solutions and Answers Search
Solutions For Problems in Chapter 3