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

ROAD MAP

Where do we go from here?

1
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

2
SEARCHING

• Simple version
– Given a set of objects S, and a query object x, is x in
S?

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)

5
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)

6
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 available CDs in the library

7
CONSIDERATIONS

• How much time are we willing to wait?

8
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!

9
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?)

10
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)

11
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!

12
CONSIDERATIONS

• How much (additional) memory can we use?


– Additional to the set itself

13
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)

14
HOW TO COMPARE?

• Equality
– Is X in S?

15
HOW TO COMPARE?

• Equality
– Is X in S?
• Functional relationship
– Is there an element Y such that F(Y) = X?

16
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

17
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?

18
HOW TO COMPARE?

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

19
HOW TO COMPARE?

• Closeness
– What is/are the element(s) “closest” to X?
• What are the “correct” versions of the misspelled Turkish
words
– iktapalrdaik
– evdaki
– Çekoslovakyalıleştırabliemediklerimizdenmişsinizcsine

20
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

21
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 “correct” Turkish sentence closest in
meaning to “Ben var şiş kebap yemek?”

22
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

23
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”?

24
WHAT IF S IS INFINITE?

• How can we search infinite sets?


– S is the set of possible sentences in Turkish
– X is a sequence of words
– Is X a sentence in Turkish?

25
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?

26
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)

27
WHAT IF COMPARISON IS NOT
EASY?
• Whose fingerprint is this?

28
WHAT IF COMPARISON IS NOT
EASY?
• Whose fingerprint is
this?

• Whose face is this?

29
WHAT IF COMPARISON IS NOT
EASY?
• Whose fingerprint is
this?

• Whose face is this?

• Whose eye is this?

30
WHAT IF COMPARISON IS NOT
EASY?
• Should I run away?

31
WHAT IF COMPARISON IS NOT
EASY?
• Should I run away?

• Find all pictures with


Bill and Monica in them

32
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.
33
LINEAR DATA STRUCTURES

LISTS, STACKS, and QUEUES

34
ABSTRACT DATA TYPES

• Contrary to common conception,


– writing programs is not really about writing a
sequence of statements,

35
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. 36
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.
37
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.

• An abstract data type ADT is a conceptual


specification of the behaviour of a data
structure.

38
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)

39
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.
40
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.

41
REPRESENTATION VS TYPE

32 bit binary data

42
REPRESENTATION VS TYPE

32 bit binary data Representation

Non-negative integers Integers Real numbers

Type
43
REPRESENTATION VS TYPE

Pair of Real numbers Representation

Complex Numbers 2-D Vectors X-Y Coordinates

Type
44
REPRESENTATION VS TYPE

• Type determines what you can do!


– Complex numbers
• Add, Subtract, Multiply, Divide
• Modulus, Angle, Conjugate
• ez, cos z, sin z...

45
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

46
REPRESENTATION VS TYPE

Array of n reals Representation

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

Type
47
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 ...

48
REPRESENTATION VS TYPE

• A given ADT may be based on different


representations.
• Sets: intersect, union, size, membership...

49
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
– ....
50
ADTs VS OBJECTS

• Objects (as in C++) are convenient mechanisms


for implementing ADTs in programming
languages.

51
ADTS VS OBJECTS

• Objects (as in C++) are convenient mechanisms


for implementing ADTs in programming
languages.

• But ...

52
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.

53
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!
54
LINKED LISTS

• A linked list is an ordered sequence of data


items: A1, A2, A3, .... , AN
– An empty list has no elements

55
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)

56
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

57
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 of any type

58
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 of any type
– In general, the (maximum) number of elements, N, is
not known in advance!
59
DIGRESSION - POINTERS

• A pointer is a basic data type supported by the


CPU.
• It contains the actual memory address of
another memory location.
• Pointers occupy 4-bytes in memory.

60
POINTERS

• char * c;
– c is a pointer pointing to a single character;

61
POINTERS

• char * c;
– c is a pointer pointing to a single character;
• int * i;
– i is a pointer pointing to an integer.
– You can also read this as “the type of “*i” is an
integer.
– * is the “content-of” operator.

62
POINTERS

• int j, *i, k;
• k=5;
• i= &k; //i gets the address of k;
• *i = 6 ; // k is now 6
• j= *i ; // j now is also 6

63
POINTERS
• char c = ‘a’ ; 0

