pointers and dynamic memory pointer variables are necessary for creation and manipulation of...

56
Pointers and Dynamic Memory Pointer variables are necessary for creation and manipulation of dynamic objects Objects whose memory is acquired during program execution. Dynamic objects stay allocated for the duration na program executes unless deallocated explicitly Dynamic objects enable variable-sized arrays (lists) A pointer is an object containing the address of another object a pointer type specifies the type of objects to be referenced

Post on 21-Dec-2015

231 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Pointers and Dynamic Memory  Pointer variables are necessary for creation and manipulation of dynamic objects Objects whose memory is acquired during

Pointers and Dynamic Memory

Pointer variables are necessary for creation and manipulation of dynamic objects

Objects whose memory is acquired during program execution. Dynamic objects stay allocated for the duration na program executes unless deallocated explicitly

Dynamic objects enable variable-sized arrays (lists)

A pointer is an object containing the address of another object

a pointer type specifies the type of objects to be referenced

Page 2: Pointers and Dynamic Memory  Pointer variables are necessary for creation and manipulation of dynamic objects Objects whose memory is acquired during

Pointers Syntax

Example of uninitialized pointersint *iPtr; //iPtr is a pointer to type int

char *s; //s is a pointer to type char

Date *dPtr; //dPtr is a pointer to type Date

& is the address of operatorapplied to an object, it returns the address (memory

location) of the object

Example of initialized pointers

int i =1; char c = 'y';

int *iptr = &i; //iptr is points to variable i

char *t = &c; // t points to a variable c

Page 3: Pointers and Dynamic Memory  Pointer variables are necessary for creation and manipulation of dynamic objects Objects whose memory is acquired during

Addressing and Indirection

The unary address operator & can be used to obtain the address of an object

The indirection or dereferencing operator *, when used on a pointer object, computes the lvalue of the object to which the pointer object points.

Page 4: Pointers and Dynamic Memory  Pointer variables are necessary for creation and manipulation of dynamic objects Objects whose memory is acquired during

Example of Pointer Manipulation

#include <iostream>using namespace std;

int main()

{

int v1, *ptr1 = &v1, v2, *ptr2 = &v2, *ptr3 = 0;

cout << "Enter two integers: ";

cin >> v1 >> v2;

*ptr1 += v2;

(*ptr2)++; // * has lower precedence than ++

ptr3 = ptr2; ptr2 = ptr1;

*ptr1 = v1 + *ptr3;

cout <<"v1 = " << v1 << " v2 = " << v2 << endl;

cout <<"*ptr1 = " << *ptr1 << " *ptr2 = " << *ptr2 << endl;

cout <<"*ptr3 = " << *ptr3 << endl;

return 0;}

Page 5: Pointers and Dynamic Memory  Pointer variables are necessary for creation and manipulation of dynamic objects Objects whose memory is acquired during

Pointers(1)

C++ allows pointer types whose objects are pointers to pointers to pointers, and so on.

int **ptrptr; // ptrptr is a pointer to type int*

int i = 0;

int *ptr = &i;

ptrptr = &ptr; // OK! because ptr is an int*

ptrptr = ptr; // Illegal! ptrptr needs an int**

Page 6: Pointers and Dynamic Memory  Pointer variables are necessary for creation and manipulation of dynamic objects Objects whose memory is acquired during

Pointers(2)

Pointers as parameterFunctions can have pointer type parameters.void indirectSwap(int* ptr1, int *ptr2){

int temp;

temp = *ptr1;

*ptr1 = *ptr2;

*ptr2 = temp;

}

Call:

int v1, v2;

// ...

indirectSwap(&v1, &v2);

Page 7: Pointers and Dynamic Memory  Pointer variables are necessary for creation and manipulation of dynamic objects Objects whose memory is acquired during

Pointers(3)Constant pointers and pointers to constants

The modifier const can be applied in pointer definitions; depending on where the modifier const is placed, either the pointer is a constant

or the contents of the location to which the pointer points are considered to be constant.

char c1 = 'a'; char c2 = 'b';

const char *cPtr1 = &c1; // *cPtr1 is considered to be //constant! cPtr1 is not a const

char const *cPtr2 = &c2; // *cPtr2 is considered to be //constant! cPtr2 is not a const

char *const cPtr3 = &c1; // cPtr3 is constant; *cptr3 is // not constant

