Download as ppt, pdf, or txt
Download as ppt, pdf, or txt
You are on page 1of 150

1

IMPORTANT PROBLEMS
OF COMPUTER SCIENCE

Search
&
Sort

2
WHAT ARE SOME OF THE IMPORTANT
PROBLEMS?

• THE most important and most frequent task a


computer does ALL THE TIME is
– Searching
• The next most important thing is probably
– Sorting

3
SEARCHING
• Simple version
– Given a set of objects S, and a query object x, is x in
S?
• Complex version
– Given a set of objects S, and a partial information
about an object X, is there a set element which is
similar to X in some sense?

4
CONSIDERATIONS

• The size of the set (N)


• The range of the values of the set elements
– All real numbers
– Integers in the range 0-199
– Pictures
– Arbitrary complex data structures (e.g., student
transcripts, phone bills)

5
CONSIDERATIONS

• How static is the set?


– Static
• we construct it once and then ask questions; the set
does not change afterwards (at least for a long time)
– e.g. student database
– Dynamic
• the set keeps on changing; we insert new elements
and delete old elements all the time
– e.g. List of bank accounts in a bank

6
CONSIDERATIONS

• How much time are we willing to wait?


– O(N) MAY be sometimes acceptable when N is
“small”, but N is usually very large!
– So unless N is small, O(N) time is NOT ACCEPTABLE!

7
CONSIDERATIONS

• How much time are we willing to wait?


– O( log N): usually this is very acceptable.
– log N is a very slow growing function of N, so even
for large N this is fast!
• N = 1000 log N  10
• N = 1,000,000 log N  20
• N= 1,000,000,000 log N  30
– Note that the base of the logarithm does not
matter! (Why?)

8
CONSIDERATIONS
• How much time are we willing to wait?
– O(1): Constant time: very good- can’t do any better
– but may not be desirable for other reasons (e.g.,
may require additional memory)

9
CONSIDERATIONS
• How much time are we willing to wait for
insertions and deletions?
– You may want to wait long for insertions and
deletions
– but want the find operations to be fast!

10
CONSIDERATIONS
• How much (additional) memory can we use?
(Additional to the set itself)
– None (not really “none” but constant additional
memory)
– O(N) additional memory (constant additional
memory per item stored)

11
HOW TO COMPARE?
• Equality
– Is X in S?
• Functional relationship
– Is there an element Y such that F(Y) = X?
• Is there a student (Y) with LastName(Y)=“Öztürk”?
• List all students (Ys) with GPA(Y) = 3.00

12
HOW TO COMPARE?
• Inequality
– Is there an element larger than X?
– Is there an element NOT equal to X?
– Is there an element between X and Y?

13
HOW TO COMPARE?
• Closeness
– What is/are the element(s) “closest” to X?
– What elements are at most “distance” y away
from X?

14
HOW TO COMPARE?

• Closeness
– What is/are the element(s) “closest” to X?
• What are the “correct” versions of the misspelled
words
– iktapalrdaik (kitaplardaki)
– evdaki (avdaki, evdeki)
– Çekoslovakyalılaştırabilemediklerimizdenmişsinizcesine

15
HOW TO COMPARE?
• Closeness
– What is/are the element(s) “closest” to X?
• What are the “correct” versions of the misspelled words
– iktapalrdaik (kitaplardaki)
– evdaki (avdaki, evdeki)
– Çekoslovakyalılaştırabilemediklerimizdenmişsinizcesine
– What is the Turkish sentence closest in meaning to
“Ben var şiş kebap yemek”?
• Ben şiş kebap yedim

16
HOW TO COMPARE?
• Closeness
– Find 6 letter words whose first letter is a and whose
last letter is m?

– What is the word whose meaning is “el tezgahında


bez dokuyan kimse”?

17
WHAT IF S IS INFINITE?
• How can we search infinite sets?
– S is the set of possible sentences in Turkish
– X is a sentence
– Is X a sentence in Turkish?
• Set S is implicitly defined (over a universe of
objects)
– All Y’s with a certain property are in S
– Find if X has that property?

18
WHAT IF COMPARISON IS NOT EASY?

• Find 6 letter words whose first letter is a and


whose last letter is m?
– alaşım, atılım, aküzüm, alaçam, anonim, arıtım,...

• What is the word whose meaning is “el


tezgahında bez dokuyan kimse”? (çulha)

19
WHAT IF COMPARISON IS NOT EASY?

• Whose fingerprint is
this?

• Whose face is this?

• Whose eye is this?

20
LESSON
• All life is searching ()

• Searching is a VERY complicated problem.


– Humans are very good at some search problems
– Not so good in others

• We will look at some very simple data


structures for some searching problems.
21
LINEAR DATA STRUCTURES

LISTS, STACKS and QUEUES

22
ABSTRACT DATA TYPES
• Contrary to common conception,
– writing programs is not really about writing a
sequence of statements,

–but rather it is
about organizing
your data. 23
ABSTRACT DATA TYPES
• Contrary to common conception,
– writing programs is not really about writing a
sequence of statements,
– but rather it is about organizing your data. (Never
forget this!)

• An abstract data type ADT is a conceptual


specification of the behaviour of a data
structure.
24
ABSTRACT DATA TYPES
• An abstract data type ADT is a conceptual
specification of the behaviour of a data
structure.
• We are not interested in the representation of
the data (yet)
• It is the type of the data that
determines its behaviour.
25
ABSTRACT DATA TYPES
• An abstract data type ADT is a conceptual
specification of the behaviour of a data
structure.
• We are not interested in the representation of
the data (yet)
• It is the type of the data that determines its
behaviour.
• Representation does NOT determine behaviour.

26
REPRESENTATION VS TYPE

32 bit binary data Representation

Non-negative integers Integers Real numbers

Type
27
REPRESENTATION VS TYPE

Pair of Real numbers Representation

Complex Numbers 2-D Vectors X-Y Coordinates

Type
28
REPRESENTATION VS TYPE

• Type determines what you can do!


