Chapter 6 Lists Plus

77
Chapter 6 Lists Plus Lecture 12

description

Lecture 12. Chapter 6 Lists Plus. What is a Circular Linked List?. A circular linked list is a list in which every node has a successor ; the “ last ” element is succeeded by the “ first ” element. External Pointer to the Last Node. What is a Doubly Linked List?. - PowerPoint PPT Presentation

Transcript of Chapter 6 Lists Plus

Page 1: Chapter 6 Lists Plus

Chapter 6

Lists Plus

Lecture 12

Page 2: Chapter 6 Lists Plus

What is a Circular Linked List?

• A circular linked list is a list in which every node has a successor; the “last” element is succeeded by the “first” element.

Page 3: Chapter 6 Lists Plus

External Pointer to the Last Node

Page 4: Chapter 6 Lists Plus

What is a Doubly Linked List?

• A doubly linked list is a list in which each node is linked to both its successor and its predecessor.

Page 5: Chapter 6 Lists Plus

Linking the New Node into the List

Page 6: Chapter 6 Lists Plus

Deleting from a Doubly Linked List

What are the advantages of a circular doubly linked list?

Page 7: Chapter 6 Lists Plus

What are Header and Trailer Nodes?

• A Header Node is a node at the beginning of a list that contains a key value smaller than any possible key.

• A Trailer Node is a node at the end of a list that contains a key larger than any possible key.

• Both header and trailer are placeholding nodes used to simplify list processing.

Page 8: Chapter 6 Lists Plus

A linked list in static storage ?

A Linked List as an Array of Records

Page 9: Chapter 6 Lists Plus

A Sorted list Stored in an Array of Nodes

Page 10: Chapter 6 Lists Plus

An Array with Linked List of Values and Free Space

Page 11: Chapter 6 Lists Plus

An Array with Three Lists (Including the Free List)

Page 12: Chapter 6 Lists Plus

What is a Class Template?

• A class template allows the compiler to generate multiple versions of a class type by using type parameters.

• The formal parameter appears in the class template definition, and

• the actual parameter appears in the client code.

• Both are enclosed in pointed brackets, < >

Page 13: Chapter 6 Lists Plus

//--------------------------------------------------------// CLASS TEMPLATE DEFINITION//--------------------------------------------------------#include "ItemType.h" // for MAX_ITEMS and ItemType

template<class ItemType> // formal parameter listclass StackType {public:

StackType( ); bool IsEmpty( ) const;bool IsFull( ) const;void Push( ItemType item );void Pop( ItemType item );ItemType Top( );

private:int top;ItemType items[MAX_ITEMS];

};

Page 14: Chapter 6 Lists Plus

StackType<int> numStack;

top 3

[MAX_ITEMS-1] . . .

[ 3 ] 789

[ 2 ] -56

[ 1 ] 132

items [ 0 ] 5670

ACTUAL PARAMETER

Page 15: Chapter 6 Lists Plus

top 3

[MAX_ITEMS-1] . . .

[ 3 ] 3456.8

[ 2 ] -90.98

[ 1 ] 98.6

items [ 0 ] 167.87

StackType<float> numStack;ACTUAL PARAMETER

Page 16: Chapter 6 Lists Plus

top 3

[MAX_ITEMS-1] . . .

[ 3 ] Bradley

[ 2 ] Asad

[ 1 ] Rodrigo

items [ 0 ] Max

StackType<string> numStack;ACTUAL PARAMETER

Page 17: Chapter 6 Lists Plus

//--------------------------------------------------------// SAMPLE CLASS MEMBER FUNCTIONS //--------------------------------------------------------

template<class ItemType> // formal parameter listStackType<ItemType>::StackType( ){

top = -1;}

template<class ItemType> // formal parameter list void StackType<ItemType>::Push ( ItemType newItem ){

if (IsFull()) throw FullStack(); top++;

items[top] = newItem; // STATIC ARRAY IMPLEMENTATION

}

Page 18: Chapter 6 Lists Plus

Using class templates

The actual parameter to the template is a data type. Any type can be used, either built-in or user-defined.

Templates are instantiated at run time.

Can you see how this might cause a problem?

Page 19: Chapter 6 Lists Plus

When creating class template

• Put .h and .cpp code in the same .h file

or

• Have .h include .cpp file at the end

Page 20: Chapter 6 Lists Plus

Recall Definition of Stack

• Logical (or ADT) level: A stack is an ordered group of homogeneous items (elements),

• in which the removal and addition of stack items can take place only at the top of the stack.

• A stack is a LIFO “last in, first out” structure.

Page 21: Chapter 6 Lists Plus