Page 8: Pointers and Dynamic Memory  Pointer variables are necessary for creation and manipulation of dynamic objects Objects whose memory is acquired during

Pointers(4)

Constant pointers and pointers to constants (contd.)

*cPtr1 = 'A'; // illegal: *cPtr1 is a constant!

c1 = 'A'; // legal: c1 is not a constant!

cPtr3 = cPtr2; // illegal; cPtr3 is a constant;

const char* const cPtr4 = &c1; // *cPtr4 is (considered) // const and cPtr4 is constant

Page 9: Pointers and Dynamic Memory  Pointer variables are necessary for creation and manipulation of dynamic objects Objects whose memory is acquired during

Arrays and PointersIn C++ the name of an array is considered to be a constant

pointer; as soon as an array name occurs in an expression, there is an automatic type conversion to a pointer, and the pointer will point to the first element in the array.\

int intArr[] = {1, 2, 3, 4};

int *intPtr = intArr; // intArr is same as &intArr[0]

cout << *(intPtr+2) << endl;// outputs intArr[2]

Page 10: Pointers and Dynamic Memory  Pointer variables are necessary for creation and manipulation of dynamic objects Objects whose memory is acquired during

C-style character stringstext strings are stored as arrays of characters terminated bynull character ’\0’

char txt[5];

char name[] = "Sara";// 5-element char array

char *charPtr;

charPtr = name; // charPtr points to name[0]

cout << charPtr << endl; // "Sara" is written

cout << charPtr+2 << endl; // "ra" is written

cout << *(charPtr+2) << endl; // "r" is written

\end{verbatim}

Page 11: Pointers and Dynamic Memory  Pointer variables are necessary for creation and manipulation of dynamic objects Objects whose memory is acquired during

Array of Pointersint main(){ char *message[] = {"Enter an integer", "Input Error", "Error: divide by zero", "You have mail"}; for (int i = 0; i < 4; i++) cout << message[i] << endl;}

Page 12: Pointers and Dynamic Memory  Pointer variables are necessary for creation and manipulation of dynamic objects Objects whose memory is acquired during

C-style Character StringsThere is a c-style string library cstring which containsvarious functions for processing null terminated string:

#include <cstring> // or #include <string.h>

strcpy(s1, s2); // copies s2 to s1

strcat(s1, s2); // puts a copy of s2 at the end of // s1; no checks for space is done

strlen(s); // returns the length of the string s // (excluding '\0')

// ...

Page 13: Pointers and Dynamic Memory  Pointer variables are necessary for creation and manipulation of dynamic objects Objects whose memory is acquired during

Pointers and Free Store

Memory class of an object may be one of the following

Static: Memory is allocated once at the beginning of executionand stays allocated until the program terminates.Example: global and static local variables.

Automatic: Memory is allocated when the block of declarationis entered and deallocated each time the block is exited. Example: local variables and parameters.

Dynamic: Memory is allocated from the free store (heap), usingoperator new and stays allocated during the execution until it is

de-allocated using operator delete

Page 14: Pointers and Dynamic Memory  Pointer variables are necessary for creation and manipulation of dynamic objects Objects whose memory is acquired during

Dynamic MemoryDynamic objects can be referred to only via pointers.

int *iPtr; // iPtr is uninitialized iPtr = new int; // iptr points to an int

// object (no value yet)

*iPtr = 10; // the object pointed to by

// iPtr receives the value 10

cout << *iPtr << endl;

delete iPtr; // return the memory to the // operating system; iPtr is // undefined

Page 15: Pointers and Dynamic Memory  Pointer variables are necessary for creation and manipulation of dynamic objects Objects whose memory is acquired during

General new Operation Behavior Memory for dynamic objects is requested from the free store. Free store is memory controlled by the operating system. Operation specifies the type and number of objects If there is sufficient memory to satisfy the request, a pointer

to the memory is returned by the operation If there is insufficient memory to satisfy the request, an

exception is generated (an error state/ condition which if not handled (corrected) causes the program to terminate)

SyntaxPtr = new SomeType ;

where Ptr is a pointer of type SomeType

The newly acquired memory is uninitialized unless there is a default constructor for the class SomeType

Page 16: Pointers and Dynamic Memory  Pointer variables are necessary for creation and manipulation of dynamic objects Objects whose memory is acquired during