– Complex numbers
• Add, Subtract, Multiply, Divide
• Modulus, Angle, Conjugate
• ez, cos z, sin z...
– 2D-Vectors
• Add, Subtract,
• Dot product, modulus, angle, scale

29
REPRESENTATION VS TYPE

Array of n reals Representation

Polynomials of degree n-1 n-D Vectors n-sample points

Type
30
REPRESENTATION VS TYPE
• Type determines what you can do!
– Polynomials of degree n
• Add, Subtract, Divide, Multiply, Evaluate, Differentiate,
Integrate, Find Roots,...
– n-D vectors
• Add, Subtract, Dot Product,...
– n-sample points
• Average, standard deviation ...

31
REPRESENTATION VS TYPE
• A given ADT may be based on different
representations.
• Sets: intersect, union, size, membership...
• Representations (which themselves can be
ADTs)
– Bit Vectors
– Hash Tables
– Linked Lists
– Trees
– ....
32
ADTS VS OBJECTS
• Objects (as in C++) are convenient mechanisms
for implementing ADTs in programming
languages.

• But ... One does not necessarily need an object


oriented programming language to implement
ADTs.
• Using ADTs is a matter of
discipline!
33
LINKED LISTS
• A linked list is an ordered sequence of data
items: A1, A2, A3, .... , AN
– An empty list has no elements
– For any list except the empty list
• A i+1 follows or succeeds Ai (i < N )
• A i-1 precedes Ai (i > 1)
– Ai is at position i
– Data items Ai can be any type.
– In general, the (maximum) number of elements, N, is
not known in advance! 34
POINTERS
• Assumed to be covered in the recitations

35
LINKED LISTS
Tail (of the list)

A1 A2 A3

First Element
(Head) Pointers to the next element in the list

... AN—1 AN

Last Element
Null pointer
36
LINKED LISTS
Deleting an element

A1 A2 A3 A4 A5

A1 A2 A3 A4 A5

37
LINKED LISTS
Deleting an element

A1 A2 A3 A4 A5

A1 A2 A4 A5

A3

38
LINKED LISTS
Deleting an element

A1 A2 A3 A4 A5

A1 A2 A4 A5

A3

39
LINKED LISTS
Inserting an element

A1 A2 A3 A4 A5

Insertion point A6

40
LINKED LISTS
Inserting an element

A1 A2 A3 A4 A5

A6

41
LINKED LISTS
Inserting an element

A1 A2 A3 A4 A5

A6

42
LINKED LISTS
Inserting an element

A1 A2 A6 A3 A4

A5

43
LINKED LISTS

Linked Lists with dummy header nodes

A1 A2 A6 A3

A4
The methods are a bit easier to write.

A5

44
LINKED LISTS
LISTNODE CLASS
A1
template <class Object>
class List; // Incomplete declaration.

template <class Object>


class ListItr; // Incomplete declaration.

template <class Object>


class ListNode
{
ListNode( const Object & theElement = Object( ), ListNode * n = NULL )
: element( theElement ), next( n ) { } // Constructor

Object element;
ListNode *next;

friend class List<Object>;


friend class ListItr<Object>;
};
45
LINKED LISTS
LISTNODE CLASS
A1
template <class Object>
class List; // Incomplete declaration.

template <class Object>


class ListItr; // Incomplete declaration.

template <class Object>


class ListNode
{
ListNode( const Object & theElement = Object( ), ListNode * n = NULL )
: element( theElement ), next( n ) { } // Constructor

Object element; // Private data fields


ListNode *next;

friend class List<Object>;


friend class ListItr<Object>;
};
46
LINKED LISTS
LISTNODE CLASS
template <class Object>
class List; // Incomplete declaration.

template <class Object>


class ListItr; // Incomplete declaration.

template <class Object>


class ListNode
{
ListNode( const Object & theElement = Object( ), ListNode * n = NULL )
: element( theElement ), next( n ) { } // Constructor

Object element; // Private data fields


ListNode *next;

friend class List<Object>; // Other objects that can


friend class ListItr<Object>; // access the private fields
};
47
friends of a class
• friend class List<Object>;
• friend class ListItr<Object>;

• The methods of a class which is declared to be a


friend of another class can access the private
data/methods of that class.

• The methods of classes List<Object> and


ListItr<Object> can access element and next directly.

48
friends of a class
• But this is a one way access.

• The class declaring other classes as its friends


can not access their private data!

• The two incomplete declarations were made


just to be able to use the friend functionality.

49
LINKED LISTS
LISTNODE CLASS

template <class Object>


class List; // Incomplete declaration.
So the compiler at least
knows that
template <class Object>
class ListItr; // Incomplete declaration.
List and ListItr are
some kind of classes.
template <class Object>
class ListNode
{
ListNode( const Object & theElement = Object( ), ListNode * n = NULL )
: element( theElement ), next( n ) { }

Object element;
ListNode *next;

friend class List<Object>;


friend class ListItr<Object>;
};
50
CLASS TEMPLATES

template <class Object>


class ListNode
{
ListNode( const Object & theElement = Object( ),

ListNode * n = NULL )
: element( theElement ), next( n ) { }

Object element;
ListNode *next;

friend class List<Object>;


friend class ListItr<Object>;
};

51
LISTNODE STORING A DATE

class DateListNode
{
...

Date element;
DateListNode *next;

...
};

52
LISTNODE STORING A RECTANGLE

class RectangleListNode
{
...

Rectangle element;
RectangleListNode *next;

...
};

53
LISTNODE STORING A CIRCLE

class CircleListNode
{
...

Circle element;
CircleListNode *next;

...
};

54
CLASS TEMPLATES
template <class Object>
class ListNode A template
{ parameter is a
ListNode( const Object & theElement = Object( ), ListNode * n = NULL ) special kind of
: element( theElement ), next( n ) { }
parameter that
Object element; can be used to
ListNode *next; pass a type as
friend class List<Object>;
argument: just like
friend class ListItr<Object>; regular function
}; parameters can be
ListNode<Date> node; // automatically creates the following class used to pass
class ListNode values to a
{ function
ListNode( const Date & theElement = Date( ), ListNode * n = NULL )
: element( theElement ), next( n ) { } It represents a
Date element;
type that has not
ListNode *next; yet been specified

friend class List<Date>;


friend class ListItr<Date>;
55
};
CLASS TEMPLATES
template <class Object>
class ListNode
{
ListNode( const Object & theElement = Object( ), ListNode * n = NULL )
: element( theElement ), next( n ) { }

Object element;
ListNode *next;

friend class List<Object>;


friend class ListItr<Object>;
};

