Η παρουσίαση φορτώνεται. Παρακαλείστε να περιμένετε

Η παρουσίαση φορτώνεται. Παρακαλείστε να περιμένετε

ΜΥΥ105: Εισαγωγή στον Προγραμματισμό

Παρόμοιες παρουσιάσεις


Παρουσίαση με θέμα: "ΜΥΥ105: Εισαγωγή στον Προγραμματισμό"— Μεταγράφημα παρουσίασης:

1 ΜΥΥ105: Εισαγωγή στον Προγραμματισμό
Αναδρομικές Συναρτήσεις Χειμερινό Εξάμηνο 2016

2 Ορισμός και ιδιότητες Μια συνάρτηση είναι αναδρομική αν καλεί τον εαυτό της Οι περισσότερες γλώσσες προγραμματισμού υποστηρίζουν αναδρομικές συναρτήσεις Οι αναδρομικές συναρτήσεις είναι πολλές φορές πιο διαισθητικές από τις αντίστοιχες επαναληπτικές Η εκσφαλμάτωσή τους είναι όμως δυσκολότερη, οπότε πρέπει να χρησιμοποιούνται με προσοχή Επίσης οι αναδρομικές συναρτήσεις μπορεί να επιβαρύνουν τη μνήμη του συστήματος και να είναι πιο αργές

3 Αναδρομικές συναρτήσεις στα μαθηματικά
Παράδειγμα: παραγοντικό def fact(n): if n==0 or n==1: return 1 else: return n*fact(n-1) «βασική» περίπτωση def fact(n): f = 1 for i in range(1,n+1): f *= i return f επαναληπτική συνάρτηση: αναδρομική περίπτωση

4 Παράδειγμα: ύψωση σε δύναμη
def power(x, n): if n == 0: return 1 else: return x * power(x, n-1) αναδρομική συνάρτηση: def power(x, n): result = 1 for i in range(n): result *= x return result επαναληπτική συνάρτηση:

5 Παράδειγμα: αριθμοί Fibonacci
Μια ακολουθία αριθμών: 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144,... Ορίζονται με την αναδρομική συνάρτηση: Χρήσεις και εμφάνιση: Μαθηματικα: συνδεση με τη χρυσή τομή Φύση: διακλαδώσεις δέντρων, διάταξη φύλλων, κλπ.

6 Παράδειγμα: αριθμοί Fibonacci
def rfib(n): if n==1 or n==2: return 1 else: return rfib(n-1)+rfib(n-2) αναδρομική συνάρτηση: def fib(n): if n<=1: return -1 # undefined p = 1 # first number c = 1 # second number for i in range(n-2): # c becomes p, compute new c p, c = c, p +c return c επαναληπτική συνάρτηση: p (previous) = προηγούμενος αριθμός c (current) = τρέχων αριθμός

7 Αναδρομικές συναρτήσεις σε γλώσσα προγραμματισμού
Πιο περίπλοκες από τις μαθηματικές αναδρομές Μπορούν να δημιουργήσουν προβλήματα αν δεν οριστούν σωστά Άσκηση: Τι κάνει η παρακάτω συνάρτηση; Ποιο είναι το πρόβλημα της παρακάτω συνάρτησης; Πως θα φτιάξουμε το πρόβλημα; Η «βασική» περίπτωση ορίζει τη συνθήκη τερματισμού def countdown(n): print(n) countdown(n-1) def countdown(n): print(n) if n==0: print('blast off!'); return countdown(n-1)

8 Αναδρομικές συναρτήσεις σε γλώσσα προγραμματισμού
def countdown(n): print(n) if n==0: print('blast off!'); return countdown(n-1) countdown(0) print(0) print('blast off!')) countdown(3) print(3) countdown(2) countdown(2) print(2) countdown(1) countdown(1) print(1) countdown(0) Η Python δημιουργεί μια «στοίβα» όπου κρατάει τη «μνήμη» για κάθε αναδρομική κλήση: τοπικές μεταβλητές σημείο της συνάρτησης από το οποίο πρέπει να συνεχίσει μετά την επιστροφή από την αναδρομική κλήση

9 Αναδρομικές συναρτήσεις σε γλώσσα προγραμματισμού
Το παράδειγμά μας εξακολουθεί να έχει προβλήματα: Αν καλέσουμε countdown(-1) η συνάρτηση δεν τερματίζει Αν καλέσουμε countdown(10000) το πρόγραμμα θα «κολλήσει» μετά από περίπου 1000 κλήσεις αναδρομής ... η «στοίβα» του προγράμματος θα γεμίσει RuntimeError: maximum recursion depth exceeded def countdown(n): print(n) if n==0: print('blast off!'); return countdown(n-1)

10 Σκεπτόμενοι αναδρομικά
Άσκηση: φτιάξτε μια αναδρομική συνάρτηση vertical, η οποία να τυπώνει τα ψηφία ενός αριθμού «κάθετα» από το περισσότερο στο λιγότερο σημαντικό Επιθυμητή συμπεριφορά: >>> vertical(3124) 3 1 2 4

11 Σκεπτόμενοι αναδρομικά
Βήμα 1: ποια είναι η «βασική» περίπτωση; αν ο αριθμός έχει ένα μόνο ψηφίο, απλά τύπωσε το ψηφίο άρα η συνάρτησή μας πρέπει να έχει τη μορφή: >>> vertical(6) 6 def vertical(n): if n<10: # base case: n has 1 digit print(n) # just print n else: # recursive case: n has 2 or more digits # remainder of function