The new Operator

SomeType *Ptr = new SomeType( argumentList);

The newly acquired memory is initialized using appropriate SomeType

constructor. int *iptr = new int( 10);

Date *birthDate = new Date(1995, 8, 13);

someType *P = new SomeType [Expression];

where Expression is the number of contiguous objects of typeSomeType to be constructed. Example: int *iArray = new int [3];

Page 17: Pointers and Dynamic Memory  Pointer variables are necessary for creation and manipulation of dynamic objects Objects whose memory is acquired during

delete Operator

delete operator is used to return dynamic memory to the free store

delete P; //return storage that was obtained by

//a call to new

delete [] P; //return storage that was obtained by //a call to new[]

Returns storage pointed to by pointer P is returned to free store; P is now undefined

Page 18: Pointers and Dynamic Memory  Pointer variables are necessary for creation and manipulation of dynamic objects Objects whose memory is acquired during

Pointers and Class type

A class cannot have self-reference except via a pointer or reference type

class Employee { public:

Employee(...);

...

private:

char *name; // a member of pointer type

unsigned id;

Employee *manager; // self-reference via pointer

double salary;

};

Note: Member-wise copy semantics may not be desirable if any data member is a pointer

Page 19: Pointers and Dynamic Memory  Pointer variables are necessary for creation and manipulation of dynamic objects Objects whose memory is acquired during

flexarray: A Flexible dynamic array

class

Define a class to implement a flexible array type

The size of the array can grow and shrink at runtime Array element access by operator[] is checked for valid

index range The lowest index of the array can be any user set

value (C++ arrays always begins with index 0)

Page 20: Pointers and Dynamic Memory  Pointer variables are necessary for creation and manipulation of dynamic objects Objects whose memory is acquired during

Class flexarray(1)

Make the constructor explicit. This will disallow a typically erroneous implicit type-conversion:

flexarray a( 10 ); a = 0; // Oops!! Allowed because of // implicit type-conversion.

An explicit member function is needed for each of a) copy constructor b) destructor c) copy assignment operator

Page 21: Pointers and Dynamic Memory  Pointer variables are necessary for creation and manipulation of dynamic objects Objects whose memory is acquired during

Class flexarray

class flexarray

