Advanced Data Structures and Algorithmsnadeem/classes/cs361-F13/materials/Lec-04_List.pdf · Page 7...
Transcript of Advanced Data Structures and Algorithmsnadeem/classes/cs361-F13/materials/Lec-04_List.pdf · Page 7...
Advanced Data Structures and Algorithms
�CS 361 - Fall 2013 �
Tamer Nadeem �Dept. of Computer Science�
Lec. #04: List Structures
Page 2 Fall 2013 CS 361 - Advanced Data Structures and Algorithms
Class Objective/Overview
• Understand List Container
• Understand Container Iterator
• Understand C++ STL list Container
• Understand Single Linked List Implementation
• Understand Variations of Linked List Implementation
• Familiarize with The miniList Class
Page 4 Fall 2013 CS 361 - Advanced Data Structures and Algorithms
List Container
• A Vector is a sequence container that uses array to store its element
• Data occupy contagious memory locations • An index is used to access data directly
• A Vector has serious limitations for frequent insertion and deletion of intermediate elements.
• Shifting of large blocks of data à O(n)
• List container is another sequence container alternative to Vector.
Page 5 Fall 2013 CS 361 - Advanced Data Structures and Algorithms
List Container
• List is efficient in adding and deleting at any position.
• List doesn’t provide an index for direct access of elements.
• Use Iterators.
• Each element in a list contains links to the next and the preceding items. • List items are laid in a row • First element is called
front while the last element is called back.
• To locate an element, a sequential scan is needed • Starting at front and moving forward • Staring at back and moving backward.
front back
Page 7 Fall 2013 CS 361 - Advanced Data Structures and Algorithms
Iterators
• An iterator is an object that accesses the elements in a list in their positional order.
• “locator” that slide back and forth. • access the value of an element at any position • Move one position at a time
• An iterator is a generalized pointer • Dereference operator (*) accesses the value of the element referenced by the
iterator
• The C++ standard library containers (data structures) supply iterator interfaces, which makes them convenient to use and interoperable with the standard algorithms.
Page 8 Fall 2013 CS 361 - Advanced Data Structures and Algorithms
Iterator Operators
*: Accesses the value of the item currently pointed to by the iterator.
*iter; ++: Moves the iterator to the next item in the list.
iter++;
--: Moves the iterator to the previous item in the list. iter--;
==: Takes two iterators as operands and returns true when they both point at the same item in the list.
iter1 == iter2 !=: Returns true when the two iterators do not point at the
same item in the list. iter1 != iter2
Page 9 Fall 2013 CS 361 - Advanced Data Structures and Algorithms
Iterators
• A sequential container in C++ has begin() method that returns an iterator that points to the beginning of the list
• Also, it has end() methods to return iterator that points just one past the last (back) element
• not “the last element” • That’s necessary to elegantly represent an empty sequence • One-past-the-last-element isn’t an element
• You can compare an iterator pointing to it • You can’t dereference it (read its value)
• Returning the end of the sequence is the standard idiom for “not found” or “unsuccessful”
0 1 2 3
the end: An empty sequence: some
iterator:
Page 10 Fall 2013 CS 361 - Advanced Data Structures and Algorithms
Iterators
• Typical iterator interface class iterator { public : typedef std::forward_iterator_tag iterator_category ; typedef T value_type ; typedef ptrdiff _t difference_type ; typedef T* pointer ; typedef T& reference ; iterator ( ) ; // Get the data element at this position reference operator*( ) const ; pointer operator->() const ; // Move position forward 1 place iterator& operator ++( ) ; iterator operator++( int ) ; // Comparison operators bool operator== ( const iterator&) const ; bool operator != ( const iterator&) const ; T* pos; ... } ;
Page 11 Fall 2013 CS 361 - Advanced Data Structures and Algorithms
Iterators
• Implementation of iterator interface
iterator::iterator() ; pos(0) { } iterator::reference iterator::operator* ( ){ return *pos; } iterator::pointer iterator::operator->(){ return pos; } iterator& iterator::operator++(){ //prefix ++iter pos = pos++; return *this; } iterator iterator::operator++(int){ //postfix iter++ iterator oldValue = *this ; pos = pos++; return oldValue ; }
bool iterator::operator==(iterator right) { return pos == right.pos; } bool iterator::operator!=(iterator right) { return pos != right.pos; }
Page 12 Fall 2013 CS 361 - Advanced Data Structures and Algorithms
Iterators
• Declaration and Usage: A container iterator is implemented as a nested class iterator within the declaration of its container.
• Declaration of an iterator object must include the class name iterator along with the scope operator ‘::’ of the container class (e.g., C::iterator)
• Constant Iterators: Iterators for use with objects of type const <object> or const <object>& are called const_iterator.
• const_iterator never allow the programmer to store or change a value at the iterator position, only to look at that value.
// list iterator declaration miniVector<T>::iterator iter; miniVector<int>::iterator intIter;
template <typename T> miniVector<T>:: const_iterator search (const miniVector<T>& v, T x) { for (miniVector<T>:: const_iterator iter = v.begin(); iter != v.end(); ++iter){ if (x == *iter) return iter; } return v.end(); }
Page 13 Fall 2013 CS 361 - Advanced Data Structures and Algorithms
Iterators
• An iterator should allow its consumers to: • Move to the beginning of the range of elements • Advance to the next element • Return the value referred to, often called the referent • Interrogate it to see if it is at the end of the range
• The C++ standard library provides iterators for the standard containers (for example, list, vector, deque, and so on) and a few other noncontainer classes. You can use an iterator to print the contents of, for example, a vector like this:
miniVector<int> v; // fill up v with data... for (miniVector<int>::iterator it = v.begin(); it != v.end(); ++it)
{ cout << *it << endl;
}
Page 14 Fall 2013 CS 361 - Advanced Data Structures and Algorithms
Iterators • begin() and end()
implementation
template <class T> miniVector<T>::iterator miniVector<T>::begin( ){ miniVector<T>::iterator iter; iter.pos = vArr; return iter; } ; template <class T> miniVector<T>::const_iterator miniVector<T>::begin( ) const{ miniVector<T>::const_iterator iter; iter.pos = vArr; return iter; } ; template <class T> miniVector<T>::iterator miniVector<T>::end( ){ miniVector<T>::iterator iter; iter.pos = vArr+vSize; return iter; } ; template <class T> miniVector<T>::const_iterator miniVector<T>::end( ) const{ miniVector<T>::iterator iter; iter.pos = vArr+vSize; return iter;} ;
Page 15 Fall 2013 CS 361 - Advanced Data Structures and Algorithms
Iterators • Sequential search implementation
template <class T> miniVector<T>::iterator miniVector<T>::seqSearch(miniVector<T>::iterator first, miniVector<T>::iterator last, const T& target){ // start at location first miniVector<T>::iterator iter = first; // compare list elements with target until either // we arrive at last or locate target while(iter != last && (*iter != target)) iter++; // iter either points at target or is last return iter; };
Page 16 Fall 2013 CS 361 - Advanced Data Structures and Algorithms
Iterators
• Variations of Iterators • The interface we developed previously is called forward iterator
• we can move forward through a container, but never backwards • operator++() and operator++(int)
• An obvious extension is to allow iterator to move backwards as well. It is called bidirectional iterator
• operator++() and operator++(int) • operator--() and operator--(int)
• Random Access Iterator allow us to move any integer number of places in addition to typical one position.
iterator operator+ (ptrdiff_t k) const; // Get a new iterator k positions past this one.
Page 18 Fall 2013 CS 361 - Advanced Data Structures and Algorithms
std::list - Constructors Create an empty list. This is the default constructor.
Create a list with n elements, each having a specified value. If no value argument is omitted, the elements are filled with the default value for type T. Type T must have a default constructor, and the default value of type T is specified by the notation T().
Initialize the list, using the address range [first, last).
list();
explicit list(size_type n, const T& value = T());
template <class InputIterator> list(InputIterator first, InputIterator last);
list(const list<T>& x); Copy constructor. Initialize the list using another list “x”.
Page 19 Fall 2013 CS 361 - Advanced Data Structures and Algorithms
std::list - Constructors
Example:
The contents of fifth are: 16 2 77 29 Output:
Page 20 Fall 2013 CS 361 - Advanced Data Structures and Algorithms
std::list - Copying
list<T>& operator=(const list<T>& x);
template <class InputIterator> void assign(InputIterator first, InputIterator last);
void assign(size_type n, const T& val);
Assigns new contents to the container, replacing its current contents, and modifying its size accordingly
Replace the current contents of the list container with n elements, each initialized to a copy of val, and modifying its size accordingly
Replace the current contents of the list container with the new elements constructed from each of the elements in the range between first and last, in the same order, and modifying its size accordingly
Page 21 Fall 2013 CS 361 - Advanced Data Structures and Algorithms
std::list - Copying
Example:
Size of first: 3 Size of second: 7
Output:
Page 22 Fall 2013 CS 361 - Advanced Data Structures and Algorithms
std::list - Capacity
int size() const; Return the number of elements in the list.
size_type max_size() const; Return the number of elements in the list.
void resize(size_type sz, T c = T()); Add or remove elements, as necessary, at the end of the list to make it have exactly n elements. If elements need to be added, the value of the new elements will be c.
bool empty () const; Returns whether the list container is empty
Page 23 Fall 2013 CS 361 - Advanced Data Structures and Algorithms
std::list - Capacity
Example:
mylist contains: 1 2 3 4 5 100 100 100 0 0 0 0 Output:
Page 24 Fall 2013 CS 361 - Advanced Data Structures and Algorithms
std::list – Accessing Elements
T& front(); const T& front();
Return the value of the item at the front of the list. Precondition: The vector must contain at least one element.
T& back(); const T& back();
Return the value of the item at the rear of the list. Precondition: The vector must contain at least one element.
Page 25 Fall 2013 CS 361 - Advanced Data Structures and Algorithms
std::list – Accessing Elements
iterator begin(); const_iterator begin();
Returns an iterator/const_terator that references the first position (front) of the list. If the list is empty, the iterator value end() is returned.
iterator end(); const_iterator end();
Returns an iterator or const_iterator that signifies a location immediately out of the range of actual elements. A program must not dereference the value of end() with the * operator.
Use a constant iterator to access and scan a constant list. Use a non-constant iterator to access and scan a non-
constant list
Page 26 Fall 2013 CS 361 - Advanced Data Structures and Algorithms
std::list – Access Interior Elements
list<string> names ; . . . for (list<string>::iterator pos = names.begin( ); pos != names.end( ); ++pos) { cout << "One of the names is " << *pos << endl ; }
Interior elements are accessed via iterators , which follow the usual C++ conventions. For example, a typical loop through an entire list looks like:
Or, in C++11: list<string> names ; . . . for (string aNames: names) { cout << "One of the names is " << *pos << endl ; }
Page 27 Fall 2013 CS 361 - Advanced Data Structures and Algorithms
std::list – Accessing Elements
Example:
mylist contains: 75 23 65 42 13 Output:
Page 28 Fall 2013 CS 361 - Advanced Data Structures and Algorithms
std::list - Insertion void push_back(const T& x);
Add a value at the rear of the list. Postcondition: The list has a new element at the rear, and its size increases by 1.
iterator insert(iterator position, const T& x);
Insert value x at position, and return an iterator pointing to the position of the new value in the list. The operation does not affect any existing iterators. Postcondition: The list has a new element.
void push_front (const T& x); Add a value at the front of the list. Postcondition: The list has a new element at the front, and its size increases by 1.
Page 29 Fall 2013 CS 361 - Advanced Data Structures and Algorithms
std::list - Insertion
void insert (iterator position, size_type n, const T& x);
template <class InputIterator> void insert (iterator position, InputIterator first, InputIterator last);
Copies of the elements in the range [first,last) are inserted at position
Insert n values of x starting at position. Postcondition: The list has n new elements.
Page 30 Fall 2013 CS 361 - Advanced Data Structures and Algorithms
std::list - Insertion Example:
mylist contains: 1 10 20 30 30 20 2 3 4 5 Output:
Page 31 Fall 2013 CS 361 - Advanced Data Structures and Algorithms
std::list - Deletion void pop_back();
Remove the item at the rear of the list. Precondition: The list is not empty. Postcondition: The list has a new element at the rear or is empty.
iterator erase(iterator position); Erase the element pointed to by position. Return iterator pointing to the new location of the element that followed the last element erased Precondition: The list is not empty. Postcondition: The list has one fewer element.
void pop_front (); Remove the item at the front of the list. Precondition: The list is not empty. Postcondition: The list has a new element at the front or is empty.
Page 32 Fall 2013 CS 361 - Advanced Data Structures and Algorithms
std::list - Deletion
iterator erase (iterator first, iterator last); Erase all elements specified by the range [first,last). Return iterator pointing to the new location of the element that followed the last element erased Precondition: The list is not empty and has range of elements identified by [first,last). Postcondition: The list has fewer set of elements specified by the range [first,last).
void remove (const value_type& val); Removes from the container all the elements that compare equal to val. This calls the destructor of these objects and reduces the container size by the number of elements removed.
void clear (); Removes all elements.
Page 33 Fall 2013 CS 361 - Advanced Data Structures and Algorithms
std::list - Deletion Example:
mylist contains: 10 30 60 80 90 Output:
Page 34 Fall 2013 CS 361 - Advanced Data Structures and Algorithms
std::list - Splicing
// entire list void splice (iterator position, list& x); // single element void splice (iterator position, list& x, iterator i); // element range void splice (iterator position, list& x, iterator first, iterator last);
Transfers elements from x into the container, inserting them at position. Inserted elements are removed from x, altering the sizes of both containers.
7 15 16 3 47 15 3 47 3 4destList
15 16
sourceIter
sourceList pos
5destList (After insert of 15)
15 16
sourceIter
sourceList pos
5destList (After insert of 16)
15 16
sourceIter
sourceList pos
5
Page 35 Fall 2013 CS 361 - Advanced Data Structures and Algorithms
std::list - Splicing
Example:
mylist1 contains: 30 3 4 1 10 20 mylist2 contains: 2
Output:
Page 36 Fall 2013 CS 361 - Advanced Data Structures and Algorithms
std::list – Misc Functions
void unique(); Removes all but the first element from every consecutive group of equal elements in the container.
void merge (list& x); Merges x into the list by transferring all of its elements at their respective ordered positions into the container Precondition: both containers shall already be ordered.
void sort(); Sorts the elements in the list in ascending order, altering their position within the container. Postcondition: elements are ordered in ascending order.
void reverse(); Reverses the order of the elements in the list container.
Page 37 Fall 2013 CS 361 - Advanced Data Structures and Algorithms
std::list – Misc Functions
Example:
mylist contains: 9 8 7 6 5 4 3 2 1 Output:
Page 38 Fall 2013 CS 361 - Advanced Data Structures and Algorithms
The Standard list namespace std { template <class T> class list { public : typedef T& reference ; typedef const T& const_reference ; typedef . . . iterator ; typedef . . . const_iterator ; typedef . . . size_type ; typedef . . . difference_type ; typedef T value_type ; typedef T* pointer ; typedef const T* const_pointer typedef std::reverse_iterator <iterator> reverse_iterator ; typedef std::reverse_i terator <const_iterator> const_reverse_iterator ; // construct / copy / destroy : explicitlist (const Allocator& = Allocator ()) ; explicitlist ( size_type n, const T& value = T ( ) ) ; template <class InputIterator > list (InputIterator first , InputIterator last ) ;
Page 39 Fall 2013 CS 361 - Advanced Data Structures and Algorithms
The Standard list list (const list<T>& x ) ; ~list( ) ; list <T>& operator=(const list <T>& x ) ; template <class InputIterator > void assign (InputIterator first , InputIterator last) ; void assign ( size_type n, const T& t ) ; // iterators : iterator begin ( ) ; const_iterator begin ( ) const ; iterator end ( ) ; const_iterator end( ) const ; reverse_iterator rbegin ( ) ; const_reverse_iterator rbegin ( ) const ; reverse_iterator rend ( ) ; const_reverse_iterator rend ( ) const ; // _lib.list.capacity_capacity : bool empty ( ) const ; size_type size ( ) const ; size_type max_size ( ) const ; void res ize ( size_type sz , T c = T ( ) ) ;
Page 40 Fall 2013 CS 361 - Advanced Data Structures and Algorithms
The Standard list // element access: reference front ( ) ; const_reference front ( ) const ; reference back ( ) ; const_reference back ( ) const ; // _lib.list.modifiers_ modifiers : void push_front ( const T& x ) ; void pop_front ( ) ; void push_back ( const T& x ) ; void pop_back ( ) ; iterator insert (iterator position, const T& x ) ; void insert (iterator position , size_type n, const T& x ) ; template <class Input I terator > void insert (iterator position , InputIterator first , InputIterator last) ; iterator erase (iterator position) ; iterator erase (iterator position, iterator last ) ; void swap(list <T>&); void clear ( ) ;
Page 41 Fall 2013 CS 361 - Advanced Data Structures and Algorithms
The Standard list // _l ib.list.ops_ list operations : void splice (iterator position , list <T>& x ) ; void splice (iterator position , list <T>& x , iterator i ) ; void splice (iterator position , list <T>& x , iterator first , iterator last ) ; void remove( const T& value ) ; template <class Predicate > void remove_if ( Predicate pred ) ; void unique ( ) ; template <class BinaryPredicate > void unique ( BinaryPredicate binary_pred ) ; void merge( list <T>& x ) ; template <class Compare> void merge( list <T>& x , Compare comp) ; void sort ( ) ; template <class Compare> void sort (Compare comp) ; void reverse ( ) ; } ;
Page 42 Fall 2013 CS 361 - Advanced Data Structures and Algorithms
The Standard list template <class T> bool operator==(const list <T>& x , const list <T>& y ) ; template <class T> bool operator< ( const list <T>& x , const list <T>& y ) ; template <class T> bool operator> ( const list <T>& x , const list <T>& y ) ; template <class T> bool operator >=(const list <T>& x , const list <T>& y ) ; template <class T> bool operator <=(const list <T>& x , const list <T>& y ) ; // specialized algorithms : template <class T, class Allocator > void swap( list <T>& x , list <T>& y ) ; }
Page 45 Fall 2013 CS 361 - Advanced Data Structures and Algorithms
Linked List
• Linked lists store each element in a distinct node.
• Nodes are linked by pointers. • Accessing elements by number is slow and
awkward • Easy to insert things into the middle
Individual Piece Pop Chain
Page 46 Fall 2013 CS 361 - Advanced Data Structures and Algorithms
Linked List Nodes
• Each node provides a data field and a next pointer.
template <typename T> class node { public : T data ; node<T>* next ; node ( ) : next ( nullptr) { } node ( const T& item, node<T>* nextNode = nullptr ) :
data ( item) , next (nextNode ) { } } ;
nodeValue
next
nodeValue nextdata
data
Page 47 Fall 2013 CS 361 - Advanced Data Structures and Algorithms
Coding for Linked Lists
template <class Data> class LList{ public: LList ( ) ; . . . private: node<Data>* front; //or head // node<Data>* current; // node<Data>* prev; . . . } ;
We need two data types to build a linked list: • The linked list node, which we have already looked at • and a header for the entire list:
Page 48 Fall 2013 CS 361 - Advanced Data Structures and Algorithms
Traversing Linked List
• We can move from node to node by tracing the pointers. node<string> *current = front ; // assuming that head points
// to the f i r s t node while ( current != nullptr ) { doSomethingWith ( current->data ) ; current = current->next ; // move forward one step }
• or for (node<string > *current = front ; current != nullptr ; current = current->next ) { doSomethingWith ( current->data ) ; }
data
Page 49 Fall 2013 CS 361 - Advanced Data Structures and Algorithms
Inserting into Linked List
• We insert by working from the node prior to the insertion point:
// Insert value after node p // node<string> *newNode = new node<string>; newNod->data = value; newNode->next = p->link ; p->next= newNode;
l To insert a new link, break the chain at the desired location and simply reconnect at both ends of the new piece.
Disconnect
Reconnect
p
newNode
Page 50 Fall 2013 CS 361 - Advanced Data Structures and Algorithms
Removing from Linked List
• We delete by moving the previous pointer "around" the unwanted node:
// Remove value after node p // node<string> *q = p->next ; p->next = q->next ; delete q;
l Removal is like Insertion in reverse.
Disconnect
p q
Reconnect
q
p
next
front
target
prev curr
// //
p q
Page 51 Fall 2013 CS 361 - Advanced Data Structures and Algorithms
Inserting at Front of Linked List • We insert by working from the node prior to the insertion point:
// Insert value after node p // node<string> *newNode = new node<string>; newNod->data = value; newNode->next = front; front = newNode;
front
front
Before
(a)
item
newNode
After
back data (b)
20
front
Before
front
55
20item
front
After
front
55data
Page 52 Fall 2013 CS 361 - Advanced Data Structures and Algorithms
Deleting from Front of Linked List • We insert by working from the node prior to the insertion point:
// Insert value after node p // if (front){ node<string> *q = front; front = front->next; delete q; }
Page 53 Fall 2013 CS 361 - Advanced Data Structures and Algorithms
Searching a Linked List
// Remove element elm from the list (if exist) Template <class Data> Void LList::removeElement(const Data& elm) { node<Data> *current = front; node<Data> *prev = nullptr; while ( current != nullptr &&
current->data != elm) { prev = current; current = current->next; } if ( current != nullptr ) { // We found the author we were looking for . if (prev != nullptr) // node found not front { prev->next = current->next ; }
else // node found is front { front = current->next; } delete current; // delete found node } }
Page 54 Fall 2013 CS 361 - Advanced Data Structures and Algorithms
Add to end of Linked List
// Add “elm” to end of the linked list Template <class Data> Void LList::addToEnd(const Data& elm) { node<Data> *newNode = new node<Data>(elm, nullptr); node<Data> *current = front; if (front == nullptr) front = newNode; else { while ( current ->next != nullptr) current = current->next; current->next = newNode; } }
Page 55 Fall 2013 CS 361 - Advanced Data Structures and Algorithms
Add to an Ordered Linked List // Add “elm” to an ordered linked list Template <class Data> Void LList::addInOrder(const Data& elm) { node<Data> *newNode = new node<Data>(elm, nullptr); node<Data> *current = front; node<Data> *prev = nullptr; if (front == nullptr) front = newNode; else { while ( current != nullptr && current->data < elm) { prev = current; current = current->next; } newNode->next = current; if (prev == nullptr) front = newNode; else prev->next = newNode; } }
Page 57 Fall 2013 CS 361 - Advanced Data Structures and Algorithms
Front & Back Linked List • Single linked list does not efficiently handle operations at the back of
the list
• Alternative approach: define a second pointer called back pointing to the end of list
... //
item
newNode
front
back
// data
• Empty list à (front==nullptr && back==nullptr)
Node<Data> *front, *back, *mewNode; newNode = new node<Data>(elm,nullptr); if (front != nullptr) back->next = newNode; else front = newNode; back = newNode;
Page 58 Fall 2013 CS 361 - Advanced Data Structures and Algorithms
Front & Back Linked List • Single linked list does not efficiently handle operations at the back of
the list
• Alternative approach: define a second pointer called back pointing to the end of list
... //
item
newNode
front
back
// data
• Empty list à (front==nullptr && back==nullptr) // Node<Data> *front, *back; Node<Data> *newNode; newNode = new node<Data>(elm,nullptr); if (front != nullptr) back->next = newNode; else front = newNode; back = newNode;
Page 59 Fall 2013 CS 361 - Advanced Data Structures and Algorithms
Doubly-Linked List • By modifying the node structure:
• Move backwards as well as forward in the list • by following the prev pointers
• Easily add in front of a node
template <typename Data> struct dnode { Data data; dnode<Data>* prev; dnode<Data>* next; dnode() {next = prev = 0;} dnode (const Data& d, dnode<Data>* prv = 0,
dnode<Data>* nxt = 0) : data(d), next(nxt), prev(prv)
{} };
front:
back:
Page 60 Fall 2013 CS 361 - Advanced Data Structures and Algorithms
addBefore: Singly vs. Doubly-Linked List
• Let’s compare the problem of adding a value in front of a known position using both single and doubly linked lists.
template <typename Data> void LList<Data>::addBefore
(node<Data>* beforeThis , const Data& value )
{ if ( beforeThis == front ) addToFront ( value ) ; else { // Move to front of beforeThis node<Data>* current = front; while ( current->next != beforeThis ) current = current¡>next ; // Link after that node addAfter ( current , value ) ; } }
Singly linked template <typename Data> Void DLList<Data >::addBefore
(dnode<Data>* beforeThis , const Data& value )
{ if ( beforeThis == front ) addToFront ( value ) ; else { // Move to front of beforeThis dnode<Data>* current =
beforeThis->prev; // Link after that node addAfter ( current , value ) ; } }
Doubly linked
O(n) O(1)
Page 62 Fall 2013 CS 361 - Advanced Data Structures and Algorithms
miniList Class
#ifndef LIST_CLASS #define LIST_CLASS #include <iostream> #include <string> #include "d_dnode.h" // dnode class #include "d_except.h" // exception classes using namespace std; template <typename T> class miniList { public: // include the iterator nested classes #include "d_liter.h”
Page 63 Fall 2013 CS 361 - Advanced Data Structures and Algorithms
miniList Class miniList(); // constructor. create an empty list miniList(int n, const T& item = T()); // constructor. build a list with n elements, all having // the value item miniList(T* first, T* last); // constructor. build a list whose data comes from the // pointer range [first, last) miniList(const miniList<T>& obj); // copy constructor
~miniList();
// destructor miniList<T>& operator= (const miniList<T>& rhs);
// overloaded assignment operator int size() const;
// return the size of the list bool empty() const;
// is the list empty
Page 64 Fall 2013 CS 361 - Advanced Data Structures and Algorithms
miniList Class void push_front(const T& item); // insert item at the front of the list // Postcondition: the list size increases by 1 void push_back(const T& item); // insert item at the back of the list // Postcondition: the list size increases by 1 iterator insert(iterator pos, const T& item); // insert item before pos. // Postcondition: the list size increases by 1
void pop_front(); // erase the front of the list. // Precondition: the list is not empty. if the list is // empty, the function throws the
underflowError exception. // Postcondition: the list size decreases by 1 void pop_back(); // erase the back of the list. // Precondition: the list is not empty. if the list is // empty, the function throws the
underflowError exception. // Postcondition: the list size decreases by 1
Page 65 Fall 2013 CS 361 - Advanced Data Structures and Algorithms
miniList Class void erase(iterator pos); // erase the list element at pos // Precondition: the list is not empty. if the list is // empty, the function throws the
underflowError exception. // Postcondition: the list size decreases by 1
T& front(); // return a reference to the value at the
front of the list. // Precondition: the list is not empty. if the list is // empty, the function throws the
underflowError exception const T& front() const; // constant version of front() T& back(); // return a reference to the value at the
back of the list. // Precondition: the list is not empty. if the list is // empty, the function throws the
underflowError exception
Page 66 Fall 2013 CS 361 - Advanced Data Structures and Algorithms
miniList Class
const T& back() const; // constant version of back()iterator begin(); // return an iterator pointing at the first node in the list // or end() if the list is empty
const_iterator begin() const; // constant version of begin()
iterator end();
// return an iterator pointing just past the last node of // the list
const_iterator end() const; // constant version of end()
private: // header (sentinel) node dnode<T> *header; // number of elements in the list int listSize;
Page 67 Fall 2013 CS 361 - Advanced Data Structures and Algorithms
miniList Class
dnode<T> *getDNode(const T& item); // allocate a dnode object with the value item and // return a pointer to it. throw the memoryAllocationError // exception of the memory allocation fails
dnode<T> *dinsert(dnode<T> *curr, const T& item); // insert item before node curr of the linked list and // return the address of the new node
void derase(dnode<T> *curr); // erase node curr from the linked list. // Precondition: the list is not empty. the functions that // call derase() check the precondition
};
Page 68 Fall 2013 CS 361 - Advanced Data Structures and Algorithms
miniList Class
template <typename T> dnode<T> *miniList<T>::getDNode(const T& item) {
// pointer to the new node dnode<T> *newNode;
// allocate the new node and verify that the // allocation succeeded newNode = new dnode<T>(item); if (newNode == NULL) throw memoryAllocationError("miniList(): memory allocation failure"); // return the address of the new node return newNode;
} template <typename T> dnode<T> *miniList<T>::dinsert(dnode<T> *curr, const T& item) {
// allocate the new node dnode<T> *newNode = getDNode(item);
Page 69 Fall 2013 CS 361 - Advanced Data Structures and Algorithms
miniList Class
// insert newNode before curr newNode->prev = curr->prev; newNode->next = curr; curr->prev->next = newNode; curr->prev = newNode;
return newNode;
} template <typename T> void miniList<T>::derase(dnode<T> *curr) {
// unlink the node from the list curr->prev->next = curr->next; curr->next->prev = curr->prev;
// delete the node delete curr;
}
Page 70 Fall 2013 CS 361 - Advanced Data Structures and Algorithms
miniList Class // list size is 0 template <typename T> miniList<T>::miniList(): listSize(0) {
// create an empty list header = new dnode<T>; if (header == NULL) throw memoryAllocationError("miniList(): memory allocation
failure"); } // list size is n template <typename T> miniList<T>::miniList(int n, const T& value): listSize(n) {
int i;
// create an empty list header = new dnode<T>; if (header == NULL) throw memoryAllocationError ("miniList(): memory allocation failure");
Page 71 Fall 2013 CS 361 - Advanced Data Structures and Algorithms
miniList Class // insert n copies of value at the front of the list for (i=0;i < n;i++) dinsert(header->next, value);
} // initialize listSize to 0 template <typename T> miniList<T>::miniList(T* first, T* last): listSize(0) {
T *curr = first;
// create an empty list header = new dnode<T>; if (header == NULL) throw memoryAllocationError("miniList(): memory allocation failure");
// insert the values in the range [first, last) at the // back of the list. increment listSize in each iteration while (curr != last) { dinsert(header, *curr); curr++; listSize++; }
}
Page 72 Fall 2013 CS 361 - Advanced Data Structures and Algorithms
miniList Class template <typename T> miniList<T>::miniList(const miniList<T>& obj): listSize(obj.listSize) {
// curr moves through the nodes in obj, and end marks the finish // of a traversal through obj dnode<T> *curr = obj.header->next, *end = obj.header;
// create an empty list header = new dnode<T>; if (header == NULL) throw memoryAllocationError ("miniList(): memory allocation failure");
// insert the values in the linked list obj.header // at the back of the current list while (curr != end) { dinsert(header, curr->nodeValue); curr = curr->next; }
}
Page 73 Fall 2013 CS 361 - Advanced Data Structures and Algorithms
miniList Class template <typename T> miniList<T>::~miniList() {
// erase the front of the list until it is empty while (header->next != header) derase(header->next);
// the list has no nodes listSize = 0;
// delete the header node delete header;
} template <typename T> miniList<T>& miniList<T>::operator=(const miniList<T>& rhs) {
// curr moves through the nodes in rhs, and end marks the finish // of a traversal through rhs dnode<T> *curr = rhs.header->next, *end = rhs.header;
Page 74 Fall 2013 CS 361 - Advanced Data Structures and Algorithms
miniList Class // can't assign list to itself if (this == &rhs)
return *this;
// erase the current list while (header->next != header) derase(header->next);
// insert the elements of rhs at the back of the list while (curr != end) { dinsert(header, curr->nodeValue); curr = curr->next; }
// list size is the size of rhs listSize = rhs.listSize;
return *this; }
Page 75 Fall 2013 CS 361 - Advanced Data Structures and Algorithms
miniList Class template <typename T> int miniList<T>::size() const {
return listSize; } template <typename T> bool miniList<T>::empty() const {
return listSize == 0; } template <typename T> void miniList<T>::push_front(const T& item) {
// insert at the front dinsert(header->next, item);
// increment the list size listSize++;
}
Page 76 Fall 2013 CS 361 - Advanced Data Structures and Algorithms
miniList Class template <typename T> void miniList<T>::push_back(const T& item) {
// insert at the back dinsert(header, item);
// increment the list size listSize++;
} template <typename T> typename miniList<T>::iterator miniList<T>::insert(iterator pos, const T& item) {
// record the current node's address in curr. newNode will be // the address of the node we insert dnode<T> *curr = pos.nodePtr, *newNode;
// insert item before curr and capture the new node's address newNode = dinsert(curr, item);
// increment the list size listSize++;
Page 77 Fall 2013 CS 361 - Advanced Data Structures and Algorithms
miniList Class
// constructor converts newNode to an iterator return iterator(newNode);
} template <typename T> void miniList<T>::pop_front() {
if (listSize == 0) throw underflowError("miniList pop_front(): list is empty");
// erase the front derase(header->next);
// decrement the list size listSize--;
}
Page 78 Fall 2013 CS 361 - Advanced Data Structures and Algorithms
miniList Class template <typename T> void miniList<T>::pop_back() {
if (listSize == 0) throw underflowError("miniList pop_back(): list is empty");
// erase the back derase(header->prev);
// decrement the list size listSize--;
} template <typename T> void miniList<T>::erase(iterator pos) {
if (listSize == 0) throw underflowError("miniList erase(): list is empty");
// retrieve the address of the node to be erased dnode<T> *curr = pos.nodePtr;
Page 79 Fall 2013 CS 361 - Advanced Data Structures and Algorithms
miniList Class // erase the node from the list derase(curr);
// decrement the list size listSize--;
} template <typename T> T& miniList<T>::front() {
if (listSize == 0) throw underflowError("miniList front(): list is empty");
return header->next->nodeValue;
} template <typename T> const T& miniList<T>::front() const {
if (listSize == 0) throw underflowError("miniList front(): list is empty");
Page 80 Fall 2013 CS 361 - Advanced Data Structures and Algorithms
miniList Class return header->next->nodeValue;
} template <typename T> T& miniList<T>::back() {
if (listSize == 0) throw underflowError("miniList back(): list is empty");
return header->prev->nodeValue;
} template <typename T> const T& miniList<T>::back() const {
if (listSize == 0) throw underflowError("miniList back(): list is empty");
return header->prev->nodeValue;
}
Page 81 Fall 2013 CS 361 - Advanced Data Structures and Algorithms
miniList Class // note that in each of begin() and end(), a // private iterator/const_iterator constructor converts // the pointer into an iterator template <typename T> typename miniList<T>::iterator miniList<T>::begin() {
// private iterator constructor builds an iterator object // from the dnode pointer return iterator(header->next);
} template <typename T> typename miniList<T>::const_iterator miniList<T>::begin() const {
// private constructor builds a const_iterator object // from the dnode pointer return const_iterator(header->next);
}
Page 82 Fall 2013 CS 361 - Advanced Data Structures and Algorithms
miniList Class
template <typename T> typename miniList<T>::iterator miniList<T>::end() {
// private constructor builds an iterator object // from the dnode pointer return iterator(header);
} template <typename T> typename miniList<T>::const_iterator miniList<T>::end() const {
// private constructor builds a const_iterator object // from the dnode pointer return const_iterator(header);
} #endif // LIST_CLASS
Page 83 Fall 2013 CS 361 - Advanced Data Structures and Algorithms
dnode Class (d_dnode.h)
#ifndef DOUBLY_LINKED_NODE_CLASS #define DOUBLY_LINKED_NODE_CLASS template <typename T> class dnode {
public: // the members of a dnode object are used for operations within a // doubly linked list; access is simplified by making them public
T nodeValue; // data value of the node
dnode<T> *prev; // previous node in the list dnode<T> *next; // next node in the list
// default constructor. creates object with value T(), the // default value of type T. set the node pointers to point at // the node itself
dnode() { next = this; // the next node is the current node prev = this; // the previous node is the current node }
Page 84 Fall 2013 CS 361 - Advanced Data Structures and Algorithms
dnode Class (d_dnode.h)
// constructor with an argument to initialize nodeValue.
// set the node pointers to point at the node itself dnode(const T& value): nodeValue(value)
{ next = this; // the next node is the current node prev = this; // the previous node is the current node }
}; #endif // DOUBLY_LINKED_NODE_CLASS
Page 85 Fall 2013 CS 361 - Advanced Data Structures and Algorithms
Iterator Class (d_liter.h)
#ifndef MINILIST_ITERATOR_CLASSES #define MINILIST_ITERATOR_CLASSES // these classes do not stand alone. the miniList // class includes this file in its public section // necessary so iterator classes can access private section // of miniList class iterator; class const_iterator; friend class iterator; friend class const_iterator; // miniList class iterator implementation class iterator { public: friend class miniList<T>;
Page 86 Fall 2013 CS 361 - Advanced Data Structures and Algorithms
Iterator Class (d_liter.h)
// needed by the const_iterator constructor // that converts a const iterator to a const_iterator friend class const_iterator; // constructor iterator() {} // equality for iterators bool operator== (const iterator& rhs) const { // iterators equal if they point to same node return nodePtr == rhs.nodePtr; } // inequality for iterators bool operator!= (const iterator& rhs) const { // iterators unequal if they point to different nodes return nodePtr != rhs.nodePtr; }
Page 87 Fall 2013 CS 361 - Advanced Data Structures and Algorithms
Iterator Class (d_liter.h)
// pointer dereference operator T& operator* () { // if the node's successor is itself, the list is empty if (nodePtr->next == nodePtr) throw referenceError("miniList iterator: reference error"); return nodePtr->nodeValue; } // prefix increment. move forward one node iterator& operator++ () {
// move to the successor of nodePtr nodePtr = nodePtr->next;
return *this; // return new iterator value }
Page 88 Fall 2013 CS 361 - Advanced Data Structures and Algorithms
Iterator Class (d_liter.h)
// postfix increment. move forward one node iterator operator++ (int) {
// save the current value of the iterator iterator tmp = *this;
// move to the successor of nodePtr nodePtr = nodePtr->next; return tmp; // return original iterator value } // prefix decrement. move back one node iterator& operator-- () {
// move to the predecessor of nodePtr nodePtr = nodePtr->prev;
return *this; // return new iterator value }
Page 89 Fall 2013 CS 361 - Advanced Data Structures and Algorithms
Iterator Class (d_liter.h)
// postfix decrement. move back one node iterator operator-- (int) {
// save the current value of the iterator iterator tmp = *this;
// move to the predecessor of nodePtr nodePtr = nodePtr->prev; return tmp; // return original iterator value } private: // pointer to the current list node dnode<T> *nodePtr;
// private constructor. converts p to an iterator // by assigning p to nodePtr iterator(dnode<T> *p): nodePtr(p) {}
};
Page 90 Fall 2013 CS 361 - Advanced Data Structures and Algorithms
Iterator Class (d_liter.h)
// type is const_iterator, the list referred to is // constant and * returns a constant reference class const_iterator { public: friend class miniList<T>; const_iterator() {} // converts const iterator --> const_iterator const_iterator(const iterator& obj) { nodePtr = obj.nodePtr; } bool operator== (const const_iterator& rhs) const { return nodePtr == rhs.nodePtr; }
Page 91 Fall 2013 CS 361 - Advanced Data Structures and Algorithms
Iterator Class (d_liter.h) bool operator!= (const const_iterator& rhs) const { return nodePtr != rhs.nodePtr; } const T& operator* () const { // if the node's successor is itself, the list
// is empty if (nodePtr->next == nodePtr) throw
referenceError("miniList iterator: reference error"); return nodePtr->nodeValue; } // prefix increment. move forward one node const_iterator& operator++ () {
// move to the successor of nodePtr nodePtr = nodePtr->next;
Page 92 Fall 2013 CS 361 - Advanced Data Structures and Algorithms
Iterator Class (d_liter.h) return *this; // return new iterator value } // postfix increment. move forward one node const_iterator operator++ (int) {
// save the current value of the iterator const_iterator tmp = *this;
// move to the successor of nodePtr nodePtr = nodePtr->next; return tmp; // return original iterator value } // prefix decrement. move back one node const_iterator& operator-- () {
// move to the predecessor of nodePtr nodePtr = nodePtr->prev;
return *this; // return new iterator value }
Page 93 Fall 2013 CS 361 - Advanced Data Structures and Algorithms
Iterator Class (d_liter.h)
// postfix decrement. move forward one node const_iterator operator-- (int) {
// save the current value of the iterator const_iterator tmp = *this;
// move to the predecessor of nodePtr nodePtr = nodePtr->prev; return tmp; // return original iterator value } private: dnode<T> *nodePtr;
// converts a dnode pointer to an const_iterator const_iterator(dnode<T> *p): nodePtr(p) {}
}; #endif // MINILIST_ITERATOR_CLASSES