ΕΙΣΑΓΩΓΗ ΣΤΟΝ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟ Ενδεικτικές Απαντήσεις Εξετάσεων Α' Περιόδου 2011 Θέµα 1 (α') 1 - i 2 - ii 3 - iii 4 - iv 5 - v 6 - vi 7 - vii 8 - viii 9 - ix 10 - x Το αποτέλεσµα είναι η αντιστοιχία των αριθµών από το 1 έως το 10, για το αραβικό και το ρωµαϊκό σύστηµα αρίθµησης. (β') Η realloc χρειάζεται όταν θέλουµε να τροποποιήσουµε (µειώσουµε ή αυξήσουµε) το µέγεθος δυναµικά δεσµευµένης µνήµης στον σωρό. Το πρόβληµα που υπάρχει είναι ότι όταν θέλουµε να αυξήσουµε τη µνήµη και η επιπλέον ποσότητα που θέλουµε δεν υπάρχει συνεχόµενη µετά την ήδη δεσµευµένη. Τότε, πρέπει να γίνει αντιγραφής της υπάρχουσας αλλού, ώστε να µπορέσει να επεκταθεί, κάτι που µπορεί να οδηγήσει σε αναποτελεσµατικότητα, ιδιαίτερα όταν η αρχική µνήµη είναι µεγάλη και η realloc γίνεται επαναλαµβανόµενα. (γ') Ο στόχος αυτού του τµήµατος προγράµµατος είναι η αντιγραφή των περιεχοµένων του αρχείου που αντιστοιχεί στον δείκτη αρχείου ifp στο αρχείο µε δείκτη αρχείου ofp. Η διαφορά στο µέγεθος του buf επιδρά στο πλήθος των επαναλήψεων της while. Μεγαλύτερο µέγεθος του buf σηµαίνει λιγότερες επαναλήψεις, και αντίστροφα. (δ') i) Η γρήγορη µέθοδος ταξινόµησης έχει καλύτερη µέση πολυπλοκότητα από τη µέθοδο της εισαγωγής, δηλαδή O(nlogn) έναντι O(n^2). ii) Η µέθοδος της συγχώνευσης έχει καλύτερη χείριστη πολυπλοκότητα από τη γρήγορη µέθοδο, δηλαδή O(nlogn) έναντι O(n^2). iii) Η µέθοδος του σωρού και η µέθοδος της συγχώνευσης έχουν την ίδια πολυπλοκότητα. ιαφέρουν στο ότι η µέθοδος του σωρού είναι επαναληπτική, ενώ η µέθοδος της συγχώνευσης είναι διπλά αναδροµική. Υπ' αυτή την έννοια, είναι προτιµότερη η χρήση της µεθόδου του σωρού, αν και η διπλή αναδροµή της µεθόδου της συγχώνευσης δεν είναι τόσο µεγάλο πρόβληµα, γιατί το βάθος του δέντρου, άρα και το πλήθος των κλήσεων συναρτήσεων στη στοίβα, είναι της τάξης του logn.
Θέµα 2 (α') typedef struct dlistnode *DListptr; struct dlistnode { int value; DListptr next; DListptr prev; ; void print_dlist_bf(dlistptr dlist) { if (dlist == NULL) printf("end"); else { printf("%d --> ", dlist->value); while (dlist->next!= NULL) { dlist = dlist->next; printf("%d --> ", dlist->value); printf("end --> %d", dlist->value); while (dlist->prev!= NULL) { dlist = dlist->prev; printf(" --> %d", dlist->value); (β') void insert_at_start_dlist(dlistptr *ptraddr, int v) { DListptr templist; templist = *ptraddr; *ptraddr = malloc(sizeof(struct dlistnode)); (*ptraddr)->value = v; (*ptraddr)->next = templist; (*ptraddr)->prev = NULL; if (templist!= NULL) templist->prev = *ptraddr; (γ') Πρωτότυπο: int delete_nth_dlist(dlistptr *, int) Η συνάρτηση επιστρέφει 1 όταν είναι εφικτή η διαγραφή, αλλιώς 0. Το πρώτο όρισµα είναι η διεύθυνση του δείκτη στο πρώτο στοιχείο της λίστας και το δεύτερο όρισµα είναι το N. Κλήση: delete_nth_dlist(500, 3) Λίστα µετά τη διαγραφή: 500 1000 1100 1300 +----+ +----+----+----+ +----+----+----+ +----+----+----+ 1000 --> 87 1100 NULL 23 1300 1000 10 NULL 1100 +----+ +----+----+----+ +----+----+----+ +----+----+----+ ^ ^^ ^ +-----+ +-----+ +------+ +------+
Θέµα 3 #include <stdio.h> #include <stdlib.h> int main(int argc, char *argv[]) { int a, b, c, n, lim; if (argc == 1) lim = atoi(argv[1]); for (n = 1 ; n <= lim ; n++) { /* Έστω n^3 = a^3 + b^3 + c^3 */ for (a = 1 ; 3*a*a*a <= n*n*n ; a++) { /* Το a κυµαίνεται από 1 έως µία τιµή τέτοια ώστε a^3 <= (n^3)/3 */ for (b = a ; 2*b*b*b <= n*n*n - a*a*a ; b++) { /* Το b κυµαίνεται από a έως µία τιµή τέτοια ώστε b^3 <= (n^3 - a^3)/2 */ for (c = b ; c*c*c <= n*n*n - a*a*a - b*b*b ; c++) /* Το c κυµαίνεται από b έως µία τιµή τέτοια ώστε c^3 <= n^3 - a^3 - b^3 */ if (n*n*n == a*a*a + b*b*b + c*c*c) /* Έλεγχος */ printf("%d^3 = %d^3 + %d^3 + %d^3\n", n, a, b, c); return 0;
Θέµα 4 #include <stdio.h> #include <stdlib.h> #include <time.h> /* Αποσχολιάστε την παρακάτω γραµµή για την έκδοση µε κατακόρυφη εκτύπωση */ /* #define VERT */ #ifndef VERT int main(int argc, char *argv[]) /* Έκδοση µε οριζόντια εκτύπωση */ { int i, j, k, n, m, d, ***grid; /* Ορίζουµε έναν 3-διάστατο πίνακα, αφού θα χρειαστούµε στο τέλος όλες τις καταστάσεις για να τις εκτυπώσουµε οριζόντια */ char beats, kinds[] = "RSP"; long seed; seed = time(null); scanf("%d %d %d", &n, &m, &d); if ((grid = malloc((d+1) * sizeof(int **))) == NULL) for (i = 0 ; i <= d ; i++) { if ((grid[i] = malloc(n * sizeof(int *))) == NULL) for (j = 0 ; j < n ; j++) if ((grid[i][j] = malloc(m * sizeof(int))) == NULL) if (argc > 1) seed = atoi(argv[1]); srand ((unsigned int) seed); for (j = 0 ; j < n ; j++) /* ηµιουργία τυχαίας αρχικής κατάστασης */ for (k = 0 ; k < m ; k++) grid[0][j][k] = kinds[rand() % 3]; for (i = 1 ; i <= d ; i++) for (j = 0 ; j < n ; j++) for (k = 0 ; k < m ; k++) { grid[i][j][k] = grid[i-1][j][k]; /* Αντιγραφή τρέχουσας κατάστασης στην επόµενη */ switch (grid[i-1][j][k]) { case 'R': beats = 'P'; /* Το χαρτί κερδίζει την πέτρα */ case 'S': beats = 'R'; /* Η πέτρα κερδίζει το ψαλίδι */ case 'P': beats = 'S'; /* Το ψαλίδι κερδίζει το χαρτί */ if ((k < m-1 && grid[i-1][j][k+1] == beats) (j < n-1 && grid[i-1][j+1][k] == beats) (k > 0 && grid[i-1][j][k-1] == beats) (j > 0 && grid[i-1][j-1][k] == beats)) grid[i][j][k] = beats; /* Αλλαγή γειτονικού κελιού */ for (i = 1 ; i <= d ; i++) { /* Εκτύπωση όλων των καταστάσεων */ printf("day %-2d", i); for (j = 0 ; j <= m ; j++) printf(" "); for (j = 0 ; j < n ; j++) { for (i = 0 ; i <= d ; i++) { if (i > 0) { if (j == 0) printf(" ----> "); else printf(" ");
for (k = 0 ; k < m ; k++) putchar(grid[i][j][k]); for (i = 0 ; i < d ; i++) { for (j = 0 ; j < n ; j++) free(grid[i][j]); free(grid[i]); free(grid); return 0; #else int main(int argc, char *argv[]) /* Έκδοση µε κατακόρυφη εκτύπωση */ { int i, j, day, n, m, d, **grid, **newgrid, **temp; /* Ορίζουµε δύο 2-διάστατους πίνακες, για να κρατάµε την τρέχουσα κατάσταση και την επόµενή της */ char beats, kinds[] = "RSP"; long seed; seed = time(null); scanf("%d %d %d", &n, &m, &d); if ((grid = malloc(n * sizeof(int *))) == NULL) if ((newgrid = malloc(n * sizeof(int *))) == NULL) for (i = 0 ; i < n ; i++) { if ((grid[i] = malloc(m * sizeof(int))) == NULL) if ((newgrid[i] = malloc(m * sizeof(int))) == NULL) if (argc > 1) seed = atoi(argv[1]); srand ((unsigned int) seed); for (i = 0 ; i < n ; i++) /* ηµιουργία τυχαίας αρχικής κατάστασης */ for (j = 0 ; j < m ; j++) grid[i][j] = kinds[rand() % 3]; for (day = 1 ; day <= d+1 ; day++) { for (i = 0 ; i < n ; i++) { /* Εκτύπωση τρέχουσας κατάστασης */ for (j = 0 ; j < m ; j++) printf("%c", grid[i][j]); if (day < d+1) printf("day %d\n", day); for (i = 0 ; i < n ; i++) for (j = 0 ; j < m ; j++) { newgrid[i][j] = grid[i][j]; /* Αντιγραφή τρέχουσας κατάστασης στην επόµενη */ switch (grid[i][j]) { /* Τι κερδίζει τι */ case 'R': beats = 'P'; case 'S': beats = 'R'; case 'P': beats = 'S'; if ((j < m-1 && grid[i][j+1] == beats) (i < n-1 && grid[i+1][j] == beats) (j > 0 && grid[i][j-1] == beats) (i > 0 && grid[i-1][j] == beats)) newgrid[i][j] = beats; /* Αλλαγή γειτονικού κελιού */
temp = grid; /* Επόµενη κατάσταση είναι η τρέχουσα */ grid = newgrid; newgrid = temp; for (i = 0 ; i < n ; i++) { free(grid[i]); free(newgrid[i]); free(grid); free(newgrid); return 0; #endif