ListNode<Rectangle> node; // automatically creates the following class

class ListNode
{
ListNode( const Rectangle & theElement = Rectangle( ), ListNode * n = NULL )
: element( theElement ), next( n ) { }

Rectangle element;
ListNode *next;

friend class List<Rectangle>;


friend class ListItr<Rectangle>;
}; 56
CLASS TEMPLATES
template <class Object>
class ListNode
{
ListNode( const Object & theElement = Object( ), ListNode * n = NULL )
: element( theElement ), next( n ) { }

Object element;
ListNode *next;

friend class List<Object>;


friend class ListItr<Object>;
};

ListNode<Circle> node; // automatically creates the following class

class ListNode
{
ListNode( const Circle & theElement = Circle( ), ListNode * n = NULL )
: element( theElement ), next( n ) { }

Circle element;
ListNode *next;

friend class List<Circle>;


friend class ListItr<Circle>;
}; 57
LIST ITERATOR
template <class Object>
The list iterator is an object
class ListItr
{
that keeps track of list
public: positions
ListItr( ) : current( NULL ) { }
bool isPastEnd( ) const
{ return current == NULL; }
void advance( )
{ if ( ! isPastEnd( ) ) current = current->next; }
const Object & retrieve( ) const
{ if ( isPastEnd( ) ) throw BadIterator( );
return current->element; }

private:
ListNode<Object> *current; // Current position
ListItr( ListNode<Object> *theNode )
: current( theNode ) { }

friend class List<Object>; // Grant access to constructor


58
};
LIST ITERATOR
template <class Object> The list iterator is an object
class ListItr that keeps track of list
{
positions
public:
ListItr( ) : current( NULL ) { }
bool isPastEnd( ) const
{ return current == NULL; }
void advance( )
{ if ( ! isPastEnd( ) ) current = current->next; }
const Object & retrieve( ) const
{ if ( isPastEnd( ) ) throw BadIterator( );
return current->element; }

private:
ListNode<Object> *current; // Current position

ListItr( ListNode<Object> *theNode )


: current( theNode ) { }
friend class List<Object>; // Grant access to constructor 59
};
LIST ITERATOR
template <class Object>
class ListItr
{ Checks if the position is at
public: the end of a list
ListItr( ) : current( NULL ) { }
bool isPastEnd( ) const
{ return current == NULL; }
void advance( )
{ if( !isPastEnd( ) ) current = current->next; }
const Object & retrieve( ) const
{ if( isPastEnd( ) ) throw BadIterator( );
return current->element; }
private:
ListNode<Object> *current; // Current position

ListItr( ListNode<Object> *theNode )


: current( theNode ) { }

friend class List<Object>; // Grant access to constructor


}; 60
LIST ITERATOR
template <class Object>
class ListItr
{ Checks if the position is at the end of
public: a list
ListItr( ) : current( NULL ) { }
bool isPastEnd( ) const
{ return current == NULL; }
Moves to the next position in the list if
void advance( ) not at the end
{ if ( ! isPastEnd( ) )
current = current->next; }
const Object & retrieve( ) const
{ if( isPastEnd( ) ) throw BadIterator( );
return current->element; }

private:
ListNode<Object> *current; // Current position

ListItr( ListNode<Object> *theNode )


: current( theNode ) { }

friend class List<Object>; // Grant access to constructor


}; 61
LIST ITERATOR
template <class Object>
class ListItr Checks if the position is at the end of
{ a list
public:
ListItr( ) : current( NULL ) { }
bool isPastEnd( ) const
Moves to the next position in the list if
{ return current == NULL; } not at the end
void advance( )
{ if( !isPastEnd( ) ) current = current->next; }
const Object & retrieve( ) const
{ if ( isPastEnd( ) ) Returns a reference to the
throw BadIterator( ); object at the current
return current->element; } position
private:
ListNode<Object> *current; // Current position

ListItr( ListNode<Object> *theNode )


: current( theNode ) { }
friend class List<Object>; // Grant access to constructor
};
62
LIST ITERATOR
template <class Object> Checks if the position is at the end
class ListItr of a list
{
public:
ListItr( ) : current( NULL ) { }
bool isPastEnd( ) const Moves to the next position in the list if
{ return current == NULL; } not at the end
void advance( )
{ if( !isPastEnd( ) ) current = current->next; }
const Object & retrieve( ) const
{ if( isPastEnd( ) ) throw BadIterator( ); Returns a reference to the object
return current->element; } at the current position

private:
ListNode<Object> *current; // Current position

ListItr( ListNode<Object> *theNode )


: current( theNode ) { } Private constructor

friend class List<Object>; // Grant access to constructor


};
63
LISTS
template <class Object>
class List
{
public:
List( );
List( const List & rhs );
~List( );
bool isEmpty( ) const;
void makeEmpty( );
ListItr<Object> zeroth( ) const;
ListItr<Object> first( ) const;
void insert( const Object & x, const ListItr<Object> & p );
ListItr<Object> find( const Object & x ) const;
ListItr<Object> findPrevious( const Object & x ) const;
void remove( const Object & x );

const List & operator=( const List & rhs );

private:
ListNode<Object> *header; 64
};
(Back to) LISTS
template <class Object>
class List
{
public:
List( );
List( const List & rhs );
~List( );
bool isEmpty( ) const;
void makeEmpty( );
ListItr<Object> zeroth( ) const;
ListItr<Object> first( ) const;
void insert( const Object & x, const ListItr<Object> & p );
ListItr<Object> find( const Object & x ) const;
ListItr<Object> findPrevious( const Object & x ) const;
void remove( const Object & x );

const List & operator=( const List & rhs );

private:
ListNode<Object> *header;
}; 65
LISTS
template <class Object>
class List
{
public:
List( );
List( const List & rhs );
~List( );
bool isEmpty( ) const;
void makeEmpty( );
ListItr<Object> zeroth( ) const;
ListItr<Object> first( ) const;
void insert( const Object & x, const ListItr<Object> & p );
ListItr<Object> find( const Object & x ) const;
ListItr<Object> findPrevious( const Object & x ) const;
void remove( const Object & x );

const List & operator=( const List & rhs );

private:
ListNode<Object> *header; 66
};
LISTS
template <class Object>
class List
{
public:
List( );
List( const List & rhs );
~List( );
bool isEmpty( ) const;
void makeEmpty( );
ListItr<Object> zeroth( ) const;
ListItr<Object> first( ) const;
void insert( const Object & x, const ListItr<Object> & p );
ListItr<Object> find( const Object & x ) const;
ListItr<Object> findPrevious( const Object & x ) const;
void remove( const Object & x );

const List & operator=( const List & rhs );

private:
ListNode<Object> *header;
}; 67
LISTS
template <class Object>
class List
{
public:
List( );
List( const List & rhs );
~List( );
bool isEmpty( ) const;
void makeEmpty( );
ListItr<Object> zeroth( ) const;
ListItr<Object> first( ) const;
void insert( const Object & x, const ListItr<Object> & p );
ListItr<Object> find( const Object & x ) const;
ListItr<Object> findPrevious( const Object & x ) const;
void remove( const Object & x );

const List & operator=( const List & rhs );

private:
ListNode<Object> *header;
}; 68
LISTS
template <class Object>
class List
{
public:
List( );
List( const List & rhs );
~List( );
bool isEmpty( ) const;
void makeEmpty( );
ListItr<Object> zeroth( ) const;
ListItr<Object> first( ) const;
void insert( const Object & x, const ListItr<Object> & p );
ListItr<Object> find( const Object & x ) const;
ListItr<Object> findPrevious( const Object & x ) const;
void remove( const Object & x );

const List & operator=( const List & rhs );

private:
ListNode<Object> *header;
}; 69
LISTS
template <class Object>
class List
{
public:
List( );
List( const List & rhs );
~List( );
bool isEmpty( ) const;
void makeEmpty( );
ListItr<Object> zeroth( ) const;
ListItr<Object> first( ) const;
void insert( const Object & x, const ListItr<Object> & p );
ListItr<Object> find( const Object & x ) const;
ListItr<Object> findPrevious( const Object & x ) const;
void remove( const Object & x );

const List & operator=( const List & rhs );

private:
ListNode<Object> *header;
}; 70
LISTS
template <class Object>
class List
{
public:
List( );
List( const List & rhs );
~List( );
bool isEmpty( ) const;
void makeEmpty( );
ListItr<Object> zeroth( ) const;
ListItr<Object> first( ) const;
void insert( const Object & x, const ListItr<Object> & p );
ListItr<Object> find( const Object & x ) const;
ListItr<Object> findPrevious( const Object & x ) const;
void remove( const Object & x );
const List & operator=( const List & rhs );

private:
ListNode<Object> *header;
}; 71
LISTS
template <class Object>
class List
{
public:
List( );
List( const List & rhs );
~List( );
bool isEmpty( ) const;
void makeEmpty( );
ListItr<Object> zeroth( ) const;
ListItr<Object> first( ) const;
void insert( const Object & x, const ListItr<Object> & p );
ListItr<Object> find( const Object & x ) const;
ListItr<Object> findPrevious( const Object & x ) const;
void remove( const Object & x );

const List & operator=( const List & rhs );


private:
ListNode<Object> *header;
}; 72
CONSTRUCTOR