class StackType<int>

StackType

Top

Pop

Push

IsFull

IsEmpty Private data:

topPtr

~StackType

20 30

Page 22: Chapter 6 Lists Plus

What happens . . .

• When a function is called that uses pass by value for a class object like our dynamically linked stack?

Page 23: Chapter 6 Lists Plus

23

Pass by value makes a shallow copy

20 30

StackType<int> myStack; // CLIENT CODE . . .

MyFunction( myStack ); // function call

Private data: 7000 6000

topPtr 7000

Private data:

topPtr 7000

myStack

shallow copy

momeStack

Page 24: Chapter 6 Lists Plus

What’s the difference?

• A shallow copy shares the pointed to data with the original class object.

• A deep copy stores its own copy of the pointed to data at different locations than the data in the original class object.

Page 25: Chapter 6 Lists Plus

Making a deep copy

20 30

Private data: 7000 6000

topPtr 7000someStack

20 30

Private data: 5000 2000

topPtr 5000

myStack

deep copy

Page 26: Chapter 6 Lists Plus

// FUNCTION CODE

template<class ItemType>

void MyFunction( StackType<ItemType> SomeStack )

// Uses pass by value

{

ItemType item;

SomeStack.Pop(item); .

.

.

}

Suppose MyFunction Uses Pop

What happens in a shallow copy?

Page 27: Chapter 6 Lists Plus

27

MyStack.topPtr is left dangling

? 30

StackType<int> myStack; // CLIENT CODE . . .

MyFunction( myStack );

Private data:

topPtr 6000

myStack someStack

shallow copy

Private data: 7000 6000

topPtr 7000

Page 28: Chapter 6 Lists Plus

28

MyStack.topPtr is left dangling

? 30

Private data:

topPtr 6000

myStack someStack

shallow copy

Private data: 7000 6000

topPtr 7000

Notice that the shallow copy and the actual parameter myStack, have changed!

Page 29: Chapter 6 Lists Plus

As a result . . .

• This default method used for pass by value is not the best way when a data member points to dynamic data.

• Instead, you should write what is called a copy constructor, • which makes a deep copy of the dynamic data in

a different memory location.

Page 30: Chapter 6 Lists Plus

More about copy constructors

• When there is a copy constructor provided for a class, the copy constructor is used to make copies for pass by value.

• You do not call the copy constructor.

• Like other constructors, it has no return type.

• Because the copy constructor properly defines pass by value for your class, it must use pass by reference in its definition.

Page 31: Chapter 6 Lists Plus

// DYNAMICALLY LINKED IMPLEMENTATION OF STACK template<class ItemType>class StackType {public: StackType( );

// Default constructor.// Post: Stack is created and empty.

StackType( const StackType<ItemType>& anotherStack );// Copy constructor.// Implicitly called for pass by value.. ..

~StackType( ); // Destructor.// Post: Memory for nodes has been deallocated.

private:NodeType<ItemType>* topPtr;

};

Page 32: Chapter 6 Lists Plus

CLASS CONSTRUCTOR

CLASS COPY CONSTRUCTOR

CLASS DESTRUCTOR

Classes with Data Member Pointers Need

Page 33: Chapter 6 Lists Plus

template<class ItemType> // COPY CONSTRUCTORStackType<ItemType>::StackType( const StackType<ItemType>& anotherStack ){ NodeType<ItemType>* ptr1;

NodeType<ItemType>* ptr2;if ( anotherStack.topPtr == NULL )

topPtr = NULL;else // allocate memory for first node{ topPtr = new NodeType<ItemType>;

topPtr->info = anotherStack.topPtr->info;ptr1 = anotherStack.topPtr->next;ptr2 = topPtr;while ( ptr1 != NULL ) // deep copy other nodes{ ptr2->next = new NodeType<ItemType>;

ptr2 = ptr2->next;ptr2->info = ptr1->info;ptr1 = ptr1->next;

}ptr2->next = NULL;

}}

Page 34: Chapter 6 Lists Plus

What About the Assignment Operator?

• The default method used for assignment of class objects makes a shallow copy.

• If your class has a data member pointer to dynamic data, • you should write a member function to overload

the assignment operator to make a deep copy of the dynamic data.

Page 35: Chapter 6 Lists Plus

// DYNAMICALLY LINKED IMPLEMENTATION OF STACK template<class ItemType>class StackType {public:

StackType( ); // Default constructor.StackType(const StackType<ItemType>& anotherStack );// Copy constructor.void operator= ( StackType<ItemType> );// Overloads assignment operator.. ..

~StackType( ); // Destructor.

private:NodeType<ItemType>* topPtr;

};