c 4

12

16

20

24

64
POINTERS
• char c = ‘a’ ; 0

c 4 a

12

16

20

24

65
POINTERS
• char c = ‘a’ ; 0
• int i;
c 4 a

i 8

12

16

20

24

66
POINTERS
• char c = ‘a’ ; 0
• int i;
c 4 a
• char *p = & c;
i 8

p 12 0 0 0 4

16

20

24

67
POINTERS
• char c = ‘a’ ; 0
• int i; c 4 a
• char *p = & c;
i 8
• int *j ;
p 12 0 0 0 4

j 16

20

24

68
POINTERS
• char c = ‘a’ ; 0
• int i; c 4 a
• char *p = & c;
i 8
• int *j ;
p 12 0 0 0 4

• j= &i; j 16 0 0 0 8

20

24

69
POINTERS
• char c = ‘a’ ; 0
• int i; c 4 a
• char *p = & c;
i 8 0 0 0 67
• int *j ;
p 12 0 0 0 4

• j= &i; j 16 0 0 0 8
• *j = 67;
20

24

70
POINTERS
• char c = ‘a’ ; 0
• int i; c 4 a b
• char *p = & c;
i 8 0 0 0 67
• int *j ;
p 12 0 0 0 4

• j= &i; j 16 0 0 0 8
• *j = 67;
20
• *(p+1) = ‘b’;
24

71
POINTER ARITHMETIC

• You can add / subtract an integer to a pointer.

72
POINTERS
• char C = ‘a’ ; 0
• int i; c 4 a b
• char *p = & c;
i 8 0 0 0 67
• int *j ;
p 12 0 0 0 4

• j= &i; j 16 0 0 0 8
• *j = 67;
20
• *(p+1) = ‘b’;
24

73
POINTER ARITHMETIC

• What is actually added depends on the type of


the data:

74
POINTER ARITHMETIC

• What is actually added depends on the type of


the data:
– char *c;
• c+1 is the address of the next character

75
POINTER ARITHMETIC

• What is actually added depends on the type of


the data:
– char *c; (assume c = 4)
• c+1 = 5 is the address of the next character
– int *i; (assume i = 8)
• i+1 = i+1 * 4 = 12 is the address of the next integer!
• i+5 = i + 5 * 4 = 28 is the address of 5th next integer.

76
ARRAYS AND POINTERS

• In C and C++, an array is also considered to be


a pointer to the first element;
– int A[10]; //A is an array of 10 integers
• An array is also a pointer to the first element
– int *J = A; // J now points to the first element
– int i = *(J+2); // i now has the value of A[2];
– *(A+3) = 6; // Same as A[3] = 6;

77
ARRAYS AND POINTERS

• Character strings are arrays of characters


• So a string is also a pointer to a character.

78
STRINGS
Courtesy Berrin Yanıkoğlu

char *my_strcpy (char * destination, char *source)


{
char *p = destination;
while (*source != '\0') {
*p++ = *source++; //replaces ...
//destination[i] = source[i];
}
*p = '\0'; //insert the final marker
return destination;
}

79
ARRAYS AND POINTERS

• Character strings are arrays of characters


• So a string is also a pointer to a character.
– char Name[6]=“Hello”; // 5 chars + \0
– char *p=Name; // p also points to the same Hello
– char NewName[8];

80
ARRAYS AND POINTERS

• Character strings are arrays of characters


• So a string is also a pointer to a character.
– char Name[6]=“Hello”; // 5 chars + 0
– char *p=Name; // p also points to the same Hello
– char NewName[8];
– char * q;
– q= my_strcpy(NewName, p);
– //q now points to NewName[0];

81
POINTERS

• In general you can point to anything!

82
POINTERS
Date today;   
Date *p_date; //preferred naming - starts with p

Date *p1 = new Date(); //p1

Date *p2 = p1; //p2

int month = (*p1).Month(); //month


// OR
int month = p1->Month();

int day = p1->Day(); //shorthand for (*p).

83
POINTERS ARE POWERFUL, IF YOU
KNOW WHAT YOU ARE DOING
• DELETE any object when it is no longer needed
1. Date *d1 = new Date(); // allocate
2. delete d1; // delete when not needed
• AVOID memory leaks!!!
1. Date *d1 = new Date(); d1

2. d1 = new Date(); // memory leak


