CASE STUDY 1: Πρόβληµα Να γραφεί ένα menu-driven πρόγραµµα για τη διαχείριση µίας ουράς πελατών που καταφθάνουν σε µία τράπεζα και περιµένουν να εξυπηρετηθούν. Το πρόγραµµα θα πρέπει να εισάγει ένα νέο πελάτη στο τέλος της ουράς, να εµφανίζει τον πελάτη που είναι πρώτος στην ουρά και να τον διαγράφει εφόσον έχει εξυπηρετηθεί. Πριν τον τερµατισµό του προγράµµατος, θα πρέπει να εµφανίζεται το πλήθος των πελατών που παραµένουν στην ουρά. Προκαταρκτική σχεδίαση Θα χρησιµοποιήσουµε τη δοµή της ουράς- η οποία θα υλοποιείται µε πίνακα και τις βασικές λειτουργίες εισαγωγής (enqueue) και εξαγωγής (dequeue) στοιχείου. Επίσης, θα ορίσουµε µία δοµή Pelatis, όπου θα αποθηκεύονται τα στοιχεία του πελάτη και θα αναπτύξουµε τις συναρτήσεις readpelatis (για το διάβασµα των στοιχείων ενός πελάτη), writepelatis (για την εµφάνιση των στοιχείων ενός πελάτη) και countpelates (για την εµφάνιση του πλήθους των πελατών που παραµένουν στην ουρά. Αλγόριθµος 1. Αρχικοποίηση της ουράς 2. Επανάλαβε 3. Εµφάνισε το µενού 4. ιάβασε την επιλογή 5. Εκτέλεσε τη λειτουργία που επιλέχθηκε µέχρι να επιλεγεί έξοδος από το µενού 6. Εµφάνισε το πλήθος των πελατών που παραµένουν στην ουρά Πρόγραµµα #include <stdio.h> #include <conio.h> #include <stdlib> #include <string.h> #define N 10
struct Pelatis int accno; char name[20]; ; void enqueue(struct Pelatis q[],int *r,struct Pelatis pel); void dequeue(struct Pelatis q[],int *f,int r); struct Pelatis readpelatis(); void writepelatis(struct Pelatis q[],int f, int r); void countpelates(int f, int r); main() int i, front, rear, choice, telos = 0; struct Pelatis q[n], pel; front = -1; rear = -1; do clrscr(); printf(" Menu\n"); printf(" ====\n"); printf("1.customer Arrival\n"); printf("2.customer Departure\n"); printf("3.first customer retrieval\n"); printf("4.exit\n"); printf("\nchoice?"); scanf("%d",&choice); switch (choice) case 1: pel=readpelatis(); enqueue(q,&rear,pel); break;
case 2: dequeue(q,&front,rear); break; case 3: writepelatis(q,front,rear); break; case 4: telos = 1; break; while (telos == 0); countpelates(front,rear); return 0; void enqueue(struct Pelatis q[],int *r,struct Pelatis pel) if ((*r) == N-1) printf("queue is full..."); getch(); q[++(*r)]=pel; void dequeue(struct Pelatis q[],int *f,int r) struct Pelatis pel; if ((*f) == r) printf("queue is empty...\n"); pel = q[++(*f)]; printf("diagrafi pelati %d ",pel.accno); getch();
struct Pelatis readpelatis() struct Pelatis pel; printf("dose ar. log.:"); scanf("%d",&pel.accno); printf("dose onoma pelati:"); scanf("%s",pel.name); return pel; void writepelatis(struct Pelatis q[],int f, int r) if (f == r) printf("queue is empty..."); printf("protos stin oura:\n"); printf("ar.log. = %d \n", q[++f].accno); printf("onoma = %s \n",q[f].name); getch(); void countpelates(int f, int r) int i, count = 0; if (f == r) printf("queue is empty..."); for (i=f+1; i<=r; i++) count++; printf("plithos pelaton stin oyra: %d\n",count); getch();
Έλεγχος προγράµµατος
CASE STUDY 2: Πρόβληµα Να γραφεί πρόγραµµα που να διαβάζει αριθµητικές παραστάσεις σε Επιθεµατική µορφή (Reverse Polish Notation) και να υπολογίζει την τιµή τους. Σε µία αριθµητική παράσταση σε RPN δεν υπάρχουν παρενθέσεις και οι τελεστές έπονται των τελεσταίων. Για παράδειγµα, η παράσταση σε RPN γίνεται 5 3 + 2 * Επίσης, η παράσταση γίνεται 8 5 3 + * 9 2 4 + * - 2 * ( 5 + 3 ) 8 * ( 5 + 3 ) 9 * ( 2 + 4 ) Προκαταρκτική σχεδίαση O υπολογισµός της παράστασης θα γίνεται µε χρήση µίας στοίβας υλοποιείται µε πίνακα. Η λειτουργία του προγράµµατος θα έχει ως εξής: η οποία θα Η παράσταση θα πληκτρολογείται σε µία γραµµή και το τέλος της θα ολοκληρώνεται µε το ENTER. Κάθε φορά που θα πληκτρολογείται ένας τελεσταίος θα τοποθετείται στην στοίβα. Κάθε φορά που θα πληκτρολογείται ένας τελεστής, θα εξάγονται δύο τελεσταίοι από την κορυφή της στοίβας, θα γίνεται η ανάλογη αριθµητική πράξη και το αποτέλεσµα θα τοποθετείται πίσω στη στοίβα. Θα χρησιµοποιήσουµε όπως προαναφέρθηκε - τη δοµή της στοίβας και τις βασικές λειτουργίες για την ώθηση (push) στοιχείου στη στοίβα και την απώθηση (pop) στοιχείου από τη στοίβα. Όταν ολοκληρωθεί η επεξεργασία όλης της παράστασης, το τελικό αποτέλεσµα είναι το µοναδικό που βρίσκεται στη στοίβα (θέση 0 του πίνακα). Αλγόριθµος 1. Αρχικοποίηση της στοίβας 2. Επανάλαβε 3. ιάβασε τον επόµενο χαρακτήρα της παράστασης
4. Αν είναι τελεστής 5. Εξαγωγή δύο στοιχείων από την κορυφή της στοίβας 6. Εκτέλεση της αντίστοιχης αριθµητικής πράξης 7. Τοποθέτηση του αποτελέσµατος πίσω στη στοίβα 8. Αν είναι τελεσταίος 9. Τοποθέτηση του αριθµού στην κορυφή της στοίβας µέχρι να τελειώσει η παράσταση 10.. Εµφάνισε το αποτέλεσµα της παράστασης Πρόγραµµα #include <stdio.h> #include <conio.h> #include <stdlib> #define N 10 void push(int stack[],int *t,int obj); int pop(int stack[],int *t); main() int stack[n], top; int i, num, obj1, obj2, res; char expr[100]; clrscr(); top = -1; printf("input expression, ENTER to quit:\n"); gets(expr); i = 0; while (expr[i]!='\0') if ( expr[i]== '+' expr[i]== '-' expr[i]== '*' expr[i]== '/') obj1 = pop(stack,&top); obj2 = pop(stack,&top); if (expr[i] == '+') res = obj2 + obj1;
if (expr[i] == '-') res = obj2 - obj1; if (expr[i] == '*') res = obj2 * obj1; res = obj2 / obj1; push(stack,&top,res); num = expr[i] - '0'; push(stack,&top,num); i++; if (top == 0) res = pop(stack,&top); printf("\nthe result of the expression is %d\n",res); printf("error in expression - too many operands."); getch(); return 0; void push(int stack[],int *t,int obj) if ((*t) == N-1) printf("stack overflow...\n"); getch(); abort(); stack[++(*t)] = obj;
int pop(int stack[],int *t) int r; if ((*t) < 0) printf("stack empty...\n"); printf("error in expression.\n"); getch(); abort(); r = stack[(*t)--]; return r; Έλεγχος προγράµµατος Θα τρέξουµε το πρόγραµµα δίνοντας σαν είσοδο δεδοµένων τις προηγούµενες παραστάσεις, οι οποίες έχουν ελεγθεί για την ορθότητά τους. Τα αποτελέσµατα που αναµένουµε είναι για την παράσταση 5 3 + 2 * αποτέλεσµα 16 και για την παράσταση 8 5 3 + * 9 2 4 + * - αποτέλεσµα 10.
CASE STUDY 3: Πρόβληµα Να γραφεί πρόγραµµα που να διαβάζει αριθµητικές παραστάσεις και να ελέγχει αν είναι σωστές ως προς τη χρήση των παρενθέσεων. Για παράδειγµα, η παράσταση (a + b) * (c + d) είναι σωστή, ενώ η παράσταση (a + b) * (c + d είναι λάθος, γιατί έχει περισσότερες παρενθέσεις που ανοίγουν (αριστερές) και η παράσταση (a + b) * c + d) είναι επίσης λάθος, γιατί έχει περισσότερες παρενθέσεις που κλείνουν (δεξιές). Προκαταρκτική σχεδίαση Η εξακρίβωση για την ορθότητα της παράστασης θα γίνεται µε χρήση µίας στοίβας η οποία θα υλοποιείται µε συνδεδεµένη λίστα. Ο λόγος που επιλέγουµε συνδεδεµένη λίστα είναι γιατί αν ορίσουµε τη στοίβα σαν ένα πίνακα χαρακτήρων, θα εκληφθεί ως αλφαριθµητικό και αυτό δυσχεραίνει την επεξεργασία του. Η λειτουργία του προγράµµατος θα έχει ως εξής: Η παράσταση θα πληκτρολογείται σε µία γραµµή και το τέλος της θα ολοκληρώνεται µε το ENTER. Κάθε φορά που θα διαβάζεται µία αριστερή παρένθεση θα τοποθετείται στη στοίβα. Κάθε φορά που θα διαβάζεται µία δεξιά παρένθεση, θα εξάγεται µία αριστερή παρένθεση από την κορυφή της στοίβας. Θα χρησιµοποιήσουµε όπως προαναφέρθηκε - τη δοµή της στοίβας και τις βασικές λειτουργίες για την ώθηση (push) στοιχείου στη στοίβα και την απώθηση (pop) στοιχείου από τη στοίβα. Όταν ολοκληρωθεί η επεξεργασία όλης της παράστασης, η στοίβα θα πρέπει να είναι άδεια για να έχουµε σωστό αποτέλεσµα.
Αλγόριθµος 1. Αρχικοποίηση της στοίβας 2. Επανάλαβε 3. ιάβασε τον επόµενο χαρακτήρα της παράστασης 4. Αν είναι αριστερή παρένθεση 5. Τοποθέτηση της παρένθεσης στην κορυφή της στοίβας 6. Αν είναι δεξιά παρένθεση 7. Αν η στοίβα δεν είναι άδεια 8. Εξαγωγή µίας αριστερής παρένθεσης από την κορυφή της στοίβας 9. Αν η στοίβα είναι άδεια 10. Τερµατισµός επεξεργασίας, η παράσταση είναι λάθος µέχρι να τελειώσει η παράσταση ή να διαπιστωθεί ότι είναι λάθος 11. Αν η στοίβα είναι άδεια 12. Αν δεν τέλειωσε το διάβασµα της παράστασης 13. Εµφάνισε λάθος, περισσότερες δεξιές παρενθέσεις 14. Αν τέλειωσε το διάβασµα της παράστασης 15. Εµφάνισε σωστή παράσταση 16. Αν η στοίβα δεν είναι άδεια 17. Εµφάνισε λάθος, περισσότερες αριστερές παρενθέσεις Πρόγραµµα #include <stdio.h> #include <conio.h> #include <stdlib> struct node int data; struct node *next; ; typedef struct node * PTR; PTR push(char obj, PTR t); PTR pop(ptr t, char *obj);
main() PTR top; char expr[30], ch; int i, error; clrscr(); top = NULL; printf("input expression, ENTER to quit:\n"); gets(expr); error = 0; i = 0; while (expr[i]!='\0' && error == 0) switch (expr[i]) case '(': top = push(expr[i],top); break; case ')': if (top == NULL) error = 1; top = pop(top,&ch); break; i++; if (top == NULL) if (error == 0) printf(" ->Correct expression."); printf(" ->Error. Too many right parentheses."); printf(" ->Error. Too many left parentheses."); getch(); return 0;
PTR push(char obj, PTR t) PTR newnode; newnode = malloc(sizeof(struct node)); newnode->data = obj; newnode->next = t; t = newnode; return t; PTR pop(ptr t, char *obj) PTR p; if (t == NULL) printf("stack empty.\n"); getch(); p = t; t = t->next; *obj = p->data; free(p); return t; Έλεγχος προγράµµατος Θα τρέξουµε το πρόγραµµα δίνοντας σαν είσοδο δεδοµένων τις προηγούµενες παραστάσεις όπου τα αναµενόµενα αποτελέσµατα είναι (a + b) * (c + d) =>σωστή παράσταση (a + b) * (c + d =>λάθος, περισσότερες αριστερές παρενθέσεις (a + b) * c + d) =>λάθος, περισσότερες δεξιές παρενθέσεις
CASE STUDY 4: Πρόβληµα Να γραφεί πρόγραµµα που να αναζητά σε ένα πλήθος πελατών µιας µεγάλης ασφαλιστικής εταιρίας, τα στοιχεία κάποιου συγκεκριµένου πελάτη, τα οποία είναι Αριθµός µητρώου Όνοµα Τηλέφωνο Οι πληροφορίες είναι καταχωρηµένες σε αύξουσα σειρά, βάσει των αριθµών µητρώου. Επειδή η εταρία είναι αρκετά µεγάλη, δεν ενδείκνυται να εφαρµόσουµε σειριακή αναζήτηση. Να γραφεί ένας αλγόριθµος αναζήτησης που εκµεταλεύεται το γεγονός ότι οι πελάτες είναι ταξινοµηµένοι. Προκαταρκτική σχεδίαση Ο αλγόριθµος που αναζητούµε είναι η υαδική Αναζήτηση. Θα υποθέσουµε ότι τα στοιχεία των πελατών αποθηκεύονται σε ένα πίνακα, ταξινοµηµένα ως προς τους αριθµούς µητρώου. Το πλεονέκτηµα της µεθόδου αυτής έγκειται στο γεγονός ότι κάθε φορά που εξετάζουµε ένα στοιχείο, τα µισά στοιχεία µπορούν να απορριφθούν και να συνεχίσουµε την αναζήτηση µε το µισό πίνακα.. Για παράδειγµα, αν το µέγεθος του πίνακα είναι 1000, µετά την πρώτη εξέταση πολυπλοκότητα του αλγορίθµου της υαδικής Αναζήτησης είναι Ο(log 2 N). Για την αποθήκευση των πληροφοριών ενός πελάτη θα χρησιµοποιηθεί µια δοµή (struct) µε τρία πεδία. Ο πίνακας θα είναι πίνακας δοµών και θα παίρνει τα δεδοµένα εισόδου στη δήλωσή του. Για να απλουστεύσουµε τη διαδικασία, θα ορίσουµε ένα µικρό πίνακα 10 θέσεων. Ο αλγόριθµος της υαδικής Αναζήτησης που θα εφαρµοστεί είναι αναδροµικός. Χρησιµοποιούνται τρεις µεταβλητές left, right και mid που αντιστοιχούν στην πρώτη, στην τελευταία και στη µεσαία θέση του πίνακα. Ο τύπος υπολογισµού της µέσης του πίνακα είναι mid = (left + right) / 2
Αλγόριθµος 1. Υπολόγισε τη µέση του πίνακα 2. Αν η τελευταία θέση είναι µικρότερη της πρώτης τότε 3. Επέστρεψε την τιµή -1 4. Αν το στοιχείο που αναζητούµε βρίσκεται στη µεσαία θέση τότε 5. Επέστρεψε τη µεσαία θέση 6. Αν το στοιχείο που αναζητούµε είναι µικρότερο από το στοιχείο της µεσαίας θέσης 7. Εξετάζουµε τον υποπίνακα µε άκρα left..mid-1 8. Αν το στοιχείο που αναζητούµε είναι µεγαλύτερο από το στοιχείο της µεσαίας θέσης 9. Εξετάζουµε τον υποπίνακα µε άκρα mid+1..right 10. Αν η τιµή που επιστράφηκε είναι -1 11. Εµφανίζουµε µήνυµα ανεπιτυχούς αναζήτησης 12. Αν η τιµή είναι διαφορετική του -1 13. Εµφανιζουµε τα στοιχεία του πελάτη Πρόγραµµα #include <stdio.h> #include <conio.h> #define N 10 struct persondetails int am; char onoma[20]; char tel[10]; ; typedef struct persondetails Person; int binarysearch(int left, int right, Person p[], int x);
main() Person p[n] = 100, "ANAGNOSTOU", "2310923445", 200, "BLAXAKIS", "2310566433", 300, "GEORGIOU", "2310899223", 400, "DIMITRIADIS", "2310345677", 500, "EYAGGELOPOULOS", "2310778654", 600, "ZHSH", "2310783211", 700, "IAKOVIDOU", "2310578990", 800, "KOSTA", "2310234500", 900, "LAMPIRIS", "2310245655", 999, "NIKOLAOU", "2310997445"; int x, pos; clrscr(); printf("dose am gia anazitisi:"); scanf("%i",&x); pos = binarysearch(0,n-1,p,x); printf("\nbinary search:\n"); if (pos == -1) printf("the number was not found!\n"); printf("the number was found at position %i\n",pos); printf("a.m.: %d \n", p[pos].am); printf("onoma: %s \n", p[pos].onoma); printf("tel.: %s \n", p[pos].tel); getch(); return 0; int binarysearch(int left, int right, Person p[], int x) int mid, pos; if (left > right) pos = -1;
mid = (left + right) / 2; if (p[mid].am == x) pos = mid; if (x < p[mid].am) pos = binarysearch(left,mid-1,p,x); pos = binarysearch(mid+1,right,p,x); return pos; Έλεγχος προγράµµατος
CASE STUDY 5: Πρόβληµα Να γραφεί ένα menu-driven πρόγραµµα για τη διαχείριση ενός υαδικού ένδρου Αναζήτησης, στους κόµβους του οποίου βρίσκονται αποθηκευµένες πληροφορίες πελατών µιας µεγάλης ασφαλιστικής εταιρίας, τα οποία είναι Αριθµός µητρώου Όνοµα Τηλέφωνο Οι πληροφορίες τροφοδοτούνται στο δένδρο από ένα πίνακα. Ο σκοπός της εφαρµογής είναι να µπορούµε να εµφανιζουµε τις πληροφορίες των πελατών σε αύξουσα σειρά ως προς τον αριθµό µητρώου και να εφαρµόζουµε επιλεκτικές αναζητήσεις δίνοντας για παράδειγµα τον αριθµό µητρώου κάποιου πελάτη. Προκαταρκτική σχεδίαση Θα υποθέσουµε ότι τα στοιχεία των πελατών αποθηκεύονται σε ένα πίνακα, χωρίς καµία συγκεκριµένη σειρά. ιαβάζονται µε τη σειρά από τον πίνακα και τοποθετούνται στο υαδικό ένδρο Αναζήτησης µε τη συνάρτηση insert_node. Ο πίνακας θα είναι πίνακας δοµών και θα παίρνει τα δεδοµένα εισόδου στη δήλωσή του. Για να απλουστεύσουµε τη διαδικασία, θα ορίσουµε ένα µικρό πίνακα 10 θέσεων. Σύµφωνα µε τα δεδοµένα που ορίζονται στο πρόγραµµα, η σειρά των πελατών όπως τοποθετούνται στο δένδρο είναι, αναφέροντας µόνον τους αριθµούς µητρώου: 500, 300, 700, 200, 400, 600, 900, 100, 800, 999 Eποµένως, το αντίστοιχο υαδικό ένδρο που θα προκύψει είναι: 500 300 700 200 400 600 900 100 800 999
Επίσης, στο πρόγραµµα χρησιµοποιούνται τρεις αναδροµικές συναρτήσεις για την επίσκεψη των κόµβων του δένδρου. Αυτές είναι οι preorder_traversal inorder_traversal postorder_traversal Η συνάρτηση που παρουσιάζει περισσότερο ενδιαφέρον είναι η inorder_traversal γιατί εµφανίζει τα περιεχόµενα του δένδρου ταξινοµηµένα. Τέλος, χρησιµοποιείται ακόµη µία αναδροµική συνάρτηση, η find_node για την αναζήτηση κάποιου συγκεκριµένου πελάτη στο δένδρο. Αλγόριθµος 1. Τοποθέτησε τα στοιχεία των πελατών από τον πίνακα στο δένδρο 2. Επανάλαβε 3. Εµφάνισε το µενού 4. ώσε µία επιλογή 5. Εκτέλεσε τη λειτουργία σύµφωνα µε την επιλογή Μέχρι να επιλεγεί έξοδος από το µενού Πρόγραµµα #include <stdio.h> #include <conio.h> #include <stdlib.h> #include <string.h> #define N 10 struct persondetails int am; char onoma[20]; char tel[10]; ; typedef struct persondetails Person;
struct treenode Person data; struct treenode *left; struct treenode *right; ; typedef struct treenode * PTR; void insert_node(ptr *pt, Person p); void preorder_traversal(ptr t); void inorder_traversal(ptr t); void postorder_traversal(ptr t); void find_node(ptr t, int n, int i); main() Person p[n]= 500, "EYAGGELOPOULOS ", "2310778654", 300, "GEORGIOU ", "2310899223", 700, "IAKOVIDOU ", "2310578990", 200, "BLAXAKIS ", "2310566433", 400, "DIMITRIADIS ", "2310345677", 600, "ZHSH ", "2310783211", 900, "LAMPIRIS ", "2310245655", 100, "ANAGNOSTOU ", "2310923445", 800, "KOSTA ", "2310234500", 999, "NIKOLAOU ", "2310997445"; int choice, armit, i; PTR bt; clrscr(); bt = NULL; for(i=0; i<n; i++) insert_node(&bt,p[i]); i = 0; do clrscr();
printf(" M E N U\n"); printf(" =======\n"); printf("1. Preorder traversal\n"); printf("2. Inorder traversal\n"); printf("3. Postorder traversal\n"); printf("4. Tree search\n"); printf("5. EXIT\n"); printf("\n Choice?"); scanf("%d",&choice); switch (choice) case 1: printf("\n"); printf("pre-order:\n"); preorder_traversal(bt); break; case 2: printf("\n"); printf("in-order:\n"); inorder_traversal(bt); break; case 3: printf("\n"); printf("post-order:\n"); postorder_traversal(bt); break; case 4: printf("dose am gia anazitisi:"); scanf("%d",&armit); find_node(bt,armit,i); break; case 5: printf("end of program...press ENTER"); break; getch(); while (choice!= 5); return 0;
void insert_node(ptr *pt, Person x) PTR t; t = *pt; if (t==null) t = malloc(sizeof (struct treenode)); t->data = x; t->left = NULL; t->right = NULL; if (x.am < t->data.am) insert_node(&(t->left),x); insert_node(&(t->right),x); *pt = t; void preorder_traversal(ptr t) if (t!=null) printf(" %d ", t->data.am); printf(" %s ",t->data.onoma); printf(" %s \n",t->data.tel); printf("\n"); preorder_traversal(t->left); preorder_traversal(t->right); void inorder_traversal(ptr t) if (t!=null) inorder_traversal(t->left); printf(" %d ", t->data.am); printf(" %s ",t->data.onoma);
printf(" %s \n",t->data.tel); printf("\n"); inorder_traversal(t->right); void postorder_traversal(ptr t) if (t!=null) postorder_traversal(t->left); postorder_traversal(t->right); printf(" %d ", t->data.am); printf(" %s ",t->data.onoma); printf(" %s \n",t->data.tel); printf("\n"); void find_node(ptr t, int n, int i) i++; if (t==null) printf("\nden vrethike.\n"); printf("plithos anazitiseon: %d \n",i); if (t->data.am == n) printf("\nvrethike!!!\n"); printf("plithos anazitiseon: %d \n",i); printf(" %d \n", t->data.am); printf(" %s \n",t->data.onoma); printf(" %s \n",t->data.tel); printf("\n"); if (n < t->data.am) find_node(t->left,n,i);
find_node(t->right,n,i); Έλεγχος προγράµµατος