Theoretical Computer Science; Algorithms and Data Structures
Diomidis Spinellis
Department of Management Science and Technology
Athens University of Economics and Business
Athens, Greece
dds@aueb.gr
Επαλήθευση αλγορίθμων
Παράδειγμα
Είσοδος:
Α(1..Ν): πίνακας ακεραίων
N : ακέραιος
Έξοδος:
Β(1..Ν): πίνακας ακεραίων
Προϋποθέσεις:
Ν >= 1
Μετασυνθήκες:
Β(1..Ν) περιέχει τις τιμές του Α(1..Ν)
Μεταβλητές
Ι : Ακέραιος
I := 1
Όσο Ι <= Ν
Β(Ι) := Α(Ι)
Αναλοίωτη συνθήκη: Β(1..Ι) := Α(1..Ι)
Συνθήκη σύγκλισης: Ν - Ι
Ι := Ι + 1
Τέλος
Αποδοτικότητα των αλγορίθμων
- Η σημειογραφία Ο()
- Γραμμική ανίχνευση Ο(ν)
- Δυαδική ανίχνευση Ο(log ν)
- Διπλός βρόχος Ο(ν2)
- Κατώτερο (απόδειξης) πραγματικό και ανώτερο (αλγοριθμικό) κόστος
- Κόστος μνήμης
Πολυπλοκότητα
Μη υπολογισιμότητα
Τερματίζει(Πρόγραμμα, Δεδομένα)
Είσοδος: Πρόγραμμα, Δεδομένα
Έξοδος: Αληθές αν το πρόγραμμα τερματίζει με τα δεδομένα,
αλλιώς ψευδές.
Δοκιμή(Πρόγραμμα, Δεδομένα)
Αν Τερματίζει(Πρόγραμμα, Δεδομένα) Τότε
Όσο αληθές
Τέλος (Όσο)
Αλλιώς
Δοκιμή := ψευδές
Τέλος (Αν)
Δοκιμή(Δοκιμή ..., Δοκιμή ...)
Αλγοριθμική οικουμενικότητα
Πεντάδα Α = (Ι, Ο, S, λ, δ)
- Ι : Τιμές εισόδου
- Ο : Τιμές εξόδου
- S : Πεπερασμένο σύνολο εσωτερικών καταστάσεων
- λ : S X I -> S Συνάρτηση επόμενης κατάστασης
- δ : S X I -> O Συνάρτηση επόμενης τιμής εξόδου
Η μηχανή του Turing
- Πεπερασμένο αλφάβητο: Α
- Πεπερασμένο σύνολο καταστάσεων: Μ
- Άπειρη ταινία
- Κεφαλή γραφής και ανάγνωσης
- Διάγραμμα μετάπτωσης: (Α Χ Μ) -> (Α X {Δ, Α, Σ}) Χ Μ
Παραδείγματα
- Εγγραφή συμβόλου στο τέλος της ταινίας
- Αντιγραφή ταινίας
- Πρόσθεση
Η θέση των Church/Turing
Πιθανοτικοί αλγόριθμοι
Δειπνούντες φιλόσοφοι
Για πάντα
Πέτα νόμισμα και περίμενε το ανάλογο πηρούνι
Αν υπάρχει και το άλλο πηρούνι Τότε
πάρε το άλλο πηρούνι
φάε
Αλλιώς
Άσε τα πηρούνια
Τέλος
Τέλος
Γλώσσες προγραμματισμού
- Επιβάλλουν την έκφραση ενός αλγορίθμου με τυπική μορφή.
- Χρησιμοποιούνται άμεσα ή έμμεσα από τον υπολογιστή.
- Διαφορετικές γλώσσες διαθέτουν διαφορετικά επίπεδα και μέσα έκφρασης.
Γλώσσα μηχανής
89 D9
B8 01 00
83 F9 00
74 05
F7 E1
49
EB F6
Συμβολική γλώσσα
; Παραγοντικό του BX στο AX
MOV CX, BX ; Μετρητής στο CX
MOV AX, 1 ; Αρχική τιμή 1
LOOP: CMP CX, 0 ; Τέλος;
JZ DONE ; Ναι, έξοδος
MUL CX ; Όχι, πολλαπλασίασε ΑΧ με CX
DEC CX ; Επόμενη τιμή του CX
JMP LOOP ; Πίσω στο βρόχο
DONE:
Fortran 77
C Return factorial of N
C
FUNCTION IFACTORIAL(N)
INTEGER N
INTEGER IFACTORIAL
INTEGER IRESULT, I
IRESULT = 1
DO I = 1, N
IRESULT = IRESULT * I
END DO
IFACTORIAL = IRESULT
END
Fortran 95
! Return factorial of n
function factorial(n) result (nfac)
integer, intent(in) :: n
integer :: factorial
integer :: i
nfac = 1
do i = 1, n
nfac = nfac * i
end do
end function factorial
C
/* Παραγοντικό */
int
factorial(int n)
{
int result;
int count;
count = n;
result = 1;
while (count > 0) {
result = result * count;
count = count - 1;
}
return (result);
}
/* Παραγοντικό (με λιγότερες εντολές) */
int
factorial(int n)
{
int result = 1;
for (; n; n--)
result *= n;
return (result);
}
Prolog
factorial(0, 1).
% To N_Factorial είναι ισοδύναμο με Ν!
factorial(N, N_Factorial) :-
N > 0,
M is N - 1,
factorial(M, M_Factorial),
N_Factorial is M_Factorial * N.
Lisp
;; Επιστρέφει το παραγοντικό του n
(define (factorial n)
(if (= n 1)
1
(* n (factorial (- n 1)))))
Basic
500 REM Return factorial of N in variable FACT
510 FACT = 1
520 FOR I = 1 TO N
530 FACT = FACT * I
540 NEXT I
550 RETURN
Visual Basic
' Παραγοντικό του Ν
FUNCTION Factorial(N AS INTEGER) AS INTEGER
DIM Count AS INTEGER
DIM Result AS INTEGER
Count = N
Result = 1
WHILE Count > 0
Result = Result * Count
Count = Count - 1
WEND
END FUNCTION
Pascal
(* Παραγοντικό του Ν *)
function factorial(N : Integer) : Integer;
var
Count, Result : Integer;
begin
Count := N;
Result := 1;
While Count > 0 Do
begin
Result := Result * Count;
Count := Count - 1
end;
Factorial := Result
end (* Factorial *);
Java
// Υπολογισμός ν παραγοντικού
public int παραγοντικό(int ν) {
int αποτέλεσμα;
int μετρητής;
μετρητής = ν;
αποτέλεσμα = 1;
while (μετρητής > 0) {
αποτέλεσμα = αποτέλεσμα * μετρητής;
μετρητής = μετρητής - 1;
}
return (αποτέλεσμα);
}
Πίνακες
- Οι πίνακες (arrays) επιτρέπουν τη χρήση πολλών ομοίου τύπου στοιχείων.
- Συνήθως το στοιχείο i ενός πίνακα A προσδιορίζεται ως A[i] ή A(i).
- Μπορούν να οριστούν και πίνακες πολλαπλών διαστάσεων με στοιχεία
αντίστοιχα προσδιορισμένα ως A[i,j] κ.λπ.
- Συνήθως υλοποιούνται με τη διαδοχική φύλαξη των στοιχείων τους στη
μνήμη.
Παράδειγμα
class Sum {
static int sum(int a[]) {
int i, sum = 0;
for (i = 0; i < a.length; i++)
sum += a[i];
return sum;
}
static int testdata[] = {1, 2, 3, 4, 5};
public static void main(String args[]) {
System.out.println(sum(testdata));
}
}
Εγγραφές
- Οι εγγραφές (records) επιτρέπουν τον ομαδικό χειρισμό
διαφορετικού τύπου στοιχείων.
- Συνήθως το στοιχείο i μιας εγγραφής A προσδιορίζεται ως A.i
- Μπορούν να οριστούν και πίνακες που περιέχουν εγγραφές ή εγγραφές
που περιέχουν πίνακες.
- Συνήθως υλοποιούνται με τη διαδοχική φύλαξη των στοιχείων τους στη
μνήμη.
Παράδειγμα
struct point {
double x; /* X coordinate */
double y; /* Y coordinate */
};
struct customer {
char name[50]; /* Customer name */
int balance; /* Account balance */
};
struct customer customer_list[100];
main()
{
struct point a, b;
a.x = 5;
a.y = 9;
b.x = 12;
b.y = 19;
}
Δομές με δείκτη
- Οι δείκτες (pointers) αντιπροσωπεύουν δεδομένα
που έχουν καταχωρηθεί σε κάποια άλλα θέση της μνήμης.
Επιτρέπουν τον εύκολο ορισμό και χειρισμό σύνθετων δομών.
Τέτοιες δομές μπορεί να είναι
- Συνήθως τα περιεχόμενα ενός δείκτη p εκφράζονται ως *p (C, C++) ή p^ (Pascal).
- Στη γλώσσα Java όλα τα αντικείμενα εκφράζονται με τη χρήση ενός δείκτη.
- Οι δείκτες υλοποιούνται ως έμμεσες διευθύνσεις μνήμης.
Παράδειγμα (C)
struct s_int_list {
int val;
struct s_int_list *next;
};
Διαδικασίες, συναρτήσεις και τάξεις
Παράδειγμα συνάρτησης και διαδικασίας σε Pascal
program fun;
(* Παραγοντικό του Ν *)
function factorial(N : Integer) : Integer;
var
Count, Result : Integer;
begin
Count := N;
Result := 1;
While Count > 0 Do
begin
Result := Result * Count;
Count := Count - 1
end;
Factorial := Result
end (* Factorial *);
procedure clear_screen;
const number_of_lines = 24;
var i : integer;
begin
for i := 0 to number_of_lines do
writeln('');
end (*clear_screen*);
begin
clear_screen;
writeln(factorial(5));
end.
Παράδειγμα κλάσης σε Java
class Point extends Object {
private int x;
private int y;
public void MoveTo(int x, int y) {
this.x = x;
this.y = y;
}
public int GetX() {
return (x);
}
}
Αναδρομικές τεχνικές
- Διαδικασίες, συναρτήσεις και δομές που ορίζονται
αναδρομικά (recursively)
μπορούν εύκολα να ανιμετωπιστούν με τη χρήση αναδρομικών τεχνικών
προγραμματισμού.
Παράδειγμα
class Recurse {
static void russian_doll(int size) {
int i;
System.out.print("[");
for (i = 0; i < size; i++)
System.out.print("-");
System.out.println("]");
if (size > 1)
russian_doll(size - 1);
}
static int factorial(int n) {
if (n == 0)
return (1);
else
return (n * factorial(n - 1));
}
public static void main(String args[]) {
System.out.println(factorial(5));
russian_doll(10);
}
}
Αποτελέσματα
120
[----------]
[---------]
[--------]
[-------]
[------]
[-----]
[----]
[---]
[--]
[-]
Οι πύργοι του Ανόι
import java.util.*;
public class Hanoi {
static Stack A, B, C;
/** Display the contents of a collection with a given name */
static void showCollection(String name, Collection c) {
Iterator i;
System.out.print(name + ": ");
for (i = c.iterator(); i.hasNext(); )
System.out.print(i.next() + " ");
System.out.println();
}
/** Display the hanoi towers */
static void showConfiguration() {
showCollection("A", A);
showCollection("B", B);
showCollection("C", C);
System.out.println();
}
/** Move n blocks from to using tmp */
static void move(int n, Stack from, Stack to, Stack tmp) {
if (n == 1) {
to.push(from.pop());
showConfiguration();
} else {
move(n - 1, from, tmp, to);
to.push(from.pop());
showConfiguration();
move(n - 1, tmp, to, from);
}
}
public static void main(String args[]) {
final int N = 4;
A = new Stack();
B = new Stack();
C = new Stack();
for (int i = N; i > 0; i--)
A.push(new Integer(i));
showConfiguration();
move(N, A, C, B);
}
}
Βιβλιογραφία
- Μ. Μπεκάκος
Εισαγωγή στην πληροφορική. σ. 112-113
Οικονομικό Πανεπιστήμιο Αθηνών 1998.
- Andrew S. Tanenbaum
Δίκτυα Υπολογιστών. Τρίτη Έκδοση.
Παπασωτηρίου, 2000.
- Les Goldschlager και Andrew Lister
Εισαγωγή στη σύγχρονη επιστήμη των υπολογιστών. Κεφάλαιο 2.
Εκδόσεις Δίαυλος 1994.
- Peter Rechenberg.
Εισαγωγή στην Πληροφορική. σ. 112-133
Κλειδάριθμος, 1992.
- Alfred V. Aho, John E.
Hopcroft, and Jeffrey D. Ullman.
The
Design and Analysis of Computer Algorithms.
Addison-Wesley, 1974.
- J. Glenn Brookshear.
Computer Science, pages 167–224, 321–367.
Addison-Wesley, sixth edition, 2000.
- J. Glenn Brookshear.
Computer Science, pages 171–224, 319–358, 457–484.
Addison-Wesley, 8th edition, 2004.
- David Harel.
Algorithmics: the Spirit of Computing.
Addison-Wesley, 1987.
- George Pólya.
How to
Solve it.
Princeton University Press, second edition, 1957.
Published by Penguin Books 1990.
- Ravi Sethi.
Programming Languages: Concepts and Constructs.
Addison-Wesley, 1989.