// forgot to delete the previous object
• AVOID dangling pointers
1. Date *d1 = new Date();
X
d1 d2
2. Date *d2 = d1;
3. delete d1; // d2 now points to garbage
84
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
85
LINKED LISTS
Deleting an element

A1 A2 A3 A4 A5

A1 A2 A3 A4 A5

86
LINKED LISTS
Deleting an element

A1 A2 A3 A4 A5

A1 A2 A4 A5

A3

87
LINKED LISTS
Deleting an element

A1 A2 A3 A4 A5

A1 A2 A4 A5

A3

88
LINKED LISTS
Inserting an element

A1 A2 A3 A4 A5

Insertion point A6

89
LINKED LISTS
Inserting an element

A1 A2 A3 A4 A5

A6

90
LINKED LISTS
Inserting an element

A1 A2 A3 A4 A5

A6

91
LINKED LISTS
Inserting an element

A1 A2 A6 A3 A4

A5

92
LINKED LISTS

Linked Lists with dummy header nodes

A1 A2 A6 A3

A4
The methods are a bit easier to write.

A5

93
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>;
};

94
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>;
};

95
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 access the private fields
friend class ListItr<Object>;
};

96
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


and ListItr<Object> can access element and next
directly.

97
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.

98
LINKED LISTS
LISTNODE CLASS

template <class Object>


class List; // Incomplete declaration. So the compiler at least
knows that
template <class Object> List and ListItr are some
class ListItr; // Incomplete declaration.
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>;
};

99
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>;
};

100
LISTNODE STORING A DATE

class DateListNode
{
...

Date element;
DateListNode *next;

...
};

101
LISTNODE STORING A
RECTANGLE

class RectangleListNode
{
...

Rectangle element;
RectangleListNode *next;

...
};

102
LISTNODE STORING A CIRCLE

class CircleListNode
{
...

Circle element;
CircleListNode *next;

...
};

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

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

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

Date element;
ListNode *next;

friend class List<Date>;


friend class ListItr<Date>;
};

104
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>;
};

105
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>;
};

106
LIST ITERATOR
The list iterator is an object that keeps
track of list positions
template <class Object>
class ListItr
{
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


};
107
LIST ITERATOR
The list iterator is an object that keeps
track of list positions
template <class Object>
class ListItr
{
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


};
108
LIST ITERATOR
The list iterator is an object that keeps
track of list positions
template <class Object>
class ListItr
{
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
}; 109
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
{ 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


}; 110
LIST ITERATOR
template <class Object>
class ListItr
{ Checks if the position is at the end
public: of 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


}; 111
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( ) ) Returns a reference to the obje
at the current position
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 112
};
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 113


};
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( ) ) Returns a reference to the object
at the current position
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 114
};
(DIGRESSION)EXCEPTIONS
• Exceptions are anomalies that occur during
the normal flow of a program and prevent it
from continuing.

115
EXCEPTIONS
• Exceptions are anomalies that occur during
the normal flow of a program and prevent it
from continuing.
• These anomalies--user, logic, or system
errors--can be detected by a function.

116
EXCEPTIONS
• Exceptions are anomalies that occur during
the normal flow of a program and prevent it
from continuing.
• These anomalies--user, logic, or system
errors--can be detected by a function.
• If the detecting function cannot deal with
the anomaly, it "throws" an exception.

117
EXCEPTIONS
• Exceptions are anomalies that occur during
the normal flow of a program and prevent it
from continuing.
• These anomalies--user, logic, or system
errors--can be detected by a function.
• If the detecting function cannot deal with
the anomaly, it "throws" an exception.
• A function that "handles" that kind of
exception “catches” it.

118
EXCEPTIONS

• In C++, when an exception is thrown,


it cannot be ignored.
• There must be some kind of
notification or termination of the
program.
• If no user-provided exception handler
is present, the compiler provides a
default mechanism to terminate the
program.
119
EXCEPTIONS

• Exceptions are particularly helpful in


dealing with situations that cannot be
handled locally.
• Instead of propagating error status
throughout the program, you can
transfer control directly to the point
where the error can be handled

120
EXCEPTIONS

• Division by zero causes an arithmetic exception


• An unrepresentable arithmetic result may cause
an aritmetic exception (overflow!)
• Running out of memory and needing more may
cause an exception
• Hitting ctrl-c may cause an exception

121
EXCEPTIONS