Page 36: Chapter 6 Lists Plus

Using Overloaded Binary operator+

When a Member Function was definedmyStack + yourStack

myStack.operator+(yourStack)

When a Friend Function was defined

myStack + yourStack

operator+(myStack, yourStack)

Page 37: Chapter 6 Lists Plus

C++ Operator Overloading Guides

1 All operators except these :: . sizeof ?: may be overloaded.

2 At least one operand must be a class instance.

3 You cannot change precedence, operator symbols, or number of operands.

4 Overloading ++ and -- requires prefix form use by default.

6 An operator can be given multiple meanings if the data types of operands differ.

Page 38: Chapter 6 Lists Plus

Polymorphism with Virtual Functions

formalParameter.MemberFunction(...);then1.If MemberFunction is not a virtual function, the type of the formal parameter determines which function to call.

• Static binding is used.

2.If MemberFunction is a virtual function, the type of the actual parameter determines which function to call.

• Dynamic binding is used.

Page 39: Chapter 6 Lists Plus

class ItemType { public: virtual RelationType ComparedTo(ItemType) const; private: char lastName[50] ;} ;class NewItemType : public ItemType { public: RelationType ComparedTo( ItemType) const; private: char firstName[50] ;} ;void PrintResult( ItemType& first, ItemType& second) { using namespace std; if ( first. ComparedTo( second) ==LESS) cout << " First comes before second" ; else cout << " First does not come before second" ;}

ItemType item1 , item2;NewItemType item3 , item4:PrintResult( item1 , item2) ;PrintResult( item3 , item4) ;

You should pass by reference to access derived data members

Page 40: Chapter 6 Lists Plus

Chapter 7Programming with

Recursion

Page 41: Chapter 6 Lists Plus
Page 42: Chapter 6 Lists Plus
Page 43: Chapter 6 Lists Plus
Page 44: Chapter 6 Lists Plus

What Is Recursion?

• Recursive call A method call in which the method being called is the same as the one making the call

• Direct recursion Recursion in which a method directly calls itself

• Indirect recursion Recursion in which a chain of two or more method calls returns to the method that originated the chain

Page 45: Chapter 6 Lists Plus

Recursion

• You must be careful when using recursion.

• Recursive solutions are typically less efficient than iterative solutions.

• Still, many problems lend themselves to simple, elegant, recursive solutions.

• We must avoid making an infinite sequence of function calls

• infinite recursion

Page 46: Chapter 6 Lists Plus

Some Definitions

• Base case The case for which the solution can be stated nonrecursively

• General (recursive) case The case for which the solution is expressed in terms of a smaller version of itself

• Recursive algorithm A solution that is expressed in terms of

(a)smaller instances of itself and (b)a base case

Page 47: Chapter 6 Lists Plus

Writing a recursive function to find n factorial

DISCUSSION

The function call Factorial(4) should have value 24, because that is 4 * 3 * 2 * 1 .

For a situation in which the answer is known, the value of 0! is 1.

So our base case could be along the lines of

if ( number == 0 )

return 1;

Page 48: Chapter 6 Lists Plus

General format for many recursive functions if (some condition for which answer is known)

// base case

solution statement

else // general case

recursive function call

• Each successive recursive call should bring you closer to a situation in which the answer is known.

• Each recursive algorithm must have at least one base case, as well as the general (recursive) case

Page 49: Chapter 6 Lists Plus

Writing a recursive function to find Factorial(n)

Now for the general case . . .

The value of Factorial(n) can be written as

n * the product of the numbers from (n - 1) to 1,

that is,

n * (n - 1) * . . . * 1

or,

n * Factorial(n - 1)

And notice that the recursive call Factorial(n - 1) gets us “closer” to the base case of Factorial(0).

Page 50: Chapter 6 Lists Plus

Recursive Solution

int Factorial ( int number )

// Pre: number is assigned and number >= 0.

{

if ( number == 0) // base case

return 1 ;

else // general case

return number + Factorial ( number - 1 ) ;

}

Page 51: Chapter 6 Lists Plus

Three-Question Method of verifying recursive functions

• Base-Case Question: Is there a nonrecursive way out of the function?

• Smaller-Caller Question: Does each recursive function call involve a smaller case of the original problem leading to the base case?

• General-Case Question: Assuming each recursive call works correctly, does the whole function work correctly?

Page 52: Chapter 6 Lists Plus

Recursive function to determine if value is in list

PROTOTYPE

bool ValueInList( ListType list , int value , int startIndex ) ;

Already searched Needs to be searched

74 36 . . . 95

list[0] [1] [startIndex]

75 29 47 . . .

