Εισαγωγή - Πίνακες
Διομήδης Σπινέλλης
Τμήμα Διοικητικής Επιστήμης και Τεχνολογίας
Οικονομικό Πανεπιστήμιο Αθηνών
dds@aueb.gr
Καλώς ήρθατε
Γλώσσες προγραμματισμού και δομές δεδομένων
Τι περιλαμβάνει το μάθημα
- Εισαγωγή - Πίνακες
- Στοίβες
- Ουρές και δείκτες
- Συνδεδεμένες λίστες
- Δένδρα
- Γράφοι
- Αναζήτηση
- Ταξινόμηση
- Κατακερματισμός
- Τεχνικές αρχείων
- Αντικείμενα στη C++
- Κληρονομικότητα
- Αντικειμενοστρεφής σχεδιασμός με UML
- Η βιβλιοθήκη STL
- Λίστες στη Lisp
- Κατηγορήματα στην Prolog
- Παραλληλία στα Windows NT
- Οπτικός προγραμματισμός σε Automation Basic
- Ανασκόπηση - επανάληψη
Οι σημειώσεις
Αφηρημένοι τύποι δεδομένων
-
Οι αφηρημένοι τύποι δεδομένων (abstract data types)
(ΑΤΔ (ADT))
μας επιτρέπουν να διαχωρίσουμε τον τύπο των δεδομένων από την
υλοποίησή του.
- Σε έναν αφηρημένο τύπο δεδομένων καθορίζονται τα παρακάτω:
- o τρόπος φύλαξης των δεδομένων,
- ο ορατός τύπος,
- μέθοδοι δημιουργίας,
- μέθοδοι πρόσβασης,
- μέθοδοι μεταβολής,
- άλλες μέθοδοι σχετικές με τον τύπο,
- μέθοδοι απαλειφής.
- Η υλοποίηση αφηρημένων τύπων δεδομένων επιτρέπει την
αλλαγή του τρόπου αποθήκευσης ή του αλγορίθμου υλοποίησης
χωρίς την αλλαγή του προγράμματος
που χρησιμοποιεί τα δεδομένα.
- Στη C η υλοποίηση ενός ΑΤΔ γίνεται τυπικά με τον ορισμό των
μεθόδων και του τρόπου φύλαξης στο αρχείο επικεφαλίδας και
τον καθορισμό της υλοποίησης σε ξεχωριστό αρχείο C.
Παράδειγμα
Το παρακάτω παράδειγμα ορίζει έναν ΑΤΔ για σημεία σε δύο διαστάσεις.
Ο τελεστής -> στη χρήση structure_pointer->member είναι
συντομογραφία του (*structure_pointer).member.
Δηλώσεις: point.h
/*
* Abstract Data Type Definition file point.h
*/
typedef struct s_point *point;
point new_point(void);
int get_x_point(point p);
int get_y_point(point p);
void set_point(point p, int x, int y);
void delete_point(point p);
Ορισμοί: point.c
/*
* Abstract Data Type Implementation file point.c
*/
#include <stdlib.h>
#include "point.h"
struct s_point {
int x, y; /* Point coordinates */
};
point
new_point(void)
{
return (point)malloc(sizeof(struct s_point));
}
int
get_x_point(point p)
{
return (p->x);
}
int
get_y_point(point p);
{
return (p->y);
}
void
set_point(point p, int x, int y)
{
p->x = x;
p->y = y;
}
void
delete_point(point p)
{
free(p);
}
Σημείωση: στη γλώσσα C++ οι μέθοδοι new και delete παρέχονται από τη
γλώσσα, ενώ στις υπόλοιπες συναρτήσεις ο δείκτης p μεταφέρεται αυτόματα
Πίνακες
- Οι πίνακες (arrays) επιτρέπουν τη χρήση πολλών ομοίου
τύπου στοιχείων.
- Συνήθως το στοιχείο i ενός πίνακα A προσδιορίζεται ως A[i] ή A(i).
- Μπορούν να οριστούν και πίνακες πολλαπλών διαστάσεων με στοιχεία
αντίστοιχα προσδιορισμένα ως A[i][j] κ.λπ.
- Συνήθως υλοποιούνται με τη διαδοχική φύλαξη των στοιχείων τους στη
μνήμη.
- Στη C οι πίνακες σχετίζονται άμεσα με τους δείκτες αφού
η έκφραση p[i] είναι ίδια με την έκφραση *(p + i).
- Έτσι μπορεί να χρησιμοποιηθεί δυναμική μνήμη για το
δυναμικό καθορισμό της διάστασης του πίνακα.
Υλοποίηση πινάκων
- Πίνακες μιας διάστασης υλοποιούνται με τη διαδοχική φύλαξη των στοιχείων
στη μνήμη.
- Πίνακες δύο διαστάσεων υλοποιούνται με τη διαδοχική φύλαξη
των στοιχείων κάθε γραμμής (C, Pascal) ή κάθε στήλης (Fortran) στη
μνήμη.
- Ανάλογα υλοποιούνται και πίνακες με περισσότερες από δύο διαστάσεις.
- Έτσι το στοιχείο i,j ενός πίνακα Ν*Μ στοιχείων μεγέθους Κ βρίσκεται
στη θέση μνήμης Κ * (i * M + j).
- Πίνακες δύο και παραπάνω διαστάσεων μπορούν ακόμα να υλοποιηθούν με
τη χρήση πινάκων μιας διάστασης και δεικτών (C).
Το παρακάτω παράδειγμα ορίζει έναν ΑΤΔ για πίνακα ακεραίων δύο διαστάσεων
με δυναμικά οριζόμενες διαστάσεις.
Ο υπολογισμός της θέσης ενός στοιχείου γίνεται με τη απεικόνιση των
δύο διαστάσεων του πίνακα στη μία διάσταση της δυναμικής μνήμης.
Δηλώσεις: array2d.h
/*
* Abstract Data Type Definition file array2d.h
*/
typedef struct s_array2d *array2d;
array2d new_array2d(int rows, int cols);
void array2d_set_value(array2d a, int row, int col, int val);
int array2d_get_value(array2d a, int row, int col);
void array2d_delete(array2d a);
Ορισμοί: array2d.c
/*
* Abstract Data Type Implementation file array2d.c
* 2D -> 1D mapping implementation
*/
#include <stdlib.h>
#include <assert.h>
#include "array2d.h"
struct s_array2d {
int *values; /* Value storage */
int rows, cols; /* Dimensions */
};
array2d
new_array2d(int rows, int cols)
{
array2d a;
a = (array2d)malloc(sizeof(struct s_array2d));
assert(a != NULL);
a->values = (int *)malloc(rows * cols * sizeof(int));
assert(a->values != NULL);
a->rows = rows;
a->cols = cols;
}
void
array2d_set_value(array2d a, int row, int col, int val)
{
assert(row > 0 && row < a->rows);
assert(col > 0 && col < a->cols);
a->values[row * a->cols + col] = val;
}
int
array2d_get_value(array2d a, int row, int col)
{
assert(row > 0 && row < a->rows);
assert(col > 0 && col < a->cols);
return (a->values[row * a->cols + col]);
}
void
array2d_delete(array2d a)
{
free(a->values);
free(a);
}
Εναλλακτικά,
μπορούμε να
υλοποιήσουμε τον πίνακα δύο διαστάσεων με βάση έναν
πίνακα από δείκτες σε πίνακες μιας διάστασης.
Η τεχνική αυτή υλοποίησης μπορεί να είναι αποδοτικότερη
σε αρχιτεκτονικές όπου ο πολλαπλασιασμός διαρκεί
μεγαλύτερο χρόνο από την πρόσβαση στη μνήμη ή
σε περιπτώσεις όπου οι διαστάσεις των γραμμών του
πίνακα δεν είναι όλες ίσες.
Οι δηλώσεις του ΑΤΔ παραμένουν φυσικά οι ίδιες.
Ορισμοί: array2d.c
/*
* Abstract Data Type Implementation file array2d.c
* Array of pointer implementation
*/
#include <stdlib.h>
#include <assert.h>
#include "array2d.h"
struct s_array2d {
int **values; /* Value storage */
int rows, cols; /* Dimensions */
};
array2d
new_array2d(int rows, int cols)
{
array2d a;
int i;
a = (array2d)malloc(sizeof(struct s_array2d));
assert(a != NULL);
a->values = (int **)malloc(rows * sizeof(int *));
assert(a->values != NULL);
for (i = 0; i < rows; i++) {
a->values[i] = (int *)malloc(cols * sizeof(int));
assert(a->values[i] != NULL);
}
a->rows = rows;
a->cols = cols;
}
void
array2d_set_value(array2d a, int row, int col, int val)
{
assert(row > 0 && row < a->rows);
assert(col > 0 && col < a->cols);
a->values[row][col] = val;
}
int
array2d_get_value(array2d a, int row, int col)
{
assert(row > 0 && row < a->rows);
assert(col > 0 && col < a->cols);
return (a->values[row][col]);
}
void
array2d_delete(array2d a)
{
int i;
for (i = 0; i < a->rows; i++)
free(a->values[i]);
free(a->values);
free(a);
}
Ειδικές μορφές πινάκων
Οι παραπάνω μορφές πινάκων μπορούν να υλοποιηθούν πολύ κομψά με
τη χρήση ΑΤΔ.
Οι παρακάτω ορισμοί υλοποιούν
συμμετρικό πίνακα ακεραίων
που ορίζεται με πίνακα δεικτών.
Οι δηλώσεις του ΑΤΔ παραμένουν φυσικά οι ίδιες με αυτές στο
προηγούμενο παράδειγμα.
Ορισμοί: array2d.c
/*
* Abstract Data Type Implementation file array2d.c
* Array of pointer implementation
* Special case for symmetric arrays
*/
#include <stdlib.h>
#include <assert.h>
#include "sym.h"
struct s_array2d {
int **values; /* Value storage */
int rows, cols; /* Dimensions */
};
/*
* Given a pointer to a symmetric array and the coordinates of an
* an element return a pointer to its location. Elements on the left
* and below the diagonal are mapped using the diagonal as the axis of
* symmetry
*/
static int *
value_position(array2d a, int row, int col)
{
assert(row >= 0 && row < a->rows);
assert(col >= 0 && col < a->cols);
if (row > col)
return (&(a->values[col][row]));
else
return (&(a->values[row][col]));
}
array2d
new_array2d(int rows, int cols)
{
array2d a;
int i;
assert(rows == cols); /* Must be symmetric */
a = (array2d)malloc(sizeof(struct s_array2d));
assert(a != NULL);
a->values = (int **)malloc(rows * sizeof(int *));
assert(a->values != NULL);
for (i = 0; i < rows; i++) {
a->values[i] = (int *)malloc((i + 1) * sizeof(int));
assert(a->values[i] != NULL);
}
a->rows = rows;
a->cols = cols;
return (a);
}
void
set_val_array2d(array2d a, int row, int col, int val)
{
*value_position(a, row, col) = val;
}
int
get_val_array2d(array2d a, int row, int col)
{
return (*value_position(a, row, col));
}
void
delete_array2d(array2d a)
{
int i;
for (i = 0; i < a->rows; i++)
free(a->values[i]);
free(a->values);
free(a);
}
Συσχετιστικοί πίνακες
Βιβλιογραφία
- Χρήστος Κοίλιας
Δομές Δεδομένων και Οργανώσεις Αρχείων. σ. 33-44
Εκδόσεις Νέων Τεχνολογιών, 1993.
- Ellis Horowitz
Βασικές αρχές γλωσσών προγραμματισμού.
Δεύτερη αμερικάνικη έκδοση.
σ. 253-285 Εκδόσεις Κλειδάριθμος, 1984.
- Donald E. Knuth.
The Art of Computer Programming, volume 1 / Fundamental
Algorithms, pages 243–248.
Addison-Wesley, second edition, 1973.
- William H. Press,
Brian P. Flannery, Saul A. Teukolsky, and William T. Vetterling.
Numerical Recipes in C, pages 37–39.
Cambridge University Press, 1988.
- Robert Sedgewick.
Algorithms in C, pages 535–543.
Addison-Wesley, 1990.
- Niklaus Wirth.
Algorithms and Data Structures, pages 30–32.
Prentice–Hall, 1986.
Γενική βιβλιογραφία
- Harold Abelson,
Gerald Jay Sussman, and Jullie Sussman.
Structure and Interpretation of Computer Programs.
MIT Press, 1990.
- Alfred V. Aho, John E.
Hopcroft, and Jeffrey D. Ullman.
The
Design and Analysis of Computer Algorithms.
Addison-Wesley, 1974.
- Alfred V. Aho, John E.
Hopcroft, and Jeffrey D. Ullman.
Data Structures and Algorithms.
Addison-Wesley, 1983.
- James O. Coplien and
Douglas C. Schmidt.
Pattern Languages of Program Design.
Addison-Wesley, 1995.
- Margaret A. Ellis
and Bjarne Stroustrup.
The
Annotated C++ Reference Manual.
Addison-Wesley, 1990.
- Anthony J. Field and
Peter G. Harrison.
Functional Programming.
Addison-Wesley, 1988.
- David Harel.
Algorithmics: the Spirit of Computing.
Addison-Wesley, 1987.
- Donald E. Knuth.
The Art of Computer Programming, volume 1 / Fundamental
Algorithms.
Addison-Wesley, second edition, 1973.
- Donald E. Knuth.
The
Art of Computer Programming, volume 3 / Sorting and Searching.
Addison-Wesley, 1973.
- Richard A. O'Keefe.
The
Art of Prolog.
MIT Press, 1990.
- James Rumbaugh, Michael
Blaha, William Premerlani, Frederick Eddy, and William Lorensen.
Object-Oriented Modeling and Design.
Prentice-Hall, 1991.
- Peter H. Salus, editor.
Handbook of Programming Languages, volume I: Object-Oriented Programming
Languages.
Macmillan Technical Publishing, 1998.
- Peter H. Salus, editor.
Handbook of Programming Languages, volume II: Imperative Programming
Languages.
Macmillan Technical Publishing, 1998.
- Peter H. Salus, editor.
Handbook of Programming Languages, volume III: Little Languages and
Tools.
Macmillan Technical Publishing, 1998.
- Peter H. Salus, editor.
Handbook of Programming Languages, volume III: Functional and Logic
Programming Languages.
Macmillan Technical Publishing, 1998.
- Robert Sedgewick.
Algorithms in C.
Addison-Wesley, 1990.
- Ravi Sethi.
Programming Languages: Convepts and Constructs.
Addison-Wesley, 1989.
- Bjarne Stroustrup.
The
C++ Programming Language.
Addison-Wesley, third edition, 1997.
- Niklaus Wirth.
Algorithms + Datastructures = Programs.
Prentice–Hall, 1976.
- Niklaus Wirth.
Algorithms and Data Structures.
Prentice–Hall, 1986.
Ασκήσεις
Άσκηση 1 (προαιρετική)
- Να ορίσετε τον ΑΤΔ για ένα τριδιαγώνιο πίνακα αριθμών κινητής υποδιαστολής.
- Υλοποιήστε ένα πρόγραμμα ελέγχου του ΑΤΔ.