Вы находитесь на странице: 1из 33

Computer programming -

Algorithms

Semester 2

Module 1
English classes
Overview Module 1
1. RECURSIVITY
1. Recursive programming in C/C++.
2. Stack management
2. RECURSIVE AND NON- RECURSIVE
PROGRAMMING METHODS
Backtracking method
Divide et impera method

3. SEARCHING AND SORTING TECHNICS


Searching methods
Binary search
Sorting methods
Simple sorting methods
Advanced sorting methods
Searching and sorting library functions
2
1. RECURSIVITY
1.1. Introduction

Recursively programming comes naturally from the


mathematical recursivity (recursion).

In mathematics a notion is defined in a recursive


mode if inside the definition is the notion itself.

Recursive algorithm: Pn
- A problem is solved at
Pn-1
different levels, the last
level being a simple one
that is solved without Pk val
recursivity (based on a
3
condition that will not impose recursivity).
Examples of recursive algorithms
Factorial:
n!= 1*2*3*...*n, as non-recursive definition

n! = n * (n-1)!, as recursive definition


fact(n)=1 if n=0
fact(n)=n * fact(n-1) if n>0

Fibonacci function:
f(n) = 0, if n=0
f(n) = 1, if n=1
f(n) = f(n-1) + f(n-2), if n>= 2
4
cmmdc(m, n) =
m, if n=0
n, if m=0
cmmdc(n, m%n), if m>n
cmmdc(m,n%m), if n>m

cmmdc(m, n) =
m or n, if m=n
cmmdc(m-n, n), if m>n
cmmdc(m, n-m), if m<n

5
Arrangements - Arrangement numbers, more commonly
called permutation numbers, or simply permutations, are
the number of ways that a number of things can be
ordered or arranged. A group of objects where the order
does matter.
Arrangements n by k:
A(n,k)=n!/ (n-k)!=n*(n-1)*(n-k+1)=n*[(n-1)**((n-1)-(k-
1)+1)]= n*A(n-1, k-1)
A(n,1)=n; if k=1 // exit condition

Combinations - Is a way of selecting items from a collection,


in which the order does not matter. Combinations n by k:
C(n,k)=n!/ (k!*(n-k)!)=[n/ (n-k)]* C(n-1,k) repetition not
allowed
C(n,k)=n, if k=1
C(n,k)=1 if k=0 or n=k
C(n,k) = C(n-1, k) + C(n-1, k-1)
(Analyze the case when repetition is allowed !!!) 6
Ackermann function (Pter and
Robinson) :
For small values of m (1, 2, 3) the value will
increase relative exponential with n. For m>=4 the
value will increase very fast.
Example:
A(4,2) is an integer with 19,729 digits (approx.
21019728)

7
1.2. Recursive functions
In programming, recursivity is expressed by sub-
programs and in C/C++ with functions and
member functions (methods)in classes

A function is recursive, if its execution involves at


least a self-call

The self-call may be realized:


direct, the function is self-called by its self
(direct recursivity)
indirect, by other functions in a circular mode
(indirect recursivity) 8
Factorial n! = n * (n-1)!
int factorial(int n);

void main(void){
int step; cin >>step;
cout << "Factorial of step = " << factorial(step) << endl;
cout<<"address 1";
cin.ignore();
cin.get();
}//main

int factorial(int n){


cout << "\nStep = "<< n;
if (n == 0) return 1;
else
return n*factorial(n-1); //address 2
9
}
Important remarks !!!
Any recursive call of a function is a new instance
to compute the function

At each call, on local stack a new set of local


variables is created (including also the formal
parameters)

The local variables have the same name but


different locations/values, no conflict will appear
Only the top value is accessible at each moment

10
11
In the function calling and in the self-calling
process on the stack will be stored:

Values of parameters transferred by value


Addresses of parameters transferred by
address (references and pointers)
Values of all non-static local variables
Return address to the next calling instruction

12
Stack evolution for fact(3)
Stiva program

adresa2
Stiva program 0
adresa2
adresa2
Stiva program
1
1
adresa2
adresa2
adresa2
Stiva program 2 2 2
adresa1 adresa1 adresa1
adresa1
3 3 3
3

13
Fibonacci numbers:
f(n) = 0, if n=0
f(n) = 1, if n=1
f(n) = f(n-1) + f(n-2), if n>= 2

int fib(int n)
{
if (n < 2)
return n;
else
return fib(n-1)+fib(n-2);
}

void main(void)
{
cout << "Fibonacci de 5 = " << fib(5) << endl;
cin.get();
}
14
The method is very inefficient, the computing time being
of order (named golden section), that is an exponential
time -
The inefficiency is because some elements are evaluated
more then once:

15
16
Important remarks!
Any recursive algorithm may be
transformed in an iterative one and vice-
versa
Any natural number may be decomposed
in a sum of non-succession Fibonacci
numbers (Zeckendorf theorem).
This thing is used in Fibonacci coding
any natural number being represented by
a bits sequence with no 2 successive 1
bits, at the end it is possible to have a 11
sequence.
17
First n Fibonacci numbers may be computed in an
iterative mode using a suplementary one dimensional
array:

