Advanced Data Structures and Algorithmsnadeem/classes/cs361-F13/materials/Lec-04_List.pdf · Page 7...

94
Advanced Data Structures and Algorithms CS 361 - Fall 2013 Tamer Nadeem Dept. of Computer Science Lec. #04: List Structures

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 3 Fall 2013 CS 361 - Advanced Data Structures and Algorithms

Class Templates

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 6 Fall 2013 CS 361 - Advanced Data Structures and Algorithms

Container Iterator

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 17 Fall 2013 CS 361 - Advanced Data Structures and Algorithms

STL list Container in C++

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 43 Fall 2013 CS 361 - Advanced Data Structures and Algorithms

List Implementation

Page 44 Fall 2013 CS 361 - Advanced Data Structures and Algorithms

Single Linked List

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 56 Fall 2013 CS 361 - Advanced Data Structures and Algorithms

Variations of Linked List

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 61 Fall 2013 CS 361 - Advanced Data Structures and Algorithms

miniList Class

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

Page 94 Fall 2013 CS 361 - Advanced Data Structures and Algorithms

Questions?