/**
* Construct the list.
*/
template <class Object>
List<Object>::List( )
{
header = new ListNode<Object>;
}

73
isEmpty
/**
* Test if the list is logically empty.
* Return true if empty, false, otherwise.
*/
template <class Object>
bool List<Object>::isEmpty( ) const
{
// see if the header points to NULL
return header–>next == NULL;
}

Returns true (1) if the header->next has value NULL (=0)

74
insert
/**
* Insert item x after p.
*/
template <class Object>
void List<Object>::insert( const Object & x, const ListItr<Object> & p )
{
if ( p.current != NULL )
p.current->next = new ListNode<Object>( x, p.current->next );
}

p.current insert here

A1 A2 A3 A4

X
75
find

/**
* Return iterator corresponding to the first node containing an item x.
* Iterator isPastEnd if item is not found.
*/
template <class Object>
ListItr<Object> List<Object>::find( const Object & x ) const
{
ListNode<Object> *itr = header->next; // Initialize

while ( itr != NULL && itr->element != x )


itr = itr->next;

return ListItr<Object>( itr );


}

76
find

/**
* Return iterator corresponding to the first node containing an item x.
* Iterator isPastEnd if item is not found.
*/
template <class Object>
ListItr<Object> List<Object>::find( const Object & x ) const
{
ListNode<Object> *itr = header->next; // Initialize

while ( itr != NULL && itr->element != x ) // Search for x


itr = itr->next;

return ListItr<Object>( itr );


}
Note Object would have to
have a method for !=
find

/**
* Return iterator corresponding to the first node containing an item x.
* Iterator isPastEnd if item is not found.
*/
template <class Object>
ListItr<Object> List<Object>::find( const Object & x ) const
{
ListNode<Object> *itr = header->next; // Initialize

while ( itr != NULL && itr->element != x ) // Search for x


itr = itr->next;

return ListItr<Object>( itr ); // return position of the


// found object or IsPastEnd
}
78
findPrevious

/**
* Return iterator prior to the first node containing an item x. */

template <class Object>


ListItr<Object> List<Object>::findPrevious( const Object & x ) const
{
ListNode<Object> *itr = header;

while ( itr->next != NULL && itr->next->element != x )


itr = itr->next;

return ListItr<Object>( itr );


}