void fib(int n, int *p)


{
int l=2;
p[0]=0; p[1]=1;
for(; l < n; l++)
p[l] = p[l-1] + p[l-2];
}
This algorithm solves the same problem in a linear
mode
18
Fibonacci numbers may be computed without this additional one
dimensional array:
//Solutia iterativa pentru generarea sirului lui Fibonacci pana la N dorit
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <conio.h>

void main(void)
{
int l=1, j=0, k, N;
printf(" Numarul de elemente dorit este: \n");
scanf("%d", &N);
printf("f[0]= 0\n");

for(k=1; k < N; k++)


{
j=l+j;
l=j-l;
printf("f[%d]= %d\n",k, j);
}//end for
_getch();
19
}//main
Combinations
C(n,k) = C(n-1,k) + C(n-1,k-1)

int comb(int n, int k)


{
if(k==0) || (n==k) return 1;
if(k==1) return n;
return (comb(n-1, k) + comb(n-1, k-1));
}
Multiple evaluations are computed in this case:
C(5,3) = C(4,3) + C(4,2)
C(4,3) = C(3,3) + C(3,2)
C(3,2) = C(2,2) + C(2,1)
C(4,2) = C(3,2) + C(3,1)
C(3,2) = C(2,2) + C(2,1) 20
c.m.m.d.c.

int cmmdc(int a, int b)


{
if(a==0) return b;
if(b==0) return a;
if(b>a) return cmmdc(a, b%a);
return cmmdc(b,a%b);
}

21
Conclusions:
A recursive algorithm is structured on more
levels
At each level is realized the same action, but
at a smaller dimension of the problem
Exists at least one level where the solving
process is non-recursive (direct)
Considering the programming language we
have a self-call:
The self-call is realized for a smaler dimension of
the problem
Exists a problem dimension where we return a
result (no self-call base case)

22
1.3. Exit from recursivity

Any function call will determine to store on the stack the


parameters of the function, the local (non-static) variables
and the return address at the first instruction after the
calling process

At successive callings the space allocated to the stack


may overflow (stack overflow)

To avoid such a situation when a function is self called at


infinite, in the self call will be a condition that will stop the
self calling process (time out).

23
Possibilities:
To associate to the recursive function an integer
parameter n and the calling process will be realized
with the values (n-1), (n-2), till n>0
We associate to the recursive function a boolean
parameter and the calling process is realized till the
parameter is TRUE

The recursive solutions will not usual generate


optimal solutions

The recursive solutions will offer more elegant and


easy to understand solutions

24
When we choose a recursive solution it is
important to analyze the elements concerning:
Used memory
Execution time
Transferred parameters (it is preferred to use
global parameters!!! where it is possible,
concerning the stack management)

We prefer the recursive solution when the


iterative solution will consider a huge effort for
implementation and the testing and maintenance
will be difficult
25
Example 1: Sum of digits of an int number
Technic:
Recursive: sum of digits from left side +
last digit
Iterative: sum of digits (digit by digit)

Recursive solution:

int suma_cifre_recursiv(int n)
{
if (n==0)
return 0;
else
return suma_cifre_recursiv(n/10)+n%10;
}
26
Cleaning stack

Adresa 2
suma_cifre_recursiv(0) n=0 0
Adresa 2
suma_cifre_recursiv(1) n=1 0+1%10=1
Adresa 2
suma_cifre_recursiv(12) n=12
1+12%10=3
Adresa 2
suma_cifre_recursiv(123) n=123
3+123%10=6
Adresa 1
suma_cifre_recursiv(1234) n=1234
6+1234%10=10
main()
28
Iterative solution:

int suma_cifre_iterativ(int n)
{
int s=0;
while(n != 0) {
s += n%10;
n /= 10;
}
return s;
}

29
Example 2: sum of elements of an one
dimensional array
Technic:
Recursive: sum of first (n-1) elements + last
element
Iterative: sum, element by element

Recursive implementation:
int suma_elem_recursiv(int tab[ ], int n)
{
if (n==1)
return tab[0];
else
return suma_elem_recursiv(tab, n-1)+
tab[n-1];
30
}
Iterative solution:

int suma_elem_iterativ(int tab[ ], int n)


{
int s=0;
for(int i=0; i<n; i++)
s += tab[i];
return s;
}

31
Example 3: palindrom string
A string is palindrom if:
First character is identic with the last character
Remainder string is palindrom
Examples: rotor, madam
Recursive implementation:
int mirror(char *s)
{
if (strlen(s) <= 1)
return 1;
else
if(s[0] == s[strlen(s) - 1])
return mirror(substr(s,1, strlen(s) - 2);
else
return 0;
} 32
Where substr() function is:

char* substr(char* s,int pi,int pf)


{
int k=0;
char *sn=new char[pf-pi+1];
for(int i=pi;i<=pf;i++,k++)
*(sn+k)=*(s+i);
*(sn+k)=0;
return sn;
}

33
We have some problems types that are usual
solved with recursive functions.
The main methods are:
Backtracking method;
Division method, divide et impera;
Greedy method;
Dynamic programing;
Methods where data are recursive, etc.

34

Вам также может понравиться