Wykład 3

Transkrypt

Wykład 3
WYKŁAD 8
Funkcje i algorytmy rekurencyjne
Proste przykłady
Programy: c3_1.c ......, c3_6.c
Tomasz Zieliński
METODY REKURENCYJNE (1) - program c3_1
======================================================================================================
Funkcja rekurencyjna to funkcja, która wywołuje samą siebie.
======================================================================================================
/* Przyklad 3.1 - wypisz znaki z klawiatury w odwrotnej kolejnosci */
#include <stdio.h>
void odwrotnie( void );
void main()
{
printf("\nPisz w linii. Zakoncz <Enter>. \n\n");
odwrotnie();
}
void odwrotnie( void )
{
char c;
if ( (c=getchar() ) != '\n' )
{
odwrotnie();
printf( "%c", c);
}
}
// wczytaj znak z klawiatury i podstaw jego
// kod ASCII do c; jeśli nie jest to koniec linii, to:
//
// wywołaj ponownie funkcję odwrotnie()
// wyświetl na ekranie znak c
METODY REKURENCYJNE (2) - program c3_1
Wypisz w odwrotnej kolejności znaki z klawiatury
ZAŁOŻENIE: z klawiatury: „ab [ENTER]”
void main()
{ .....
odwrotnie();
.....
}
void odwrotnie( void )
{
char c;
if ( (c=getchar()) != '\n' )
{
odwrotnie();
printf( "%c", c);
}
}
c ← „a”;
odwrotnie();
c ← „b”;
odwrotnie();
c ← „\n”;
wypisz c;
wypisz c;
c jest lokalną zmienną każdego z wywołań funkcji,
która ma różną wartość w każdym z wywołań
METODY REKURENCYJNE (3) - program c3_1
Wypisz w odwrotnej kolejności znaki z klawiatury
Program główny
a
ZAŁOŻENIE: z klawiatury: „abcd [ENTER]”
printf
b
printf
c
printf
d
printf
\n
METODY REKURENCYJNE (4) - program c3_2
Zamiana integer na ASCII
/* Przyklad 3.2 - wypisz ma ekranie liczbę calkowitą
/*
czyli INTEGER na ASCII
*/
*/
#include <stdio.h>
#include <math.h>
void wypisz( int n );
/* program glowny -------------------------------------------------------------------- */
void main()
{
int x;
printf(" \n jaka liczba calkowita ? ");
scanf("%d", &x);
printf(" \n podane = %d \n", x);
printf(" rekursja = "); wypisz( x );
printf("\n");
}
/* Funkcja rekurencyjna ----------------------------------------------------------- */
void wypisz( int n )
{
int i;
if ( n < 0 ) { putchar('-'); n = -n; }
//
}
// jeśli liczba ujemna,
// to napisz „-” oraz zaneguj liczbę
if ( (i=n/10) != 0 ) wypisz( i );
// jeśli „i”, czyli część całkowita z „n/10”,
// jest różna od zera, to wywołaj ponownie
// ale z argumentem „i”
putchar(‘0’+n%10);
putchar( '0' + (unsigned char) (n - 10 * i) );
// to (reszta z dzielenia n przez 10)
// lub to (czyli najmniej znacząca cyfra)
METODY REKURENCYJNE (5) - program c3_2
Zamiana integer na ASCII
Program główny
ZAŁOŻENIE: z klawiatury: „12345 [ENTER]”
n
12345
putchar
„5”
putchar
i = n/10
n=1234
putchar
= putchar(‘0’ + (unsigned char) (n – 10*i)
„4”
i = n/10
n=123
= putchar(‘0’ + (unsigned char) (n % 10)
putchar
„3”
n=12
putchar
wypisz resztę z dzielenia n przez 10,
czyli najmniej znaczącą cyfrę n
i = n/10
„2”
i = n/10
n=1
putchar
„1”
METODY REKURENCYJNE (6) - program c3_3
n! czyli n-silnia
/* Przyklad 3.3 - METODY REKURENCYJNE - oblicz n!
/* n! = 1*2*3*...*(n-1)*n np. 5! = 1*2*3*4*5
*/
*/
#include <stdio.h>
long silnia( long n );
/* program glowny -------------------------------------------------------------- */
void main()
{
long n, x, iloczyn;
printf("\n Obliczam funkcje n ! Podaj n ? [max 12] ");
scanf("%ld", &n);
/* Metoda iteracyjna */
iloczyn = 1;
for( x = n; x > 0; x--)
{ iloczyn = iloczyn * x; }
printf( "\n Metoda iteracyjna --> n! = %ld \n", iloczyn );
/* Metoda rekurencyjna */
iloczyn = silnia( n );
printf( "\n Metoda rekurencyjna --> n! = %ld \n", iloczyn);
}
/* Funkcja rekurencyjna ----------------------------------------------------------- */
long silnia( long n )
{
long x, y;
if( n == 0L ) return(1);
x = n-1;
y = silnia(x);
return(n*y);
// L znaczy long
/* rekurencyjne wywolanie */
}
long silnia( long n )
{
if( n == 0L ) return(1);
return(n* silnia(n-1));
}
/* rekurencyjne wywolanie */
METODY REKURENCYJNE (7) - program c3_3
n! czyli n-silnia
Program główny
ZAŁOŻENIE: z klawiatury: „4 [ENTER]”
n
4
4*(3*2*1*1)
long silnia( long n )
{
long x, y;
24
n-1
3
3*(2*1*1)
if( n == 0L ) return(1);
x = n-1;
y = silnia(x);
return(n*y);
6
n-1
2
2
2*(1*1)
}
n-1
1
1
1*(1)
n-1
0
1
1
long silnia( long n )
{
if( n == 0L ) return(1);
return( n*silnia(n-1) );
}
METODY REKURENCYJNE (7) - program c3_5
szukanie elementu metodą podziału zbioru
na dwie części
indeks
i
tablica
dzielników
N-1
2.0
•
•
•
15
1.5
•
•
•
5
0.5
4
0.4
3
0.3
2
0.2
1
0.1
0
0.0
ZADANIE: znaleźć indeks „i” tablicy,
dla którego: tab[ i ] == x
x = 1.6
ROZWIĄZANIE 1 (sekwencyjne):
i = 0;
while( ( x != tab[i] ) & (i < N-1) )
i++;
ROZWIĄZANIE 2 (rekurencyjne):
int szukaj( int tab[ ], int x, int dol, int gora )
{ int srodek;
srodek = (dol + gora)/2;
if ( x == tab[ srodek ] ) return( srodek);
if ( x < tab[ srodek ] )
return( szukaj( tab, x, dol, srodek - 1 ) );
else
return( szukaj( tab, x, srodek + 1, gora ) );
}
METODY REKURENCYJNE (8) - program c3_5
PRZYKŁAD: przetworniki A/C kompensacyjne:
równomierny (po lewej) i wagowy (po prawej)
Ux
K
Ulicznika
Ux
0/1
UC/A
0
0
1
1
0
Stop
0
1
1
Stop
Układ logiki
Licznik/Generator
Start
UC/A
Start
Ulicznika
UREF
C/A
UREF
C/A
0/1
K
Uzakres
Uzakres
3/4Uz
Ux
Ux
1/2Uz
1/4Uz
stan licznika
0000
0001
0010
0011
0100
•••
0
1
2
3
nr bitu C/A
METODY REKURENCYJNE (9) - program c3_5
szukanie metodą podziału na dwie części
/* Przyklad 3.5 - METODY REKURENCYJNE - szukanie "dwojkowe"
/*
WEJŚCIE:
tab = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ]
/*
x = liczba naturalna z klawiatury
/*
WYJŚCIE:
położenie (indeks) elementu x w tablicy tab[]
*/
*/
*/
*/
#include <stdio.h>
int szukaj( int tab[ ], int x, int dol, int gora );
void main()/* program glowny ---------------------------------------------------------------------- */
{
int tab[ 11 ] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10 };
int x, indeks, dol, gora;
printf("\n Jaka jest calkowita wartosc poszukiwanego elementu ? ");
scanf("%d", &x);
dol = 0; gora = 10;
indeks = szukaj( tab, x, dol, gora );
printf( "\n Indeks = %i \n", indeks);
}
/* funkcja rekursywna ----------------------------------------------------------------- */
int szukaj( int tab[ ], int x, int dol, int gora )
{
int srodek;
if ( dol > gora ) return(-1);
/* -1 oznacza brak elementu w zbiorze */
srodek = (dol + gora)/2;
if ( x == tab[ srodek ] ) return( srodek);
if ( x < tab[ srodek ] )
return( szukaj( tab, x, dol, srodek - 1 ) );
else
return( szukaj( tab, x, srodek + 1, gora ) );
}