ΔΟΜΕΣ ΔΕΔΟΜΕΝΩΝ
description
Transcript of ΔΟΜΕΣ ΔΕΔΟΜΕΝΩΝ
ΔΟΜΕΣ ΔΕΔΟΜΕΝΩΝ
Φροντιστήρια
Εισηγητής: Σπύρος Αργυρόπουλος
Μέλος ΕΤΕΠΕργαστήριο Προγραμματισμού & Τεχνολογίας Ευφυών Συστημάτων
Abstract Data Types
Abstract Data Type (ADT): a definition for a data type solely in terms of a set of values and a set of operations on that data type.
Each ADT operation is defined by its inputs and outputs.
Encapsulation: Hide implementation details.
Data Structure
• A data structure is the physical implementation of an ADT.– Each operation associated with the ADT is
implemented by one or more subroutines in the implementation.
• Data structure usually refers to an organization for data in main memory.
• File structure is an organization for data on peripheral storage, such as a disk drive.
Logical vs. Physical Form
Data items have both a logical and a physical form.
Logical form: definition of the data item within an ADT.– Ex: Integers in mathematical sense: +, -
Physical form: implementation of the data item within a data structure.– Ex: 16/32 bit integers, overflow.
Data Type
ADT:TypeOperations
Data Items: Logical Form
Data Items: Physical Form
Data Structure:Storage SpaceSubroutines
C++
• Πρότυπα συναρτήσεων :return_type function_name(type1 name1, type2 name2, ...);
• Δηλώσεις σταθερών : const double PI = 3.1415;
char *strcpy(char *target, const char *source);
C++ (συνέχεια)
• Μεταβίβαση παραμέτρων δια μέσου αναφοράς:int string2int(char *string, int &flag); int result, status;result = string2int("5", status);
if (status == 0) { ...
• Υπερφόρτωση ονομάτων (overloading):Παράδειγμα
C++ (συνέχεια)
• Δηλώσεις μεταβλητών σε οποιοδήποτε σημείο του κώδικα
• Εξ ορισμού τιμές για παραμέτρους συναρτήσεων (default values):FILE *open_file(const char *path, const char *mode = "r"){
return fopen(path, mode);}
C++ (συνέχεια)
• Συναρτήσεις inline :inline int max(int x, int y) { return x > y ? x : y; } inline double max(double x, double y) { return x > y ? x : y; }
• Ορισμός τελεστώνΠαράδειγμα
• Τελεστές εισόδου, εξόδου (cin, cout, cerr)Παράδειγμα
C++ (συνέχεια)
• Σχόλια:i++; // Το i αυξάνεται κατά 1
j++; // Το ίδιο και το j
C++ (συνέχεια)
• Κλάσεις αντικειμένων (Classes)– Private, public, protected members– Methods & inline functions– Constructor, destructor– Copy constructor– Τελεστής ανάθεσης– Δείκτης this– Τελεστές new & delete (γενικό παράδειγμα)
C++ (συνέχεια)
• Κληρονομικότητα• Επανορισμός μεθόδων, διπλός ορισμός
μεταβλητής• Συμβατότητα δεικτών / αναφορών• Virtual methods, virtual table, pure virtual
methods
C++ (συνέχεια)
• Friend classes• Static member κλάσεων• Class templates
template <class T> class myTemplate {...};Παράδειγμα
• Exception classes
void Input(char *prompt, int &i) { …. }
void Input(char *prompt, double &d) { …. }
void Input(char *prompt, char *s) { …. }
int main(void) {
int my_integer;
double my_double;
char my_string[100];
Input("Δώστε τιμή για το my_integer", my_integer);
Input("Δώστε τιμή για το my_double", my_double);
Input("Δώστε τιμή για το my_string", my_string);
printf("my_integer = %d\nmy_double = %f\nmy_string =
%s\n",my_integer, my_double, my_string);
} BACK
typedef struct Employee {
char name[100];
int salary;
} Employee;
void operator +=(Employee &e, int raise) {
e.salary = e.salary + raise;
}
int main(void) {
Employee e1;
strcpy(e1.name, "Janitor John");
e1.salary = 100;
e1 += 200; /* Κλήση του τελεστή που ορίσαμε */
printf("%d\n", e1.salary); return 0;
} BACK
int a;
double b;
char c[100];
cin >> a; /* Ανάγνωση του a */
cin >> b >> c; /* Ανάγνωση δύο μεταβλητών, πρώτα της b και μετά της c */
cout << "Η τιμή του a είναι " << a << "\n";
cout << "Η τιμή του b είναι " << b << endl; /* Η σταθερά endl σημαίνει αλλαγή γραμμής */
cout << "Η τιμή του c είναι " << c << endl;
BACK
class Person {
private:
char name[30];
char address[50];
int birth_year;
public:
void set_name(const char *);
void set_address(const char *);
void set_birth_year(int y) {birth_year = y;}
const char *get_name(void) const {return name;}
const char *get_address(void) const {return address;}
int get_birth_year(void) const {return birth_year;}
};
BACK
void Person::set_name(const char *n)
{
strncpy(name, n, 29);
name[29] = '\0';
}
void Person::set_address(const char *a)
{
strncpy(address, a, 49);
name[49] = '\0';
}
BACK
class String
{
private:
char *str;
public:
String(void); // Συνάρτηση κατασκευής χωρίς παραμέτρους
String(const char *s); // Συνάρτηση κατασκευής όπου ορίζεται
// η τιμή που επιθυμούμε να αποδόσουμε στο στιγμιότυπο
~ String(void); // Συνάρτηση καταστροφής
void set_value(const char *s);
const char *get_value(void) const {return str;}
};
BACK
String::String(void) { str = strdup(""); }
String::String(const char *s) { str = strdup(s); }
String::~String(void) {free(str);}
void String::set_value(const char *s)
{
free(str);
str = strdup(s);
}
BACK
Copy costructorString(String &s) {str = strdup(s.str);}
Τελεστής ανάθεσηςvoid operator=(String &s) {free(str); str = strdup(s.str);}
BACK
void Person::marry(Person &new_spouse)
{
// Ελεγχος αν και οι δύο είναι ελεύθεροι
if ((spouse != NULL) || (new_spouse.spouse != NULL))
{
cerr << "Πρέπει και οι δύο να είναι ελεύθεροι!" << endl;
return;
}
spouse = &new_spouse;
new_spouse.spouse = this;
}
BACK
class IntegerListNode
{
private:
int value; // Η τιμή του κόμβου
IntegerListNode *next; // Ο δείκτης στον επόμενο
public:
IntegerListNode(int v, IntegerListNode *n) {
value = v; next = n;
}
int getValue(void) const {return value;}
void setNext(IntegerListNode *n) {next = n;}
IntegerListNode *getNext(void) const {return next;}
};
BACK
class IntegerList {
private:
IntegerListNode *first;
public:
IntegerList(void); // Συνάρτηση κατασκευής
~IntegerList(void); // Συνάρτηση καταστροφής
void add(int v); // Προσθήκη κόμβου με συγκεκριμένη τιμή
int remove(int v); // Διαγραφή κόμβου με συγκεκριμένη τιμή.
// Επιστρέφουμε 1 σε επιτυχία, 0 σε αποτυχία
// (δεν υπάρχει τέτοιος κόμβος.
int has(int v) const; // Ελεγχος ύπαρξης κόμβου με συγκεκριμένη
// τιμή. Επιστρέφουμε
// 1 αν υπάρχει, 0 αν δεν υπάρχει.
};
IntegerList::IntegerList(void) {
// Δημιουργία του dummy κόμβου με αδιάφορη τιμή και NULL ως
// επόμενο, δηλ. ο dummy κόμβος είναι ο τελευταίος στη λίστα.
first = new IntegerListNode(0, NULL);
}
IntegerList::~IntegerList(void) {
IntegerListNode *cur, *nxt;
// Διατρέχουμε τους κόμβους της λίστας
for (cur = first; cur != NULL; ) {
nxt = cur->getNext(); // Κάθε φορά φυλάμε τον επόμενο
delete cur; // ... σβήνουμε τον τρέχοντα
cur = nxt; // ... και προχωράμε στον επόμενο
}
}
void IntegerList::add(int v) {
// Προσθέτουμε τον νέο κόμβο ως πρώτο στη λίστα,
// αμέσως μετά από τον dummy.
IntegerListNode *newNode =
new IntegerListNode(v, first->getNext());
first->setNext(newNode);
}
int IntegerList::remove(int v) {
// Προσπάθεια εντοπισμού του κόμβου που θα διαγραφεί. Σε κάθε βήμα
// φροντίζουμε να δείχνουμε έναν κόμβο πιο πριν, έτσι ώστε να
// μπορούμε να τροποποιήσουμε τον κατάλληλο δείκτη next.
// Φυσικά, η τιμή του πρώτου κόμβου αγνοείται.
for (IntegerListNode *prev = first; prev->getNext() != NULL; prev = prev->getNext()) {
if (prev->getNext()->getValue() == v) {
// βρέθηκε ο κόμβος που πρέπει να διαγραφεί
IntegerListNode *victim = prev->getNext();
// Βγάζουμε τον κόμβο-θύμα από τη λίστα, συνδέοντας
// απ' ευθείας τον προηγούμενό του με τον επόμενό του
prev->setNext(victim->getNext());
// αποδεσμεύουμε τη μνήμη για τον κόμβο-θύμα
delete victim;
return 1; // Επιστροφή με ένδειξη επιτυχίας
}
}
return 0; // Επιστροφή με ένδειξη αποτυχίας
}
int IntegerList::has(int v) const
{
// Αναζήτηση του κόμβου. Ο πρώτος κόμβος αγνοείται συνολικά.
for (IntegerListNode *n = first->getNext(); n != NULL; n = n->getNext())
if (n->getValue() == v)
return 1; // Ναι, βρέθηκε
return 0; // Οχι, η λίστα εξαντλήθηκε χωρίς να βρεθεί.
}
BACK
class B: [public] A {
...
};
Κανόνες:
1. Όσα είναι private στην Α δεν είναι ορατά στη Β.
2. Όταν δεν έχει παρατεθεί η λέξη public, όλα τα public της Α είναι private για τη Β.
3. Όταν έχει παρατεθεί η λέξη public, όλα τα public της Α είναι public για τη Β.
4. Όσα είναι protected στην Α είναι ορατά στη Β και είναι χαρακτηρισμένα πάλι ως protected.
BACK
Δήλωση Επιτρέπεται;
Σχόλια
A &ra = b; Ναι Σε μία αναφορά προς στιγμιότυπο της υπερκλάσης μπορούμε να αναθέσουμε ένα στιγμιότυπο της υποκλάσης.
A *pa = &b; Ναι Σε έναν δείκτη προς στιγμιότυπο της υπερκλάσης μπορούμε να αναθέσουμε τη διεύθυνση ενός στιγμιοτύπου της υποκλάσης.
a = b; Όχι Η μόνη περίπτωση να επιτρέπεται είναι να έχουμε ορίσει στην κλάση B έναν τελεστή μετατροπής στιγμιοτύπων της σε στιγμιότυπα της κλάσης A, δηλ. τον τελεστήA &operator B::A(void) const;
B *pb = &a; Όχι Δεν επιτρέπεται η ανάθεση δείκτη προς στιγμιότυπο της υπερκλάσης σε δείκτη προς στιγμιότυπο της υποκλάσης.
BACK
Δήλωση Επιτρέπεται;
Σχόλιο
B *pb =(B *) &a; Ναι Η ανάθεση επιτρέπεται διότι παραθέτουμε ρητή μετατροπή τύπου.
B &rb = a; Όχι Δεν επιτρέπεται η ανάθεση στιγμιοτύπου της υπερκλάσης σε αναφορά προς στιγμιότυπο της υπερκλάσης, εκτός αν έχουμε ορίσει κατάλληλο τελεστή μετατροπής στην κλάση B, δηλ. τον τελεστήB &operator A::B(void) const;
b = a; Όχι Δεν επιτρέπεται η ανάθεση στιγμιοτύπου της υπερκλάσης σε στιγμιότυπο της υπερκλάσης, εκτός αν έχουμε ορίσει κατάλληλο τελεστή μετατροπής στην κλάση B, δηλ. τον τελεστήB &operator A::B(void) const;
Παράδειγμα:
#include <iostream.h>
#include <stdlib.h>
template <class T> class Array
{
private:
T *data;
int maxSize;
public:
Array(int size);
~Array(void) { delete [] data; }
Array<T> &setValue(const T &value, int position);
T getValue(int position);
}; BACK
template <class T> Array<T>::Array(int size)
{
if (size <= 0)
{
cerr << "Μη παραδεκτό μέγεθος για πίνακα (" << size << ")\n";
exit(1);
}
if ((data = new T[size]) == NULL)
{
cerr << "Δεν υπάρχει αρκετή μνήμη για τον πίνακα.\n";
exit(1);
}
maxSize = size;
} BACK
template <class T>
Array<T> &Array<T>::setValue(const T &value, int position)
{
if ((position < 0) || (position >= maxSize))
{
cerr << "Μη παραδεκτός δείκτης για πίνακα (" << position << ")\n";
exit(1);
}
data[position] = value;
return *this;
}
BACK
template <class T>
T Array<T>::getValue(int position)
{
if ((position < 0) || (position >= maxSize))
{
cerr << "Μη παραδεκτός δείκτης για πίνακα (" << position << ")\n";
exit(1);
}
return data[position];
}
BACK
int main(void)
{
Array<int> a(50);
for (int i = 0; i < 100; i++)
{
a.setValue(i * 2, i);
cout << "Position " << i << ", value " << a.getValue(i) << endl;
}
return 0;
}
BACK
template <class T> class MyList;
template <class T> class MyListNode {
private:
// Δήλωση της κλάσης MyList ως φίλης, ώστε να έχει πρόσβαση
// στα ιδιωτικά τμήματα.
friend class MyList<T>;
T datum;
MyListNode<Τ> *next;
// Παραθέτουμε και μία μέθοδο κατασκευής. Η μέθοδος αυτή
// παραμένει ιδιωτική, καθώς προσπελαύνεται μόνο από την
// MyList<T> κλάση η οποία έχει δηλωθεί ως φίλη κλάση.
MyListNode(T d, MyListNode<Τ> *n) {
datum = d;
next = n; }
}; BACK
template <class T> class MyList {
private:
MyListNode<T> *first;
MyListNode<T> **find(const T target) {
MyListNode<T> **result;
for (result = &first;*result != NULL;result = &((*result)->next))
if ((*result)->datum == target)
return result;
// Δεν βρέθηκε κατάλληλος κόμβος
return NULL;
}
public:
MyList(void) {first = NULL;}
BACK
~MyList(void) {
MyListNode<T> *victim, *nxt;
for (victim = first; victim != NULL; victim = nxt) {
nxt = victim->next;
delete victim;
}
}
MyList<T> &insert(const T datum) {
MyListNode<T> *newNode = new MyListNode<T>(datum, first);
first = newNode;
return *this;
}
BACK
MyList<T> &remove(const T datum) {
MyListNode<T> **victim, *next;
victim = find(datum);
if (victim == NULL)
return *this;
next = (*victim)->next;
delete (*victim);
*victim = next;
return *this;
}
int search(const T datum) {
MyListNode<T> **temp = find(datum);
if (temp == NULL)
return 0;
else
return 1;
}
}; // end of class definition
BACK
class Person {
public:
char idNumber[20];
char name[100];
int birthYear;
Person(const char *i, const char *n, int b) {
strcpy(idNumber, i);
strcpy(name, n);
birthYear = b;
}
};
BACK
int main(void)
{
MyList<int> IntegerList;
IntegerList.insert(2);
IntegerList.insert(7);
printf("Searching for 2... %d\n", IntegerList.search(2));
printf("Searching for 5... %d\n", IntegerList.search(5));
printf("Searching for 7... %d\n", IntegerList.search(7));
printf("Removing 2...\n");
IntegerList.remove(2);
printf("Searching for 2... %d\n", IntegerList.search(2));
printf("Searching for 7... %d\n", IntegerList.search(7));
MyList<Person> PersonList;
Person p1("A312", "John", 1968),
p2("C5670", "Mary", 1974),
p3("Z80", "Zilog", 1978);
PersonList.insert(p1);
PersonList.insert(p2);
printf("Searching for \"John\"... %d\n", PersonList.search(p1));
printf("Searching for \"Mary\"... %d\n", PersonList.search(p2));
printf("Searching for \"Zilog\"... %d\n", PersonList.search(p3));
printf("removing \"Mary\"\n");
PersonList.remove(p2);
printf("Searching for \"Mary\"... %d\n", PersonList.search(p2));
return 0;
} BACK