79
remove
/**
* Remove the first occurrence of an item x.
*/
template <class Object>
void List<Object>::remove( const Object & x )
{
ListItr<Object> p = findPrevious( x ); // Locate previous of x, if any

if ( p.current->next != NULL )
{
ListNode<Object> *oldNode = p.current->next;
p.current->next = p.current->next->next; // Bypass deleted node
delete oldNode;
}
} p.current node to be deleted

A1 x A3 A4
80
remove
/**
* Remove the first occurrence of an item x.
*/
template <class Object>
void List<Object>::remove( const Object & x )
{
ListItr<Object> p = findPrevious( x ); // Locate previous of x, if any

if ( p.current->next != NULL ) // not null if x is in the list!


{
ListNode<Object> *oldNode = p.current->next;
p.current->next = p.current->next->next; // Bypass deleted node
delete oldNode;
}
}
p.current node to be deleted

A1 x A3 A4
81
remove
if ( p.current->next != NULL ) // not null if x is in the list!
{
ListNode<Object> *oldNode = p.current->next;
p.current->next = p.current->next->next;
// Bypass deleted node
delete oldNode;
}

p.current node to be deleted

A1 x A3 A4

oldNode
82
remove
if ( p.current->next != NULL ) // not null if x is in the list!
{
ListNode<Object> *oldNode = p.current->next;
p.current->next = p.current->next->next;
// Bypass deleted node
delete oldNode;
}
p.current node to be deleted

A1 x A3 A4

oldNode
83
remove
if ( p.current->next != NULL ) // not null if x is in the list!
{
ListNode<Object> *oldNode = p.current->next;
p.current->next = p.current->next->next;
// Bypass deleted node
delete oldNode;
}

A1 A3 A4

84
zeroth

/**
* Return an iterator representing the header node.
*/
template <class Object>
ListItr<Object> List<Object>::zeroth( ) const
{
return ListItr<Object>( header );
}

Note that we are using the constructor of ListItr (since we


declared List to be a friend of ListItr)

85
first

/**
* Return an iterator representing the first node in the list.
* This operation is invalid for empty lists.
*/
template <class Object>
ListItr<Object> List<Object>::first( ) const
{
return ListItr<Object>( header->next );
}

86
makeEmpty

/**
* Make the list logically empty.
*/
template <class Object>
void List<Object>::makeEmpty( )
{
while ( ! isEmpty( ) )
remove( first( ).retrieve( ) );
}

Keep on removing the first element from the list


until the list becomes empty.
87
Deep Copy
/**
* Deep copy of linked lists.
*/
template <class Object>
const List<Object> & List<Object>::operator=( const List<Object> & rhs )
{
if ( this != &rhs )
{
makeEmpty( );

ListItr<Object> ritr = rhs.first( );


ListItr<Object> itr = zeroth( );
for ( ; ! ritr.isPastEnd( ); ritr.advance( ), itr.advance( ) )
insert( ritr.retrieve( ), itr );
}
return *this;
}
88
Shallow Copy vs Deep Copy

Shallow Copy

X A X is a pointer to an object

Y Y is a pointer

Y = X is a shallow copy

At the end, X and Y are pointing to the same object

89
Shallow Copy vs Deep Copy

Deep Copy

X A X is a pointer to an object

Y Y is a pointer

A Make a copy of the object

Y points to the new object

At the end X and Y point to objects with the same value.

90
Shallow Copy
List<Object> A;
List<Object> B;
A = B; // gets automatically converted to A.operator=(B)
// if the = operator is not overloaded, then the result
// will be a shallow copy

B.header

A1 A2 A3 A4

A.header

91
Deep Copy
/**
* Deep copy of linked lists.
*/
template <class Object>
const List<Object> & List<Object>::operator=( const List<Object> & rhs )
{
if ( this != &rhs ) // Make sure objects are different
{
makeEmpty( );

ListItr<Object> ritr = rhs.first( );


ListItr<Object> itr = zeroth( );
for( ; !ritr.isPastEnd( ); ritr.advance( ), itr.advance( ) )
insert( ritr.retrieve( ), itr );
}
return *this;
}
92
Deep Copy

/**
* Deep copy of linked lists.
*/
template <class Object>
const List<Object> & List<Object>::operator=( const List<Object> & rhs )
{
if( this != &rhs ) // Make sure objects are different
{
makeEmpty( ); // Clean up this object

ListItr<Object> ritr = rhs.first( );


ListItr<Object> itr = zeroth( );
for( ; !ritr.isPastEnd( ); ritr.advance( ), itr.advance( ) )
insert( ritr.retrieve( ), itr );
}
return *this;
}
93
Deep Copy

/**
* Deep copy of linked lists.
*/
template <class Object>
const List<Object> & List<Object>::operator=( const List<Object> & rhs )
{
if( this != &rhs ) // Make sure objects are different
{
makeEmpty( ); // Clean up this object

ListItr<Object> ritr = rhs.first( ); // initialize loop iterators


ListItr<Object> itr = zeroth( );
for( ; !ritr.isPastEnd( ); ritr.advance( ), itr.advance( ) )
insert( ritr.retrieve( ), itr );
}
return *this;
}

94
Deep Copy
/**
* Deep copy of linked lists.
*/
template <class Object>
const List<Object> & List<Object>::operator=( const List<Object> & rhs )
{
if( this != &rhs ) // Make sure objects are different
{
makeEmpty( ); // Clean up this object

ListItr<Object> ritr = rhs.first( ); // initialize loop iterators


ListItr<Object> itr = zeroth( );
for( ; !ritr.isPastEnd( ); ritr.advance( ), itr.advance( ) )
insert( ritr.retrieve( ), itr ); // insert each element one by one
}
return *this;
}
95
Deep Copy
List<Object> A;

List<Object> B;
A = B; // gets automatically converted to A.operator=(B)

// Having overloaded the = operator

B.header

A1 A2 A3 A4

A1 A2 A3 A4

A.header 96
COPY CONSTRUCTOR

/**
* Copy constructor.
*/
template <class Object>
List<Object>::List( const List<Object> & rhs )
{
header = new ListNode<Object>;
*this = rhs; // Deep Copy
}

A copy constructor is a constructor that creates an object


from an object of the same type.

97
COPY CONSTRUCTOR