[length -1]

index of currentelement to examine

Page 53: Chapter 6 Lists Plus

bool ValueInList ( ListType list , int value, int startIndex )

// Searches list for value between positions startIndex// and list.length-1// Pre: list.info[ startIndex ] . . list.info[ list.length - 1 ]// contain values to be searched// Post: Function value = // ( value exists in list.info[ startIndex ] . . // list.info[ list.length - 1 ] ){ if ( list.info[startIndex] == value ) // one base case

return true ; else if (startIndex == list.length -1 ) // another base case

return false ;else // general casereturn ValueInList( list, value, startIndex + 1 ) ;

}

Page 54: Chapter 6 Lists Plus

“Why use recursion?”

Those examples could have been written without recursion, using iteration instead.

The iterative solution uses a loop, and the recursive solution uses an if statement.

However, for certain problems the recursive solution is the most natural solution.

This often occurs with pointer variables.

Page 55: Chapter 6 Lists Plus

An example where recursion comes naturally

• Combinations• how many combinations of a certain

size can be made out of a total group of elements

Page 56: Chapter 6 Lists Plus

int Combinations(int group, int members)// Pre: group and members are positive. group >= members// Post: Function value = number of combinations of members // size that can be constructed from the total group size.{ if (members == 1) return group; // Base case 1

else

if (members == group) return 1; // Base case 2

else return (Combinations(group-1, members-1) +

Combinations(group-1, members) ) ;}

Page 57: Chapter 6 Lists Plus

Combinations(4, 3)

Page 58: Chapter 6 Lists Plus

struct NodeType{

int info ;NodeType* next ;

}

class SortedType {public :

. . .// member function prototypes

private :

NodeType* listData ;

} ;

struct ListType

Page 59: Chapter 6 Lists Plus

RevPrint(listData);

A B C D E

FIRST, print out this section of list, backwards

THEN, print this element

listData

Page 60: Chapter 6 Lists Plus

61

Using recursion with a linked list

void RevPrint ( NodeType* listPtr )

// Pre: listPtr points to an element of a list.

// Post: all elements of list pointed to by listPtr

// have been printed out in reverse order.

{

if ( listPtr != NULL ) // general case

{

RevPrint ( listPtr-> next ); // process the rest

std::cout << listPtr->info << std::endl;

// print this element

}

// Base case : if the list is empty, do nothing

}

Page 61: Chapter 6 Lists Plus

Function BinarySearch( )

• BinarySearch takes sorted array info, and two subscripts, fromLoc and toLoc, and item as arguments. • It returns false if item is not found in the

elements info[fromLoc…toLoc]. • Otherwise, it returns true.

• BinarySearch can be written using iteration, or using recursion.

Page 62: Chapter 6 Lists Plus

found = BinarySearch(info, 25, 0, 14 );

item fromLoc toLocindexes

0 1 2 3 4 5 6 7 8 9 10 11 12 13 14

info 0 2 4 6 8 10 12 14 16 18 20 22 24 26 28

16 18 20 22 24 26 28

24 26 28

24 NOTE: denotes element examined

Page 63: Chapter 6 Lists Plus

template<class ItemType>bool BinarySearch ( ItemType info[ ] , ItemType item , int fromLoc , int toLoc )

// Pre: info [ fromLoc . . toLoc ] sorted in ascending order // Post: Function value = ( item in info [ fromLoc .. toLoc] )

{ int mid ; if ( fromLoc > toLoc ) // base case -- not found return false ; else {

mid = ( fromLoc + toLoc ) / 2 ; if ( info [ mid ] == item ) //base case-- found at mi return true ;

else if ( item < info [ mid ] ) // search lower half return BinarySearch ( info, item, fromLoc, mid-1 ) ; else // search upper half

return BinarySearch( info, item, mid + 1, toLoc ) ; } }

Page 64: Chapter 6 Lists Plus

Static allocation of space

Recursion is not possible

variable names should be bound to actual addressesin memory at run time

Page 65: Chapter 6 Lists Plus

When a function is called...

• A transfer of control occurs from the calling block to the code of the function.

• It is necessary that there be a return to the correct place in the calling block after the function code is executed.

• This correct place is called the return address.

• When any function is called, the run-time stack is used. • On this stack is placed an activation record (stack frame)

for the function call.

Page 66: Chapter 6 Lists Plus

Stack Activation Frames

• The activation record stores • the return address for this function call, • the parameters, • local variables, and • the function’s return value, if non-void.

• The activation record for a particular function call is popped off the run-time stack when

• the final closing brace in the function code is reached, or • when a return statement is reached in the function code.