void main If during execution of this code an exceptional situation


occurs
{
try { //
code to be tried
throw exception;
}
catch (type  exception) {
// code to be executed in case of exception
}
}

122
EXCEPTIONS

void main If during execution of this code an exceptional situation


occurs
{
try { //
An exception object is thrown
code to be tried
throw exception;
}
catch (type  exception) {
// code to be executed in case of exception
}
}

123
EXCEPTIONS

void main If during execution of this code an exceptional situation


occurs
{
try { //
An exception object is thrown
code to be tried
throw exception;
}
catch (type  exception) {
// code to be executed in case of exception
}
}

This code then catches the exception and


“handles” it.

124
EXAMPLE
#include <iostream.h>;

int main () {
try
{
char * mystring;
mystring = new char [10];
if (mystring == NULL) throw "Allocation failure";
for (int n=0; n<=100; n++)
{
if (n> 9) throw n;
mystring[n]='z';
}
}
catch (int i)
{
cout << "Exception: ";
cout << "index " << i << " is out of range" <<endl;
exit (-1)
}
catch (char * str)
{
cout << "Exception: " << str << endl;
exit(-1)
} 125
}
EXAMPLE
#include <iostream.h>;
Compiler knows which handler
int main () {
try
to invoke looking at the types.
{
char * mystring;
mystring = new char [10];
if (mystring == NULL) throw "Allocation failure";
for (int n=0; n<=100; n++)
{
if (n> 9) throw n;
mystring[n]='z';
}
}
catch (int i)
{
cout << "Exception: ";
cout << "index " << i << " is out of range" <<endl;
exit (-1)
}
catch (char * str)
{
cout << "Exception: " << str << endl;
exit(-1)
} 126
}
EXAMPLE
#include <iostream.h>;
Exception: index 10 is out of range
int main () {
try
{
char * mystring;
mystring = new char [10];
if (mystring == NULL) throw "Allocation failure";
for (int n=0; n<=100; n++)
{
if (n> 9) throw n;
mystring[n]='z';
}
}
catch (int i)
{
cout << "Exception: ";
cout << "index " << i << " is out of range" <<endl;
exit (-1)
}
catch (char * str)
{
cout << "Exception: " << str << endl;
exit(-1)
} 127
}
EXAMPLE

const Object & retrieve( ) const


{ if( isPastEnd( ) )
throw BadIterator( );
return current->element; }

128
EXAMPLE

const Object & retrieve( ) const


{ if( isPastEnd( ) )
throw BadIterator( );
return current->element; }

try {// do something with lists


......
}
catch (BadIterator X) {
cout << “We have just gone off the deep end of a list, byeee”
<< endl;
}
129
EXAMPLE

class BadIterator {
public:
BadIterator() {}
};

See http://www.cplusplus.com/doc/tutorial/exceptions.html for some additional


information

130
(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;
}; 131
(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;
}; 132
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;
}; 133
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;
}; 134
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;
}; 135
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;
}; 136
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;
}; 137
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;
}; 138
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;
}; 139
CONSTRUCTOR

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

140
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 point to NULL
return header–>next == NULL;
}

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

141
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
142
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;

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


itr = itr->next;

return ListItr<Object>( itr );


}

143
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 );


}

144
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 );


}

145
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 !=
146
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
}

147
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 );


}

148
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 );


}

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

if( p.current->next != NULL )


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

150
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
151
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
152
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
153
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
154
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

155
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)

156
first

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

157
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.

158
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;
}

159
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

160
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 .

161
Shallow Copy
List<Object> A;

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

// if the = operator is not overloaded, then the result


// will be a shallow copy

A.header

A1 A2 A3 A4

B.header

162
(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;
}; 163
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;
}

164
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;
}

165
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;
}

166
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;
}

167
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;
}

168
Deep Copy
List<Object> A;

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

// Having overloaded the = operator

A.header

A1 A2 A3 A4

A1 A2 A3 A4

169
B.header
COPY CONSTRUCTOR

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

170
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.

171
COPY CONSTRUCTOR

There are 3 important places where a copy


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

172
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)

173
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) 174


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

175
USING LISTS
// Simpleprint 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;


}

176
USING LISTS
// Simpleprint 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;


}

177
USING LISTS
// Simpleprint 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;


}

178
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( );
}

179
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;
}