There are 3 important places where a copy


constructor is called
1. When an object is created from an object of
the same type
2. When an object is passed by value as a
parameter to a function
3. When an object is returned from a function

98
Shallow Copy
void foo(List<Object> B) { … }

List<Object> A;

foo(A); // pass-by-value – copy constructor gets called


// if the copy constructor is not implemented,
// then the result will be a shallow copy

A.header

A1 A2 A3 A4

B.header (inside foo)

99
Deep Copy
void foo(List<Object> B) { … }

List<Object> A;

foo(A); // pass-by-value – copy constructor gets called

// Having implemented the copy constructor

A.header

A1 A2 A3 A4

A1 A2 A3 A4

B.Header (inside foo) 100


DESTRUCTOR
/**
* Destructor.
*/
template <class Object>
List<Object>::~List( )
{
makeEmpty( ); // Get rid of all list nodes
delete header; // then get rid of the header
}

101
USING LISTS
// Simple print function
template <class Object>
void printList( const List<Object> & theList )
{
if ( theList.isEmpty( ) )
cout << "Empty list" << endl;
else
{
ListItr<Object> itr = theList.first( );
for ( ; ! itr.isPastEnd( ); itr.advance( ) )
cout << itr.retrieve( ) << " ";
}
cout << endl;
}

102
USING LISTS
// Simple print function
template <class Object>
void printList( const List<Object> & theList )
{
if ( theList.isEmpty( ) ) // if the list empty
cout << "Empty list" << endl;
else
{
ListItr<Object> itr = theList.first( );
for ( ; !itr.isPastEnd( ); itr.advance( ) )
cout << itr.retrieve( ) << " ";
}

cout << endl;


}
103
USING LISTS
// Simple print function
template <class Object>
void printList( const List<Object> & theList )
{
if( theList.isEmpty( ) ) // if the list empty
cout << "Empty list" << endl;
else
{ // print each element one by one
ListItr<Object> itr = theList.first( );
for( ; !itr.isPastEnd( ); itr.advance( ) )
cout << itr.retrieve( ) << " ";
}

cout << endl;


}
104
USING LISTS
int main( )
{
List<int> theList;
ListItr<int> theItr = theList.zeroth( );
int i;

printList( theList );

for( i = 0; i < 10; i++ )


{
theList.insert( i, theItr );
printList( theList );
theItr.advance( );
}

105
USING LISTS
for ( i = 0; i < 10; i += 2 )
theList.remove( i );

for ( i = 0; i < 10; i++ )


if ( theList.find( i ).isPastEnd( ) )
cout << "Find fails for " << i << endl;
else
cout << "Find succeeds for " << i << endl;

printList( theList );

List<int> list2;
list2 = theList;
printList( list2 );

return 0;
}
106
USING LISTS
Empty List
0
01
012
0123
01234
012345
0123456
01234567
012345678
0123456789
Find fails for 0
Find succeeds for 1
Find fails for 2
Find succeeds for 3
Find fails for 4
Find succeeds for 5
Find fails for 6
Find succeeds for 7
Find fails for 8
Find succeeds for 9
13579
13579 107
Reading List
Paul J.Deitel and Harvey M.Deitel, “ C++ How to Program, 10th
Edition
” , when you open this site select “Not listed? Click Here”
for the “Select Your Institution” dropdown. Then you may enter
by typing your SU email address. (available as an e-book at
Information Center).
 Section 9.11. const (Constant) Objects and const Member
Functions
 Section 9.13. friend Functions and friend Classes
 Section 9.14. Using the this Pointer
Chapter 10. Operator Overloading; Class string and Array
Objects
Chapter 17. Exception Handling
Chapter 18 and 19. Templates
108
COMPLEXITY OF LIST OPERATIONS

• N is the number of elements in the list


• INSERTION
– O(1)
• FIND
– O(N)
• DELETE
– FIND + O(1)  O(N)

109
VARIATIONS ON LISTS
• Circular linked lists
– Last node points to the first node
– So you can go back by going forward!
– End of list is detected by checking if next field is the
same as header->next

A1 A2 A3 A4

110
VARIATIONS ON LISTS
• Circular linked lists
– Last node points to the first node
– So you can go back by going forward!
– End of list is detected by checking if next field is the
same as header->next
– Not really a major improvement,
– Minor complications in coding the methods.

111
VARIATIONS ON LISTS
• Doubly Linked Lists
– With simple lists we can only go forward!
– Why not go backwards?

Data Field

Left Pointer Right Pointer

112
DOUBLY LINKED LIST

113
DOUBLY LINKED LIST
• Need an additional field for left pointer in the
ListNode class
• ListItr class would have to be changed to
include a method for moving left.
• Insert and Remove methods would have to
deal with the left pointer also.

• Possible variation is a circular doubly linked list.

114
LISTS WITH LAST POINTERS
• Sometimes one needs to access the last
element of a list directly (e.g., in queues)

• Maintaining an additional pointer to the last


element provides this functionality.

115
USING LISTS:POLYNOMIALS
• Polynomials are mathematical objects of the
sort anxn + an-1 x n-1 + .... + a1x + a0 where ai are
real/integer coefficients and n is an integer.

• We will represent a polynomial using a linked


list.

116
POLYNOMIALS

class Term {
private:
// methods for constructing and destroying go here
int coefficient;
int exponent;

friend class Polynomial;


}

117
POLYNOMIALS
class Polynomial
{
// we assume that the list nodes are ordered by
// decreasing exponent
public:
Polynomial( );
void insertTermAtFront(int coef, int exp);
void zeroPolynomial( );
Polynomial operator+( const Polynomial & rhs ) const;
Polynomial operator*( const Polynomial & rhs ) const;
void print( ostream & out ) const;

private:
List<Term> terms;
}; 118
POLYNOMIAL ADDITION
• Assume we have the two lists
• 10x5+7x3+5x2+2 is represented by
((10,5), (7, 3), (5, 2), (2, 0))
• 11x6+8x4+4x3+4x2+x is represented by
– ((11,6), (8,4), (4,3), (4, 2), (1, 1))