12 Σκεπτόμενοι αναδρομικά
Βήμα 2: ποια είναι η «αναδρομική» περίπτωση; αν ο αριθμός έχει περισσότερα από ένα ψηφία (=n), τότε σπάσε τον σε δύο μέρη: στο τελευταίο ψηφίο σε όλα τα υπόλοιπα μαζί (δηλ. τα πρώτα n-1 ψηφία) π.χ. το 3124 σπάει σε 312 και 4 πρώτα χρειριζόμαστε τα πρώτα ψηφία (υποπρόβλημα), μετά το τελευταίο ψηφίο τα πρώτα n-1 ψηφία μπορούν να τυπωθούν με τη σωστή σειρά με μια αναδρομική κλήση ο χειρισμός του τελευταίου ψηφίου είναι η «βασική» περίπτωση

13 Σκεπτόμενοι αναδρομικά
def vertical(n): if n<10: # base case: n has 1 digit print(n) # just print n else: # recursive case: n has 2 or more digits vertical(n//10) # recursively print all but last digit print(n%10) # print last digit of n >>> vertical(3124) 3 1 2 4 vertical(3124) vertical(312) print(4) vertical(31) print(2) vertical(3) print(1) print(3)

14

15 Άσκηση Τι κάνει η παρακάτω συνάρτηση; def vertical(n):
if n<10: # base case: n has 1 digit print(n) # just print n else: # recursive case: n has 2 or more digits print(n%10) # print last digit of n vertical(n//10) # recursively print all but last digit >>> vertical(3124) 4 2 1 3

16 Σκεπτόμενοι αναδρομικά
Άσκηση: φτιάξτε μια αναδρομική συνάρτηση pattern που να τυπώνει αστεράκια όπως στα παρακάτω παραδείγματα >>> pattern(3) * ** *** >>> pattern(0) >>> pattern(1) * >>> pattern(2) * **

17 Σκεπτόμενοι αναδρομικά
Βήμα 1: ποια είναι η «βασική» περίπτωση; αν το όρισμα είναι 0, μήν κάνεις τίποτα άρα η συνάρτησή μας πρέπει να έχει τη μορφή: >>> pattern(0) >>> def pattern(n): if n==0: return # base case for n=0 else: # recursive case: n>0 # remainder of function

18 Σκεπτόμενοι αναδρομικά
Βήμα 2: ποια είναι η «αναδρομική» περίπτωση; με ανάλυση της επιθυμητής συμπεριφοράς και λίγη σκέψη... >>> pattern(1) * >>> pattern(2) * ** >>> pattern(3) * ** *** 1 φορά ‘*’ pattern(0) pattern(1) pattern(2) 2 φορές ‘*’ pattern(1) 3 φορές ‘*’ pattern(2)

19 Σκεπτόμενοι αναδρομικά
def pattern(n): if n==0: return # base case for n=0 else: # recursive case: n>0 pattern(n-1) # recursively print pattern for n-1 print(n*'*') # print n stars

20 Πόσο γρήγορη είναι η συνάρτησή μας;
Όταν σχεδιάζουμε μια συνάρτηση, πρέπει να σκεφτόμαστε και την ταχύτητά της Η συνάρτηση rfib είναι πολύ πιο αργή από τη fib def rfib(n): if n==1 or n==2: return 1 else: return rfib(n-1)+rfib(n-2) αναδρομική συνάρτηση: def fib(n): if n<1: return -1 # undefined p = 1 # first number c = 1 # second number for i in range(n-2): # c becomes p, compute new c p, c = c, p +c return c επαναληπτική συνάρτηση:

21 Πόσο γρήγορη είναι η συνάρτησή μας;
Άσκηση: όταν εκτελούμε τη fib(7) πόσες επαναλήψεις εκτελούνται; Η fib(n) χρειάζεται περίπου n επαναλήψεις Άρα ο χρόνος της fib(n) είναι ανάλογος του n def fib(n): if n<1: return -1 # undefined p = 1 # first number c = 1 # second number for i in range(n-2): # c becomes p, compute new c p, c = c, p +c return c επαναληπτική συνάρτηση:

22 Πόσο γρήγορη είναι η συνάρτησή μας;
Άσκηση: όταν εκτελούμε την rfib(7) πόσες φορές εκτελείται η rfib(3); def rfib(n): if n==1 or n==2: return 1 else: return rfib(n-1)+rfib(n-2) αναδρομική συνάρτηση: H rfib κάνει τους ίδιους υπολογισμούς πολλές φορές!

23 Πόσο γρήγορη είναι η συνάρτησή μας;
Άσκηση: μελετήστε την παρακάτω συνάρτηση και σκεφτείτε πως μπορούμε να την κάνουμε πιο γρήγορη def my_pow(base, exponent): value = 1 for i in range(0, exponent): value *= base return value >>> my_pow( , ) >>> **

24 Πόσο γρήγορη είναι η συνάρτησή μας;
Λύση: πως μπορούμε να ορίσουμε τη συνάρτηση my_pow αναδρομικά; an = an/2*an/2 αν ο n είναι ζυγός αν είναι μονός; an = a*an/2*an/2 και στις 2 περιπτώσεις το an/2 χρειάζεται να υπολογιστεί μόνο 1 φορά Πόσες αναδρομικές κλήσεις απαιτούνται για τον υπολογισμό του an; περίπου log2n

25 Πόσο γρήγορη είναι η συνάρτησή μας;
def my_pow(base, exponent): if exponent==0: # base case return 1 tmp = my_pow(base, exponent//2) if exponent % 2 == 0: return tmp*tmp else: return base*tmp*tmp «βασική» περίπτωση ζυγός εκθέτης μονός εκθέτης


Κατέβασμα ppt "ΜΥΥ105: Εισαγωγή στον Προγραμματισμό"

Παρόμοιες παρουσιάσεις


Διαφημίσεις Google