• At this time the function’s return value, if non-void, is brought back to the calling block return address for use there.

Page 67: Chapter 6 Lists Plus

// Another recursive function int Func ( int a, int b )

// Pre: a and b have been assigned values// Post: Function value = ??

{ int result;

if ( b == 0 ) // base caseresult = 0;

else if ( b > 0 ) // first general caseresult = a + Func ( a , b - 1 ) ); // instruction 50

else // second general caseresult = Func ( - a , - b ); // instruction 70

return result;}

What operation does Func(a, b) simulate?

Page 68: Chapter 6 Lists Plus

FCTVAL ? result ? b 2 a 5Return Address 100

x = Func(5, 2); // original call is instruction 100

original call at instruction 100 pushes on this record for Func(5,2)

Run-Time Stack Activation Records

Page 69: Chapter 6 Lists Plus

FCTVAL ? result ? b 1 a 5Return Address 50

FCTVAL ? result 5+Func(5,1) = ? b 2 a 5Return Address 100

record for Func(5,2)

call in Func(5,2) codeat instruction 50 pushes on this recordfor Func(5,1)

x = Func(5, 2); // original call at instruction 100

Run-Time Stack Activation Records

Page 70: Chapter 6 Lists Plus

FCTVAL ? result ? b 0 a 5Return Address 50

FCTVAL ? result 5+Func(5,0) = ? b 1 a 5Return Address 50

FCTVAL ? result 5+Func(5,1) = ? b 2 a 5Return Address 100

record for Func(5,2)

record for Func(5,1)

call in Func(5,1) codeat instruction 50pushes on this record for Func(5,0)

x = Func(5, 2); // original call at instruction 100 Run-Time Stack Activation Records

Page 71: Chapter 6 Lists Plus

FCTVAL 0 result 0 b 0 a 5Return Address 50

FCTVAL ? result 5+Func(5,0) = ? b 1 a 5Return Address 50

FCTVAL ? result 5+Func(5,1) = ? b 2 a 5Return Address 100

record for Func(5,2)

record for Func(5,1)

record for Func(5,0)is popped first with its FCTVAL

x = Func(5, 2); // original call at instruction 100

Run-Time Stack Activation Records

Page 72: Chapter 6 Lists Plus

FCTVAL 5 result 5+Func(5,0) = 5+ 0 b 1 a 5Return Address 50

FCTVAL ? result 5+Func(5,1) = ? b 2 a 5Return Address 100

record for Func(5,2)

record for Func(5,1)is popped nextwith its FCTVAL

x = Func(5, 2); // original call at instruction 100

Run-Time Stack Activation Records

Page 73: Chapter 6 Lists Plus

FCTVAL 10 result 5+Func(5,1) = 5+5 b 2 a 5Return Address 100

x = Func(5, 2); // original call at line 100

record for Func(5,2)is popped lastwith its FCTVAL

Run-Time Stack Activation Records

Page 74: Chapter 6 Lists Plus

Tail Recursion

• The case in which a function contains only a single recursive call and it is the last statement to be executed in the function.

• Tail recursion can be replaced by iteration to remove recursion from the solution as in the next example.

Page 75: Chapter 6 Lists Plus

// USES TAIL RECURSION

bool ValueInList ( ListType list , int value , int startIndex )

// Searches list for value between positions startIndex

// and list.length-1

// Pre: list.info[ startIndex ] . . list.info[ list.length - 1 ]

// contain values to be searched

// Post: Function value =

// ( value exists in list.info[ startIndex ] . .

// list.info[ list.length - 1 ] )

{

if ( list.info[startIndex] == value ) // one base case return true;

else if (startIndex == list.length -1 ) // another base case

return false;

else

return ValueInList( list, value, startIndex + 1 );

}

Page 76: Chapter 6 Lists Plus

// ITERATIVE SOLUTION

bool ValueInList ( ListType list , int value , int startIndex )

// Searches list for value between positions startIndex// and list.length-1// Pre: list.info[ startIndex ] . . list.info[ list.length - 1 ]// contain values to be searched// Post: Function value = // ( value exists in list.info[ startIndex ] . . // list.info[ list.length - 1 ] ){ bool found = false; while ( !found && startIndex < list.length )

{ if ( value == list.info[ startIndex ] ) found = true;

else startIndex++;}return found;

}

Page 77: Chapter 6 Lists Plus

Use a recursive solution when:

• The depth of recursive calls is relatively “shallow” compared to the size of the problem.

• The recursive version does about the same amount of work as the nonrecursive version.

• The recursive version is [much] shorter and simpler than the nonrecursive solution.

SHALLOW DEPTH EFFICIENCY CLARITY