119
POLYNOMIALS
class Polynomial
{
// we assume that the list nodes are ordered by
// decreasing exponent
public:
Polynomial( );
void insertTermAtFront(int coef, int exp);
void zeroPolynomial( );
Polynomial operator+( const Polynomial & rhs ) const;
Polynomial operator*( const Polynomial & rhs ) const;
void print( ostream & out ) const;

private:
List<Term> terms;
};
120
POLYNOMIAL ADDITION
• Assume we have the two lists
– 10x5+7x3+5x2+2
• ((10,5), (7, 3), (5, 2), (2, 0))
– 11x6+8x4+4x3+4x2+x
• ((11,6), (8,4), (4,3), (4, 2), (1, 1))
• The sum is
– 11x6+ 10x5 + 8x4+ 11x3 + 9x2 + x + 2
• ((11,6), (10,5), (8,4), (11,3), (9,2),(1,1),(2,0))

121
POLYNOMIAL ADDITION
• Assume we have the two (ordered) lists
– ((10,5), (7, 3), (5, 2), (2, 0))
– ((11,6), (8,4), (4,3), (4, 2), (1, 1))
• Output List ( )

122
POLYNOMIAL ADDITION
• Assume we have the two (ordered) lists
– ( (10,5), (7, 3), (5, 2), (2, 0))
– ( (11,6), (8,4), (4,3), (4, 2), (1, 1))
• Set Iterators to first elements
• Compare exponents
– If exponents are not equal
• Output the element with the larger exponent to
the output list
• Advance the larger list’s iterator
123
POLYNOMIAL ADDITION
• Assume we have the two (ordered) lists
– ( (10,5), (7, 3), (5, 2), (2, 0))
– ( (11,6), (8,4), (4,3), (4, 2), (1, 1))
• Output = ( (11,6))
• Compare exponents
– If exponents are not equal
• Output the element with the larger exponent to the
output list
• Advance the larger list’s iterator

124
POLYNOMIAL ADDITION
• Assume we have the two (ordered) lists
– ( (10,5), (7, 3), (5, 2), (2, 0))
– ( (11,6), (8,4), (4,3), (4, 2), (1, 1))
• Output = ( (11,6), (10,5) )
• Compare exponents
– If exponents are not equal
• Output the element with the larger exponent to the
output list
• Advance the larger list’s iterator

125
POLYNOMIAL ADDITION
• Assume we have the two (ordered) lists
– ( (10,5), (7, 3), (5, 2), (2, 0))
– ( (11,6), (8,4), (4,3), (4, 2), (1, 1))
• Output = ( (11,6), (10,5), (8,4) )
• Compare exponents
– If exponents are not equal
• Output the element with the larger exponent to the
output list
• Advance the larger list’s iterator

126
POLYNOMIAL ADDITION
• Assume we have the two (ordered) lists
– ( (10,5), (7, 3), (5, 2), (2, 0))
– ( (11,6), (8,4), (4,3), (4, 2), (1, 1))
• Output = ( (11,6), (10,5), (8,4), (11,3) )
• Compare exponents
– If exponents are not equal
• Output the element with the larger exponent to the
output list
• Advance the larger list’s iterator

127
POLYNOMIAL ADDITION
• Assume we have the two (ordered) lists
– ( (10,5), (7, 3), (5, 2), (2, 0))
– ( (11,6), (8,4), (4,3), (4, 2), (1, 1))
• Output = ( (11,6), (10,5), (8,4), (11,3), (9,2) )
• Compare exponents
– If exponents are not equal
• Output the element with the larger exponent to the
output list
• Advance the larger list’s iterator

128
POLYNOMIAL ADDITION
• Assume we have the two (ordered) lists
– ( (10,5), (7, 3), (5, 2), (2, 0))
– ( (11,6), (8,4), (4,3), (4, 2), (1, 1))
• Output = ( (11,6), (10,5), (8,4), (11,3),(9,2))
• Compare exponents
– If exponents are not equal
• Output the element with the larger exponent to the
output list
• Advance the larger list’s iterator

129
POLYNOMIAL ADDITION
• Assume we have the two (ordered) lists
– ( (10,5), (7, 3), (5, 2), (2, 0) )
– ( (11,6), (8,4), (4,3), (4, 2), (1, 1) )
• Output = ( (11,6), (10,5), (8,4), (11,3),(9,2), (1,1))
• Compare exponents
– If one the lists is exhausted
• Add all the remaining elements of the other list to the
output

130
POLYNOMIAL ADDITION
• Assume we have the two (ordered) lists
– ( (10,5), (7, 3), (5, 2), (2, 0) )
– ( (11,6), (8,4), (4,3), (4, 2), (1, 1) )
• Output = ( (11,6), (10,5), (8,4), (11,3),(9,2), (1,1),(2,0))

• We are done

131
POLYNOMIAL ADDITION
Polynomial& Polynomial::operator+(
const Polynomial & Second) const
{
// initialize list iterators
ListItr<Term> X = terms.first();
ListItr<Term> Y = Second.terms.first();
Polynomial output;

// while both iterators are not past end


while ( ! X.isPastEnd() && ! Y.isPastEnd() ) {
if ( X.retrieve().Exponent > Y.retrieve().Exponent) {
output.insertTermAtFront( X.retrieve().Coefficient,
X.retrieve().Exponent );
X.advance();
}

132
POLYNOMIAL ADDITION
else if (X.retrieve().Exponent < Y.retrieve().Exponent) {
output.insertTermAtFront(Y.retrieve().Coefficient,
Y.retrieve().Exponent);
Y.advance();
}
else // Exponents are Equal
{
output.insertTermAtFront(
X.retrieve().Coefficient + Y.retrieve().Coefficient,
X.retrieve().Exponent);
X.advance();
Y.advance();
}
} // end of the while loop

133
POLYNOMIAL ADDITION
// copy any remaining terms
while ( ! X.isPastEnd() ) {
output.insertTermAtFront(X.retrieve().Coefficient,
X.retrieve().Exponent);
X.Advance();
}
while ( ! Y.isPastEnd() ) {
output.insertTermAtFront(Y.retrieve().Coefficient,
Y.retrieve().Exponent);
Y.Advance();
}

// At this point output is in reverse order


output.terms.Reverse(); // reversal of the list
return (output);
}