180
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
181
Reading List
Paul J.Deitel and Harvey M.Deitel, “ C++ for Programmers:
Deitel® Developer Series” , Prentice Hall, 2009 (available as
an e-book at Information Center).
 Section 10.2. const (Constant) Objects and const Member
Functions
 Section 10.4. friend Functions and friend Classes
 Section 10.5. Using the this Pointer
 Chapter 11. Operator Overloading; String and Array Objects
 Chapter 14. Templates
 Chapter 16. Exception Handling

182
COMPLEXITY OF LIST OPERATIONS

• N is the number of elements in the list


• INSERTION

183
COMPLEXITY OF LIST OPERATIONS

• N is the number of elements in the list


• INSERTION
– O(1)

184
COMPLEXITY OF LIST OPERATIONS

• N is the number of elements in the list


• INSERTION
– O(1)
• FIND

185
COMPLEXITY OF LIST OPERATIONS

• N is the number of elements in the list


• INSERTION
– O(1)
• FIND
– O(N)

186
COMPLEXITY OF LIST OPERATIONS

• N is the number of elements in the list


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

187
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)

188
FIND: AVERAGE CASE ANALYSIS

• Assuming that all searches are equally likely, the average


complexity of successful searches is O(N)
• Let the element being searched for is the ith element in the link
list

i # of nodes visited
1 1
2 2
3 3
... ...
N N

189
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

190
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.

191
VARIATIONS ON LISTS

• Doubly Linked Lists


– With simple lists we can only go forward!
– Why not go backwards?

Data Field

Left Pointer Right Pointer

192
DOUBLY LINKED LIST

193
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.

194
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 deal
with the left pointer also.

• Possible variation is a circular doubly linked


list.
195
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.

196
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.

197
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.

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

friend class Polynomial;


}

199
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;
};

200
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))

201
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<Literal> terms;
};

202
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))

203
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 ( )

204
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

205
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

206
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

207
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

208
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 equal
• Add the coefficient’s of both elements and add the sum
coeffient and exponent to the Output
• Advance both lists’ iterators

209
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 equal
• Add the coefficient’s of both elements and add the sum
coeffient and exponent to the Output
• Advance both lists’ iterators

210
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 equal
• Add the coefficient’s of both elements and add the sum
coeffient and exponent to the Output
• Advance both lists’ iterators

211
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

212
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

213
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

214
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();
}

215
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

216
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);
}

217
REVERSING A LIST

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

218
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.

219
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;
}
220
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

while (header->next != NULL) {


current = header->next;
header->next =
header->next->next;
current ->next = previous;
previous = current;
}
header->next = previous;
}
221
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;
}
222
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;
}
223
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;
}
224
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;
}
225
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
// uses two additional pointers
current
while (header->next != NULL) {
current = header->next;
header->next =
header->next->next;
current ->next = previous;
previous = current;
}
header->next = previous;
}
226
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
// uses two additional pointers
current
while (header->next != NULL) {
current = header->next;
header->next =
header->next->next;
current ->next = previous;
previous = current;
}
header->next = previous;
}
227
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
// uses two additional pointers
current
while (header->next != NULL) {
current = header->next;
header->next =
header->next->next;
current ->next = previous;
previous = current;
}
header->next = previous;
}
228
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
// uses two additional pointers
current
while (header->next != NULL) {
current = header->next;
header->next =
header->next->next;
current ->next = previous;
previous = current;
}
header->next = previous;
}
229
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
// uses two additional pointers
current
while (header->next != NULL) {
current = header->next;
header->next =
header->next->next;
current ->next = previous;
previous = current;
}
header->next = previous;
}
230
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
// uses two additional pointers
current
while (header->next != NULL) {
current = header->next;
header->next =
header->next->next;
current ->next = previous;
previous = current;
}
header->next = previous;
}
231
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
// uses two additional pointers
current
while (header->next != NULL) {
current = header->next;
header->next =
header->next->next;
current ->next = previous;
previous = current;
}
header->next = previous;
}
232
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
// uses two additional pointers
current
while (header->next != NULL) {
current = header->next;
header->next =
header->next->next;
current ->next = previous;
previous = current;
}
header->next = previous;
}
233
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
// uses two additional pointers
current
while (header->next != NULL) {
current = header->next;
header->next =
header->next->next;
current ->next = previous;
previous = current;
}
header->next = previous;
}
234

You might also like