{

public:

// Constructor that can specify size, intialization // value and lowest index

explicit flexarray( int size=0,

const int &fillValue=0, int lb=0);

// copy constructor

flexarray( const flexarray & fla );

// destructor

~flexarray( );

// other member functions

private:

int mySize; // # elements in array

int * myList; // array used for storage int

lower; // lower bound of index };

Page 22: Pointers and Dynamic Memory  Pointer variables are necessary for creation and manipulation of dynamic objects Objects whose memory is acquired during

Constructor(s) for flexarray

This constructor has three parameters and each can take default value so that there are four possible ways of creating an object using none, one, two, or all three of the default values

flexarray::flexarray(int size, const int &fillValue, int lb)// precondition: size >= 0// postcondition: flexarray has a capacity of size items, // all of which are set by assignment to fillValue/ after default construction : mySize(size), myList(new int[size]), lower(lb){ int k; for(k = 0; k < size; k++) { myList[k] = fillValue; }}

Page 23: Pointers and Dynamic Memory  Pointer variables are necessary for creation and manipulation of dynamic objects Objects whose memory is acquired during

Member initialization list

Alternative syntax for the initialization of a class member It is a comma-separated list of a member name and its

initial value The member initialization list can only be specified within

the constructor definition, not its declaration:className::className(parameter list) initialization

list

{function body}

where initialization list has the following form::d1(expression), d2(expression), ...,dn(expression)where d1, d2, ..., dn are names of data members

References and constants must be initialized with the initialization list

Page 24: Pointers and Dynamic Memory  Pointer variables are necessary for creation and manipulation of dynamic objects Objects whose memory is acquired during

Copy Constructor

Has a parameter that is a reference to another object of the same class

Is called automatically if there are declarations of the form: CT obj1=obj2;

CT obj1(obj2);

where CT is a class type and obj1 and obj2 are objects of type CTflexarray::flexarray(const flexarray & fla)

// postcondition: flexarray object is a copy of fla

: mySize(fla.length()),

myList(new int[mySize]),

lower(fla.lbound()) {

int k;

// copy elements

for(k = 0; k < mySize; k++){

myList[k] = fla.myList[k];

}

}

Page 25: Pointers and Dynamic Memory  Pointer variables are necessary for creation and manipulation of dynamic objects Objects whose memory is acquired during

Assignment Operator

const flexarray &flexarray::operator = (const flexarray &rhs)// postcondition: normal assignment via copying has been // performed; if flexarray object and rhs were different

sizes, then flexarray object// has been resized to match the size of rhs{ if (this != &rhs) // don't assign to self! { delete [] myList;// get rid of old storage mySize = rhs.length(); lower = rhs.lbound(); myList = new int [mySize]; //allocate new storage // copy rhs int k; for(k=0; k < mySize; k++) myList[k] = rhs.myList[k]; return *this; // permit a = b = c = d}

Page 26: Pointers and Dynamic Memory  Pointer variables are necessary for creation and manipulation of dynamic objects Objects whose memory is acquired during

Upper and Lower Index

int flexarray::ubound() const{// postcondition: returns flexarray's upper index bound return (lower+mySize-1);}int & flexarray::operator [] (int k) {// description: range-checked indexing, returning item at k// precondition: lower <= k <= lower+mySize-1// postcondition: returns item at position k if (k < lower || k >= (lower+mySize)){ cerr << "Illegal flexarray index: " << k << endl; if ( k < lower ) cerr << " min index = " << lower << endl; if (k >= (lower+mySize)) cerr << " max index = " << (lower+mySize-1) << endl; exit(1);}return myList[k-lower];}

Page 27: Pointers and Dynamic Memory  Pointer variables are necessary for creation and manipulation of dynamic objects Objects whose memory is acquired during

Destructor Member Function

The name of the destructor function is the class name preceded by tilde (~)

classname::~className(){ //… }

Called automatically when a class object leaves its scope to clean up and release resources

The Destructor must not be overloaded and may not have any parameter. If not defined, the compiler will supply one.

flexarray::~flexarray ()

// postcondition: flexarray object is destroyed

{

delete [] myList;

}

Page 28: Pointers and Dynamic Memory  Pointer variables are necessary for creation and manipulation of dynamic objects Objects whose memory is acquired during

Index Operator [] (constant return)

const int & flexarray::operator [] (int k) const// safe indexing, returning const reference to avoid // modification; return item at k// precondition: lower <= k <= ubound()// postcondition: return item at k// exception: exits if index is out-of-bounds{ if (k < lower || k >= (lower+mySize)) { cerr << "Illegal flexarray index: " << k << endl; if ( k < lower ) cerr << " min index = " << lower << endl; if (k >= (lower+mySize)) cerr << " max index = " << (lower+mySize-1) << endl; exit(1); } return myList[k-lower];}

Page 29: Pointers and Dynamic Memory  Pointer variables are necessary for creation and manipulation of dynamic objects Objects whose memory is acquired during

Resizing flexarray Objectsvoid flexarray::resize(int newSize)

// description: resizes the flexarray object to newSize

// elements

// precondition: the current size of flexarray is length();

// newSize >= 0

// postcondition: the current size of flexarray is newSize; for

// each k such that 0 <= k <= min(length,

// newSize), flexarray[k] is a copy of the

// original; other elements of flexarray are

// initialized using the 0-argument int

// constructor

// Note: if newSize < length, elements may be lost

{

Page 30: Pointers and Dynamic Memory  Pointer variables are necessary for creation and manipulation of dynamic objects Objects whose memory is acquired during

Resizing flexarray Objects (contd)

{

int k;

int numToCopy = newSize < mySize ? newSize : mySize;

// allocate new storage and copy element into new storage

int *newList = new int[newSize];

for(k=0; k < numToCopy; k++)

{

newList[k] = myList[k];

}

delete [] myList; // de-allocate old storage

mySize = newSize; // assign new storage/size

myList = newList;

}

Page 31: Pointers and Dynamic Memory  Pointer variables are necessary for creation and manipulation of dynamic objects Objects whose memory is acquired during

Summary

Many of the C++ operators can be overloaded for class type

Overloading of operator functions provides a natural usage of class objects

Nonmember Functions and classes can be declared “friend” of a class within that class’ definition. A friend function or class has the same access privilege as a member.

An alternative to providing “friend” access is to provide suitable accessor/modifier member functions

We must limit the number of nonmember functions having direct access to the internal implementation of class.

Page 32: Pointers and Dynamic Memory  Pointer variables are necessary for creation and manipulation of dynamic objects Objects whose memory is acquired during

Generic Programming using Function Templates

A function template describes a function format that when

instantiated with particulars generates a function definition

A function generated from a function template is called a

template function

template<class T>

Type funcName (//list of parameters of which at

// least one is of type T)

{

function body

}

Page 33: Pointers and Dynamic Memory  Pointer variables are necessary for creation and manipulation of dynamic objects Objects whose memory is acquired during

Generic Programming using Function Templates (contd.)

Based on the argument types in calls, the compiler generates a template function with appropriate types

The formal type parameters are built-in or user-defined types

Every type parameter in template definition must appear in the functions parameter list at least once!

Page 34: Pointers and Dynamic Memory  Pointer variables are necessary for creation and manipulation of dynamic objects Objects whose memory is acquired during

Example of Function Templates

#include <iostream>

using namespace std;

template <class T>

T min( T a, T b ){//works for any type for which

//comparison ‘<‘ is defined

return a < b ? a : b;

}

int main(){

// creates int min( int, int );

cout << "minimum of 10 and 20 is: " << min( 10, 20 ) << endl;

// creates double min( double, double );

cout << "minimum of 10.3 and 20.6 is: " << min( 10.3, 20.6 ) << endl;

return 0;

}

Page 35: Pointers and Dynamic Memory  Pointer variables are necessary for creation and manipulation of dynamic objects Objects whose memory is acquired during

Generic Types: Class Templates

Templates enable us to specify a range of related functions called template functions, or a range of related classes called template classes

Class templates provide the means for describing a class generically and instantiating classes that are type-specific versions of this generic class

Example: flexarray class of integers, doubles, fractions, dates, …

share a common interface and data structure and differonly by the type of the elements they contain.

Page 36: Pointers and Dynamic Memory  Pointer variables are necessary for creation and manipulation of dynamic objects Objects whose memory is acquired during

Class TemplatesDefining a template class

template <class T> // class definitionclass C {// ... returnType f(parameters); // … private: T data; //... };template <class T> // member function definition returnType C<T>::f(parameters){ ... }

T is a type parameter and is used as an ordinary type inside the class Instances of class are created when we write

C <typename>

then T is replaced by typename everywhere in this instance.

The expression C<typeName> can be used as an ordinary class name Type parameters are place holders and specify information needed to

instantiating the template class (the compiler generates the necessary

code)

Page 37: Pointers and Dynamic Memory  Pointer variables are necessary for creation and manipulation of dynamic objects Objects whose memory is acquired during

flexarray Template classtemplate <class T> // flexarray is a template class

class flexarray

{

public:

// Constructor that can specify size, intialization

// value and lowest index; note type T of the elements.

// Class T assumed to have a default constructor

explicit flexarray( int size=0, const T &fillValue = T(), int lb=0);

//A copy constructor

flexarray( const flexarray<T> & fla );

~flexarray( ); // destructor

// Assignment operator

const flexarray & operator = ( const flexarray<T> & fla );

Page 38: Pointers and Dynamic Memory  Pointer variables are necessary for creation and manipulation of dynamic objects Objects whose memory is acquired during

flexarray Template class (1)// accessors

int length( ) const; // size of flexarray

int lbound() const; // lowest index

int ubound() const; // highest index

// indexing

T & operator [ ] ( int index );

const T & operator [ ] ( int index ) const;

// modifiers

void resize( int newSize ); // change size dynamically;

private:

int mySize; // # elements in array

T * myList; // stores objects of type T

int lower; // lower bound of index

};

Page 39: Pointers and Dynamic Memory  Pointer variables are necessary for creation and manipulation of dynamic objects Objects whose memory is acquired during

flexarray Template class (2)template <class T>

flexarray<T>::flexarray(int size, const T &fillValue, int lb)

// precondition: size >= 0. Class T has a default constructor.

// postcondition: flexarray has a capacity of size items, all

// of which are set by assignment to fillValue after default

// construction

: mySize(size),

myList(new T[size]),

lower(lb)

{

int k;

for(k = 0; k < size; k++)

{

myList[k] = fillValue;

}

}

Page 40: Pointers and Dynamic Memory  Pointer variables are necessary for creation and manipulation of dynamic objects Objects whose memory is acquired during

flexarray Template class (3)template <class T>

flexarray<T>::flexarray(const flexarray<T> & fla)

// precondition: Class T has overloaded assignment

// operator

// postcondition: flexarray object is a copy of fla

: mySize(fla.length()),

myList(new T[mySize]),

lower(fla.lbound())

{

int k;

// copy elements

for(k = 0; k < mySize; k++){

myList[k] = fla.myList[k];

}

}

Page 41: Pointers and Dynamic Memory  Pointer variables are necessary for creation and manipulation of dynamic objects Objects whose memory is acquired during

flexarray Template class (4)template <class T>

T & flexarray<T>::operator [] (int k){

// description: range-checked indexing, returning item at

// index k

// precondition: 0 <= k < length()

// postcondition: returns the kth item

if (k < lower || k >= (lower+mySize)){

cerr << "Illegal flexarray index: " << k << endl;

if ( k < lower )

cerr << " min index = "

<< lower << endl;

if (k >= (lower+mySize))

cerr << " max index = "

<< (lower+mySize-1) << endl;

exit(1);

}

return myList[k-lower];

}

Page 42: Pointers and Dynamic Memory  Pointer variables are necessary for creation and manipulation of dynamic objects Objects whose memory is acquired during

Template Class Properties Template Classes and Friends: - A template class can have friends that are templates

with the same or different type parameters, or non-templates

Templates and Static Members: - Each template class has its own copy of static members - Static data members must be initialized at the file

scope. static data member v in class C will have the definition: template <class T> C<T>::v = initialization value;

Page 43: Pointers and Dynamic Memory  Pointer variables are necessary for creation and manipulation of dynamic objects Objects whose memory is acquired during

Recursive programs Recursion is the ability of a function to call itself During execution there are as many instances of the

function as the number of non-terminated calls made Each instance of the function has its own values for

formal parameters and local variables

Example:The factorial function is defined in terms of itself

0! = 1 (Base case) n! = n*(n-1)!, for n >= 1 (Recursive step)

Page 44: Pointers and Dynamic Memory  Pointer variables are necessary for creation and manipulation of dynamic objects Objects whose memory is acquired during

The factorial Function(1)//computeFactorial.cc: Computes factorial of

// nonnegative integer

//includes ...

int factorial(int, unsigned long);

int main() {

int m;

int indent = 0;

cout <<"Enter Number for factorial computation--> ";

cin >> m;

cout << factorial(indent, m) << endl;

return 0;

}

Page 45: Pointers and Dynamic Memory  Pointer variables are necessary for creation and manipulation of dynamic objects Objects whose memory is acquired during

The factorial Function(2)int factorial(int indent, unsigned long m) { int result; cout << setw(indent) <<"" << "ENTERING factorial() WITH

m = ” << m << endl; if ((m == 1) || (m == 0)) { cout << setw(indent) << "" << "LEAVING factorial()

WITH m = ” << m; cout << ", factorial() = " << 1 << endl; --indent; return 1; } else { ++indent; result = m * factorial(indent, m-1); --indent; cout << setw(indent) << "" << "LEAVING factorial() WITH m = ” << m; cout << ", factorial() = " << result << endl; return result; }}

Page 46: Pointers and Dynamic Memory  Pointer variables are necessary for creation and manipulation of dynamic objects Objects whose memory is acquired during

The factorial Function(3)A sample runEnter Number for factorial computation--> 5ENTERING factorial() WITH m = 5 ENTERING factorial() WITH m = 4 ENTERING factorial() WITH m = 3 ENTERING factorial() WITH m = 2 ENTERING factorial() WITH m = 1 LEAVING factorial() WITH m = 1, factorial() = 1 LEAVING factorial() WITH m = 2, factorial() = 2 LEAVING factorial() WITH m = 3, factorial() = 6 LEAVING factorial() WITH m = 4, factorial() = 24LEAVING factorial() WITH m = 5, factorial() = 120120

Page 47: Pointers and Dynamic Memory  Pointer variables are necessary for creation and manipulation of dynamic objects Objects whose memory is acquired during

Form of a Successful Recursive Function

Base Case: There must always be some base cases in which the computation is accomplished without recursion.

Making Progress: For the cases that are to be solved recursively, the recursive call must always be to a case that makes progress toward a base case.

Efficiency: Never duplicate work by solving the same instance of a problem in separate recursive calls.

Page 48: Pointers and Dynamic Memory  Pointer variables are necessary for creation and manipulation of dynamic objects Objects whose memory is acquired during

Recursive Problem-solving(1)

Decompose problem into smaller problem of same type

Solve the smaller sub-problems recursively

Combine the solutions of the sub-problems to obtain a solution of the original problem

Page 49: Pointers and Dynamic Memory  Pointer variables are necessary for creation and manipulation of dynamic objects Objects whose memory is acquired during

Recursive Problem-solving(2)

Produces elegant and clean solutions

Valuable when no iterative solution is possible

Introduces bookkeeping overhead that can slow down the program

Page 50: Pointers and Dynamic Memory  Pointer variables are necessary for creation and manipulation of dynamic objects Objects whose memory is acquired during

Recursion vs. Iteration

When a recursive call is the last executed statement of the function, the call is said to be tail recursive. Example: Recursive factorial function is tail recursive

We can speed up a program by replacing tail recursion by iteration.

Page 51: Pointers and Dynamic Memory  Pointer variables are necessary for creation and manipulation of dynamic objects Objects whose memory is acquired during

The Towers of Hanoi

The ProblemWe are given n disks and three towers. The disks are

initially stacked on tower 1 in decreasing order of size from bottom

to top. - We are to move the disks to tower 3,- one disk at a time, such that - no disk is ever on top of a smaller one.

Basic idea: We can (base case) move the largest disk (disk at the bottom)

from tower 1 to tower 3 directly (without recursion) (recursive step) We can move top (n-1) disks from one

tower to another

Page 52: Pointers and Dynamic Memory  Pointer variables are necessary for creation and manipulation of dynamic objects Objects whose memory is acquired during

The Towers of Hanoi Algorithm

Algorithm move(int count, int start, int finish, int temp)

// Move count disks from tower start to tower finish using // tower temp as temporary. Assume the disks are numbered from // 1, 2, …, count with disk number count at the bottom of // tower 1

Begin if (count > 0) then move(count-1, start, temp, finish) “ move disk# ‘count’ to tower ‘finish’ ” move(count-1, temp, finish, start) endifend

Page 53: Pointers and Dynamic Memory  Pointer variables are necessary for creation and manipulation of dynamic objects Objects whose memory is acquired during

Analysis of Algorithms(1)

An algorithm is a clearly specified set of instructionsto be followed to solve a problem with a finite amount

of resources (time and space)

The actual running time of an algorithm is affected by factors such as - the speed of the computer - the compiler of the language in which the algorithm is

implemented - the operating system etc.

In order to analyze algorithms in a theoretical framework, we consider an abstract computer model in which instructions are executed sequentially

Page 54: Pointers and Dynamic Memory  Pointer variables are necessary for creation and manipulation of dynamic objects Objects whose memory is acquired during

Analysis of Algorithms(2)

The model has the standard set of simple instructions such as - addition, subtraction, multiplication, division - comparison - assignment etc.

The running time of an algorithm is conveniently expressed in terms of a single variable, the size n of a problem

The time complexity function for an algorithm expresses its time requirement by giving, for each possible input, the largest amount of time needed by the algorithm to solve a problem

Page 55: Pointers and Dynamic Memory  Pointer variables are necessary for creation and manipulation of dynamic objects Objects whose memory is acquired during

Asymptotic Notation

One way to estimate the time complexity (or running time) of an algorithm (program) is to determine the number of simple instructions executed by the algorithm

Let f and g be functions from N to N (N denotes the set of natural numbers)

We say that f is Big Oh of g and write f(n) = O(g(n)), if there exist positive constants c and n0

such that f(n) <= c g(n), for all n >= n0

Page 56: Pointers and Dynamic Memory  Pointer variables are necessary for creation and manipulation of dynamic objects Objects whose memory is acquired during

Running Time Estimations

Determine the basic operations such as comparisons, additions, multiplications etc.

Express the number of basic operations as a function of the problem size (n)

Loops: If a loop is iterated y times and has x basic operations, then the running time of the loop is at most xy

The running time of a sequence of statements is the sum of the running time of the individual statements

The running time of nested loops is the product of the number of iterations of the outer loops multiplied by the running time of the innermost loop

Leading constants and low-order terms can be ignored