134
REVERSING A LIST

( 1,2,3,4,5,6,7,8)  (8,7,6,5,4,3,2,1)

Use constant additional space to perform the reversal.

135
REVERSING A LIST
template <class Object>
void List<Object>::Reverse()
{
ListNode<Object> *current, *previous;
current = NULL;
previous = NULL;
// in place reversal of a list
// uses two additional pointers

while (header->next != NULL) {


current = header->next;
header->next = header->next->next;
current ->next = previous;
previous = current;
}
header->next = previous;
} 136
REVERSING A LIST
header
template <class Object>
1 2 3
void List<Object>::Reverse()
{
ListNode<Object> *current,*previous;
current = NULL;
previous = NULL;
// in place reversal of a list
// uses two additional pointers

while (header->next != NULL) {


current = header->next;
header->next = header->next->next;
current ->next = previous;
previous = current;
}
header->next = previous;
}
137
REVERSING A LIST
template <class Object> header
void List<Object>::Reverse()
{ 1 2 3

ListNode<Object> *current,*previous;
current = NULL;
previous = NULL; current
// in place reversal of a list
// uses two additional pointers

while (header->next != NULL) {


current = header->next;
header->next =
header->next->next;
current ->next = previous;
previous = current;
}
header->next = previous;
}
138
REVERSING A LIST
header
template <class Object>
void List<Object>::Reverse() 1 2 3
{
ListNode<Object> *current,*previous;
current = NULL;
previous = NULL; current
// in place reversal of a list
// uses two additional pointers

while (header->next != NULL) {


current = header->next;
header->next =
header->next->next;
current ->next = previous;
previous = current;
}
header->next = previous; 139
}
REVERSING A LIST
template <class Object>
void List<Object>::Reverse()
{ 1 2 3
header
ListNode<Object> *current,*previous;
current = NULL;
previous = NULL;
// in place reversal of a list current
// uses two additional pointers

while (header->next != NULL) {


current = header->next;
header->next =
header->next->next;
current ->next = previous;
previous = current;
}
header->next = previous;
}
140
REVERSING A LIST
header
template <class Object>
void List<Object>::Reverse() 1 2 3

{
ListNode<Object> *current,*previous;
current = NULL;
previous = NULL; current
// in place reversal of a list previous
// uses two additional pointers

while (header->next != NULL) {


current = header->next;
header->next =
header->next->next;
current ->next = previous;
previous = current;
}
header->next = previous; 141
REVERSING A LIST

template <class Object>


void List<Object>::Reverse() header 1 2 3

{
ListNode<Object> *current,*previous;
current = NULL;
previous = NULL; current
previous
// in place reversal of a list
// uses two additional pointers

while (header->next != NULL) {


current = header->next;
header->next =
header->next->next;
current ->next = previous;
previous = current;
}
header->next = previous;
142
}
REVERSING A LIST
header
template <class Object>
void List<Object>::Reverse() 1 2 3
{
ListNode<Object> *current,*previous;
current = NULL;
previous = NULL;
// in place reversal of a list previous current
// uses two additional pointers

while (header->next != NULL) {


current = header->next;
header->next =
header->next->next;
current ->next = previous;
previous = current;
}
header->next = previous; 143
}
REVERSING A LIST
template <class Object> header
void List<Object>::Reverse()
{ 1 2 3

ListNode<Object> *current,*previous;
current = NULL;
previous = NULL;
// in place reversal of a list
previous current
// uses two additional pointers

while (header->next != NULL) {


current = header->next;
header->next =
header->next->next;
current ->next = previous;
previous = current;
}
header->next = previous;
}
144
REVERSING A LIST
header
template <class Object>
void List<Object>::Reverse() 1 2 3
{
ListNode<Object> *current,*previous;
current = NULL;
previous = NULL;
// in place reversal of a list current previous
// uses two additional pointers

while (header->next != NULL) {


current = header->next;
header->next =
header->next->next;
current ->next = previous;
previous = current;
}
header->next = previous;
145
}
REVERSING A LIST
header
template <class Object>
void List<Object>::Reverse() 1 2 3
{
ListNode<Object> *current,*previous;
current = NULL;
previous = NULL;
// in place reversal of a list
// uses two additional pointers previous
current

while (header->next != NULL) {


current = header->next;
header->next =
header->next->next;
current ->next = previous;
previous = current;
}
header->next = previous;
146
}
REVERSING A LIST
header
template <class Object>
void List<Object>::Reverse() 1 2 3
{
ListNode<Object> *current,*previous;
current = NULL;
previous = NULL;
// in place reversal of a list
// uses two additional pointers previous current

while (header->next != NULL) {


current = header->next;
header->next =
header->next->next;
current ->next = previous;
previous = current;
}
header->next = previous; 147
}
REVERSING A LIST
header
template <class Object>
void List<Object>::Reverse() 1 2 3
{
ListNode<Object> *current,*previous;
current = NULL;
previous = NULL;
// in place reversal of a list
previous current
// uses two additional pointers

while (header->next != NULL) {


current = header->next;
header->next =
header->next->next;
current ->next = previous;
previous = current;
}
header->next = previous;
148
}
REVERSING A LIST
header
template <class Object>
void List<Object>::Reverse() 1 2 3
{
ListNode<Object> *current,*previous;
current = NULL;
previous = NULL;
previous current
// in place reversal of a list
// uses two additional pointers

while (header->next != NULL) {


current = header->next;
header->next =
header->next->next;
current ->next = previous;
previous = current;
}
header->next = previous;
149
}
REVERSING A LIST
header
template <class Object>
void List<Object>::Reverse()
{ 1 2 3

ListNode<Object> *current,*previous;
current = NULL;
previous = NULL;
// in place reversal of a list
// uses two additional pointers previous
current
while (header->next != NULL) {
current = header->next;
header->next =
header->next->next;
current ->next = previous;
previous = current;
}
header->next = previous;
} 150

You might also like