Εισαγωγή - Πίνακες

Διομήδης Σπινέλλης
Τμήμα Διοικητικής Επιστήμης και Τεχνολογίας
Οικονομικό Πανεπιστήμιο Αθηνών
dds@aueb.gr

Καλώς ήρθατε

Γλώσσες προγραμματισμού και δομές δεδομένων

Τι περιλαμβάνει το μάθημα

  1. Εισαγωγή - Πίνακες
  2. Στοίβες
  3. Ουρές και δείκτες
  4. Συνδεδεμένες λίστες
  5. Δένδρα
  6. Γράφοι
  7. Αναζήτηση
  8. Ταξινόμηση
  9. Κατακερματισμός
  10. Τεχνικές αρχείων
  11. Αντικείμενα στη C++
  12. Κληρονομικότητα
  13. Αντικειμενοστρεφής σχεδιασμός με UML
  14. Η βιβλιοθήκη STL
  15. Λίστες στη Lisp
  16. Κατηγορήματα στην Prolog
  17. Παραλληλία στα Windows NT
  18. Οπτικός προγραμματισμός σε Automation Basic
  19. Ανασκόπηση - επανάληψη

Οι σημειώσεις

Αφηρημένοι τύποι δεδομένων

Παράδειγμα

Το παρακάτω παράδειγμα ορίζει έναν ΑΤΔ για σημεία σε δύο διαστάσεις. Ο τελεστής -> στη χρήση 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 μεταφέρεται αυτόματα

Πίνακες

Υλοποίηση πινάκων

Το παρακάτω παράδειγμα ορίζει έναν ΑΤΔ για πίνακα ακεραίων δύο διαστάσεων με δυναμικά οριζόμενες διαστάσεις. Ο υπολογισμός της θέσης ενός στοιχείου γίνεται με τη απεικόνιση των δύο διαστάσεων του πίνακα στη μία διάσταση της δυναμικής μνήμης.

Δηλώσεις: 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);
}

Συσχετιστικοί πίνακες

Βιβλιογραφία

Γενική βιβλιογραφία

Ασκήσεις

Άσκηση 1 (προαιρετική)

  1. Να ορίσετε τον ΑΤΔ για ένα τριδιαγώνιο πίνακα αριθμών κινητής υποδιαστολής.
  2. Υλοποιήστε ένα πρόγραμμα ελέγχου του ΑΤΔ.