Κατέβασμα παρουσίασης
Η παρουσίαση φορτώνεται. Παρακαλείστε να περιμένετε
ΔημοσίευσεStefania Rokos Τροποποιήθηκε πριν 10 χρόνια
1
Ανασκόπηση σε Δείκτες, Ουρές, Στοίβες, Συνδεδεμένες Λίστες
ΜΑΘΗΜΑ 6ο Ανασκόπηση σε Δείκτες, Ουρές, Στοίβες, Συνδεδεμένες Λίστες
2
Δείκτες (pointers) - Ανασκόπηση (i)
Μεταβλητές που δεν περιέχουν μια τιμή κάποιου απλού τύπου δεδομένων αλλά τη διεύθυνση μιας άλλης μεταβλητής Παράδειγμα int x, *p; p δ247 δ124 x δ124 42
3
Δείκτες (pointers) (ii)
Τελεστής διεύθυνσης: & η διεύθυνση μιας μεταβλητής p = &x; Τελεστής έμμεσης αναφοράς: * το περιεχόμενο μιας διεύθυνσης printf("%d", *p); *p = 7; p δ247 δ124 x δ124 42
4
Πίνακες και δείκτες (i)
p δ247 a δ124 7 δ125 6 δ126 42 Αριθμητική δεικτών int a[3] = {7, 6, 42}; int *p; δ124 p = &(a[0]); p = &a; p = a; printf("%d\n", *p); printf("%d\n", *(p+1)); p = p+2;
5
Πίνακες και δείκτες (ii)
Ισοδυναμία πινάκων και δεικτών Ένας πίνακας είναι ένας δείκτης στο πρώτο στοιχείο. a[i] ισοδύναμο με *(a+i) Οι πίνακες όμως είναι σταθεροί δείκτες, δηλαδή δεν μπορούν να αλλάξουν τιμή. int a[3] = {7, 6, 42}; int *p = &a; p++; /* σωστό */ a++; /* λάθος! */
6
Πίνακες και δείκτες (iii)
Παράδειγμα: αντιγραφή πινάκων int a[10], b[10]; int *p = a, *q = b, i; /* ο πίνακας b έχει λάβει αρχικές τιμές */ for (i=0; i<10; i++) *p++ = *q++;
7
Πίνακες και δείκτες (iv)
Παράδειγμα: εκτύπωση συμβολοσειράς void putchar (char c); char s[] = "Hello world!\n"; char *p; for (p = s; *p != '\0'; p++) putchar(*p);
8
Κενός δείκτης και δείκτης σε κενό
Ο κενός δείκτης: NULL Απαγορεύεται η έμμεση αναφορά! int *p = NULL; *p = 42; /* λάθος! */ Ο μόνος δείκτης που αντιστοιχεί στην ψευδή λογική τιμή, όταν χρησιμοποιείται σε συνθήκη Ο δείκτης σε κενό: void * Γενική μορφή δείκτη Απαγορεύεται η έμμεση αναφορά! Απαγορεύεται η αριθμητική δεικτών!
9
Δείκτες αντί μεταβίβασης με αναφορά
Κώδικας Pascal procedure inc (var x : integer); begin x := x+1 end; ... inc(a) ... Ισοδύναμος κώδικας C void inc (int * ptr_x) { (*ptr_x)++; } ... inc(&a) ...
10
Δείκτες σε εγγραφές Συντομογραφία Παράδειγμα
p->x είναι ισοδύναμο με (*p).x Παράδειγμα struct { int x, y; } coordinates, *p; coordinates.x = 1; coordinates.y = 3; p = &coordinates; printf("%d\n", p->x); printf("%d\n", p->y);
11
Μετατροπή τύπου (i) Έμμεση (coercion) Άμεση (type casting)
double d = 3; (με ανάθεση) int x = 3.14; int f (int x); (με μεταβίβαση παραμέτρου) f(3.14); Άμεση (type casting) ( τύπος ) έκφραση (double) 3 (int) 3.14 (int *) NULL
12
Μετατροπή τύπου (ii) Πρόβλημα: πώς μπορώ να τυπώσω το αποτέλεσμα της πραγματικής διαίρεσης δυο ακεραίων αριθμών, χωρίς νέες μεταβλητές; int x = 5, y = 3; Λάθος λύση #1: printf("%d", x/y); Λάθος λύση #2: printf("%lf", x/y); Σωστές λύσεις: printf("%lf", 1.0 * x / y); printf("%lf", (double) x / (double) y); printf("%lf", (double) x / y);
13
Δυναμική παραχώρηση μνήμης (i)
Συναρτήσεις βιβλιοθήκης <stdlib.h> void * malloc (size_t n); Δυναμική παραχώρηση μνήμης μήκους n bytes. Το αποτέλεσμα πρέπει να μετατραπεί στο σωστό τύπο. Επιστρέφεται NULL αν εξαντληθεί η μνήμη. void free (void * p); Αποδέσμευση της μνήμης στην οποία δείχνει το p. Το p πρέπει να έχει δημιουργηθεί με προηγούμενη κλήση στη malloc. Πόσα bytes χρειάζονται; sizeof(type) π.χ. sizeof(int) sizeof variable π.χ. sizeof x
14
Δυναμική παραχώρηση μνήμης (ii)
Παράδειγμα int *p; int i; p = (int *) malloc(sizeof(int)); *p = 42; free(p); p = (int *) malloc(10 * sizeof(int)); for (i = 0; i < 10; i++) p[i] = 42; Το αποτέλεσμα της malloc πρέπει να ελεγχθεί ότι δεν είναι NULL!
15
ΔΟΜΕΣ & ΔΕΙΚΤΕΣ typedef struct { int idNumber; char descr[100];
int avail; } sparePartType; sparePartType var1 = {123, “Wheel”, 1}; /* Αρχικές τιμές */ sparePartType *var2 = (sparePartType *)malloc(sizeof(sparePartType)); *var2 = var1; /* Αναθέτουμε όλες τις τιμές των πεδίων από την var1 */ /* στη θέση μνήμης που «δείχνει» η var2 */ var2->idNumber = 10; /* δείκτες σε δομές */ var1.idNumber = 20; /* απλές μεταβλητές δομών */
16
ΔΟΜΕΣ & ΔΙΑΝΥΣΜΑΤΑ Οπότε μπορούμε να ορίσουμε μία τάξη μαθητών σαν ένα διάνυσμα στοιχείων τύπου classType. classType class101Var[10]; Οι δομές και τα διανύσματα μπορούν να συνδυαστούν χωρίς περιορισμούς. typedef struct { char firstName[10]; char lastName[10]; } personType; personType aPerson; int id; int age; int sex; } classType; 1 2 3 4 5 6 7 8 9 Σε κάθε «κελί» του διανύσματος υπάρχει μία δομή tύπου classType. Για να βρούμε το μικρό όνομα του τρίτου μαθητή της class101Var[2], γράφουμε: (class101Var[2].aPerson).firstName
17
ΔΟΜΕΣ & ΔΙΑΝΥΣΜΑΤΑ & ΔΕΙΚΤΕΣ
typedef struct { char firstName[10]; char lastName[10]; int id; int age; int sex; } personType; char * classId; personType *aPerson; } classType; classType class101Var[10]; for (int i = 0; i< 10; i++) { class101Var[i].classId = malloc(7); strcpy(class101Var[i].classId, “ECE101”); class101Var[i].aPerson = (personType *) malloc(sizeof(personType)); strcpy(class101Var[i].aPerson->firstName, “”); strcpy(class101Var[i].aPerson->lastName, “”); class101Var[i].aPerson->id = 0; class101Var[i].aPerson->age = 0; class101Var[i].aPerson->sex = 0; }
18
Εάν θέλουμε να φτιάξουμε μία κατασκευή, π. χ
Εάν θέλουμε να φτιάξουμε μία κατασκευή, π.χ. το μοντέλο μίας τάξης από μαθητές, ένας τρόπος θα ήταν να ορίσουμε ένα διάνυσμα από δομές σαν και αυτή που ορίσαμε παραπάνω, ή ακόμη καλύτερα ένα διάνυσμα από δείκτες σε τέτοιες δομές. F3 F2 F1 Δομή Δομή F1 F2 F3 F1 F2 F3 F1 F2 F3 Διάνυσμα
19
ΠΑΡΑΔΕΙΓΜΑ typedef struct { int F1; int F2; int F3; } aStructType;
aStructType *structArray[10]; structArray[0]=(aStructType *) malloc(sizeof(aStructType)); structArray[0]->F1 = 10; (*structArray[0]).F2 = 20; …………… structArray[ ]
20
ΣΥΝΔΕΔΕΜΕΝΕΣ ΛΙΣΤΕΣ - 1 Μέχρι τώρα έχουμε μιλήσει για απλές κατασκευές δεδομένων όπως δομές, διανύσματα, και πίνακες. Επίσης χρησιμοποιήσαμε αυτές τις απλές κατασκευές για να ορίσουμε πιο σύνθετες κατασκευές, όπως διανύσματα από δομές, διανύσματα από δείκτες σε δομές κλπ. Το κοινό χαρακτηριστικό των κατασκευών που είδαμε μέχρι τώρα είναι ότι το μέγεθός τους ορίζεται στατικά κατά τη σχεδίαση του προγράμματος. Για παράδειγμα, τα διανύσματα έχουν πεπερασμένο μήκος, μέγεθος, και πλήθος διαστάσεων. Το ζητούμενο είναι να ορίσουμε κατασκευές (π.χ. Λίστες) για τις οποίες δεν χρειάζεται να ορίσουμε πόσα στοιχεία έχουν, αλλά θα μπορούμε να προσθέτουμε όσα στοιχεία θέλουμε δυναμικά, δηλαδή κατά την εκτέλεση, και σύμφωνα με τις ανάγκες του προγράμματος μας.
21
ΣΥΝΔΕΔΕΜΕΝΕΣ ΛΙΣΤΕΣ - 2 int id; char * name; char * surname; } int id
Η παρακάτω κατασκευή ορίζει μια δομή με τρία μέλη (members). struct { int id; char * name; char * surname; } int id char* name char * surname
22
ΣΥΝΔΕΔΕΜΕΝΕΣ ΛΙΣΤΕΣ - 3 Ας δούμε τώρα τι θα γινόταν εάν εισήγαμε σε μία δομή ένα νέο πεδίο το οποίο θα ήταν ένας δείκτης σε δομή του ιδίου τύπου. struct Student { int id; char * name; char * surname; struct Student *next; }; int id char *name char *surname Student * next
23
ΣΥΝΔΕΔΕΜΕΝΕΣ ΛΙΣΤΕΣ - 4 struct Student { int id; char *name;
char *surname; struct Student *next; }; typedef struct Student StudentType; StudentType *list, *temp; int i; list = (StudentType *) malloc(sizeof(StudentType)); temp = list; for(i=1; i<3; i++) { temp->next = (StudentType *) malloc(sizeof(StudentType)); temp = temp->next; temp->next = NULL; } temp list int id char *name char *surname Student * next temp int id char *name char *surname Student * next temp Int id char *name char *surname Student * next NULL
24
Ο ΑΤΔ ΣΤΟΙΒΑ Οι κατασκευές που έχουμε δει μέχρι τώρα (διανύσματα, συνδεμένες λίστες) αποτελούν τη βάση για πιο εξειδικευμένες κατασκευές. Μία τέτοια κατασκευή είναι η στοίβα. Η στοίβα είναι και αυτή μία «λίστα» αντικειμένων, μόνο που έχει διαφορετική συμπεριφορά (δηλαδή έγκυρες πράξεις). Η συμπεριφορά του ΑΤΔ Στοίβα περιγράφεται ως εξής: Τα νέα στοιχεία εισάγονται στην αρχή (ή καλύτερα) πάνω από τα ήδη υπάρχοντα στοιχεία. Το στοιχείο που μπορεί να εξαχθεί από τη Στοίβα είναι το πάνω-πάνω στοιχείο, δηλαδή το στοιχείο που εισήχθη τελευταίο σε σειρά (Last-In-First-Out, LIFO). Επίσης μπορούμε να ελέγξουμε αν η Στοίβα είναι άδεια, και ποιο είναι το πάνω-πάνω στοιχείο της (κορυφή).
25
Ο ΑΤΔ ΣΤΟΙΒΑ Εάν θεωρήσουμε την έννοια της Στοίβας αντικειμένων σαν ένα Αφηρημένο Τύπο Δεδομένων τότε αυτός θα έχει τις παρακάτω λειτουργίες (έγκυρες πράξεις). Δημιουργία: Δημιουργεί μία κενή στοίβα. Κενή: Ελέγχει εάν μία στοίβα είναι κενή. Εισαγωγή : Εισάγει ένα στοιχείο πάνω από όλα τα άλλα στοιχεία της στοίβας. Η λειτουργία αυτή αναφέρεται στη βιβλιογραφία ως ώθηση (push). Διαγραφή: Διαγράφει το πάνω-πάνω στοιχείο από τη στοίβα. Η λειτουργία αυτή αναφέρεται στη βιβλιογραφία ως εξώθηση (pop). Έλεγχος πρώτου στοιχείου: Επιστρέφει το στοιχείο που βρίσκεται πάνω-πάνω χωρίς να το διαγράφει από τη στοίβα. Η λειτουργία αυτή αναφέρεται στη βιβλιογραφία ως top.
26
Ο ΑΤΔ ΣΤΟΙΒΑ Χαρακτηριστικά: Έγκυρες Πράξεις Μέγεθος
Δημιουργία() : Στοίβα Είναι_Κενή?(Στοίβα): λογικό Push(Στοίβα, στοιχείο) : Στοίβα Pop(Στοίβα) : στοιχείο Top(Στοίβα) : στοιχείο
27
ΥΛΟΠΟΙΗΣΗ ΤΟΥ ΑΤΔ ΣΤΟΙΒΑ
Ο ΑΤΔ Στοίβα, μπορεί να υλοποιηθεί είτε με τη χρήση διανυσμάτων είτε με τη χρήση συνδεμένων λιστών. Εάν η υλοποίηση βασίζεται στη χρήση διανύσματος, τότε: Πρέπει να γνωρίζουμε το μέγιστο επιτρεπτό μέγεθος της στοίβας. Θα μπορούσαμε να θεωρήσουμε ότι το πάνω-πάνω στοιχείο είναι το πρώτο στοιχείο του διανύσματος, οπότε σε αυτή την περίπτωση κάθε φορά που θα εισήγαμε ένα νέο στοιχείο θα έπρεπε να μετατοπίζουμε τα στοιχεία του διανύσματος μία θέση δεξιά. Αντί αυτού, το πάνω στοιχείο εισάγεται στο τέλος του διανύσματος, οπότε πρέπει να γνωρίζουμε το τρέχον μέγεθος της στοίβας. top A B C D E F
28
ΥΛΟΠΟΙΗΣΗ ΣΤΟΙΒAΣ ΜΕ ΔΙΑNΥΣΜΑ
#define SIZE 100; struct stack { int top=-1; int elements[SIZE]; }; typedef struct stack StackType; int empty(StackType s) { if (s.top==-1) return TRUE; else return FALSE; } int pop(StackType *ps) { if (empty(*ps)) { printf(“stack underflow\n"); exit(1); } return ps->elements[ps->top--];
29
ΥΛΟΠΟΙΗΣΗ ΣΤΟΙΒAΣ ΜΕ ΔΙΑNΥΣΜΑ
void push(StackType *ps, int data) { if (ps->top==SIZE-1) { printf("stack overflow\n"); exit(1); } else ps->elements[++(ps->top)] =data; return; void main() { StackType s; int x; push(&s,10); push(&s,20); x=pop(&s); }
30
ΜΗ ΟΜΟΓΕΝΗΣ ΣΤΟΙΒA Στοιχεία διαφορετικών τύπων
#define SIZE 100; enum elementtype {INTGR, FLT, STR}; struct stackelement { elementtype etype; union { int ival; float fval; char *cval; } item; }; struct stack { int top=-1; struct stackelement elements[SIZE]; typedef struct stack StackType; StackType s; struct stackelement se; . . . se=s.elements[s.top]; switch (se.etype){ case INTGR: printf(“%d\n”, se.item.ival); case FLT : printf(“%f\n”, se.item.fval); case STR : printf(“%s\n”, se.item.cval); }
31
ΥΛΟΠΟΙΗΣΗ ΣΤΟΙΒAΣ ΜΕ ΣΥΝΔΕΔΕΜΕΝΗ ΛΙΣΤΑ
struct node { int info; struct node *next; }; typedef struct node *NodePtr; NodePtr stack; info next stack
32
ΥΛΟΠΟΙΗΣΗ ΤΗΣ ΣΤΟΙΒAΣ ΜΕ ΣΥΝΔΕΔΕΜΕΝΗ ΛΙΣΤΑ
int empty(NodePtr s) { if (!s) return TRUE; else return FALSE; } void push(NodePtr *s, int data) { NodePtr p; p=(NodePtr)malloc(sizeof(struct node)); p->info=data; p->next= *s; *s=p; return; int pop(NodePtr *s) { int x; NodePtr p; if (empty(*s)) { printf(“stack underflow\n"); exit(1); } p=*s; x=p->info; *s=p->next; free(p); return x;
33
ΟΥΡΕΣ Ο ΑΤΔ Ουρά περιγράφει μία «λίστα» αντικειμένων, η οποία όμως έχει ειδικό τρόπο λειτουργίας για την εισαγωγή νέων στοιχείων και την εξαγωγή στοιχείων που υπάρχουν ήδη στη λίστα. Τα νέα στοιχεία τοποθετούνται πάντα στο τέλος της λίστας («πίσω»). Το μόνο στοιχείο το οποίο μπορεί να εξαχθεί από τη λίστα κάθε φορά είναι το πρώτο στοιχείο της λίστας, δηλαδή το στοιχείο της κεφαλής της λίστας («εμπρός»).
34
Ο ΑΤΔ Ουρά Χαρακτηριστικά: Έγκυρες Πράξεις Μήκος Δημιουργία() : Ουρά
Εύρεση_Μήκους(Ουρά) : ακέραιος Είναι_Κενή?(Ουρά): λογικό Εισαγωγή(Ουρά, στοιχείο) : Ουρά Εξαγωγή(Ουρά) : στοιχείο Αντιγραφή(Ουρά, Ουρά) : Ουρά Σύγκριση(Ουρά, Ουρά) : λογικό
35
ΥΛΟΠΟΙΗΣΗ ΤΟΥ ΑΤΔ ΟΥΡΑ Ο ΑΤΔ Ουρά, μπορεί να υλοποιηθεί είτε με τη χρήση διανυσμάτων είτε με τη χρήση συνδεμένων λιστών. Εάν η υλοποίηση βασίζεται στη χρήση διανύσματος, τότε: Πρέπει να γνωρίζουμε το μέγιστο επιτρεπτό μέγεθος της ουράς. Το διάνυσμα λειτουργεί κυκλικά, δηλαδή θεωρούμε ότι η επόμενη της τελευταίας θέσης του διανύσματος είναι η θέση 0. Ο δείκτης rear δείχνει τη θέση του τελευταίου στοιχείου της ουράς. Ο δείκτης front δείχνει την αμέσως προηγούμενη της θέσης του πρώτου στοιχείου της ουράς. Συνεπώς, η συνθήκη ισότητας των front και rear συνεπάγεται άδεια ουρά. Ποιά, όμως, θα είναι η συνθήκη γεμάτης ουράς;
36
ΥΛΟΠΟΙΗΣΗ ΟΥΡΑΣ ΜΕ ΔΙΑΝΥΣΜΑ
front front A B C B C rear rear front B C D E rear
37
ΥΛΟΠΟΙΗΣΗ ΟΥΡAΣ ΜΕ ΔΙΑNΥΣΜΑ
#define SIZE 100; struct queue { int front=SIZE-1,rear=SIZE-1; int elements[SIZE]; }; typedef struct queue QueueType; int empty(QueueType q) { if (q.front==q.rear) return TRUE; else return FALSE; } int dequeue(QueueType *pq) { if (empty(*pq)) { printf(“queue underflow\n"); exit(1); } if (pq->front==SIZE-1) pq->front=0; else (pq->front)++; return pq->elements[pq->front];
38
ΥΛΟΠΟΙΗΣΗ ΟΥΡAΣ ΜΕ ΔΙΑNΥΣΜΑ
Μια θέση του διανύσματος τηρείται πάντα κενή για να μπορούμε να ελέγξουμε τη συνθήκη γεμάτης ουράς. void enqueue(QueueType *pq, int data) { if (pq->rear==SIZE-1) pq->rear=0; else (pq->rear)++; if (pq->rear==pq->front) { printf(“queue overflow\n"); exit(1); } pq->elements[pq->rear]=data; return; void main() { QueueType q; int x; enqueue(&q,10); enqueue(&q,20); x=dequeue(&q); }
39
ΥΛΟΠΟΙΗΣΗ ΟΥΡAΣ ΜΕ ΣΥΝΔΕΔΕΜΕΝΗ ΛΙΣΤΑ
struct node { int info; struct node *next; }; typedef struct node *NodePtr; struct queue { NodePtr front, rear; info next front rear
40
ΥΛΟΠΟΙΗΣΗ ΟΥΡAΣ ΜΕ ΣΥΝΔΕΔΕΜΕΝΗ ΛΙΣΤΑ
int empty(struct queue q) { if (!q.front) return TRUE; else return FALSE; } void enqueue(struct queue *q, int data) { NodePtr p; p=(NodePtr)malloc(sizeof(struct node)); p->info=data; p->next=NULL; if (!q->rear) q->front=p; (q->rear)->next=p; q->rear=p; return; int dequeue(struct queue *q) { int x; NodePtr p; if (empty(*q)) { printf(“queue underflow\n"); exit(1); } p=q->front; x=p->info; q->front=p->next; if (!q->front) q->rear=NULL; free(p); return x;
41
ΠΡΑΞΕΙΣ ΣΥΝΔΕΔΕΜΕΝΗΣ ΛΙΣΤΑΣ
struct node { int info; struct node *next; }; typedef struct node *NodePtr; info next list
42
- ΕΙΣΑΓΩΓΗ ΣΤΟ ΤΕΛΟΣ ΤΗΣ ΛΙΣΤΑΣ - ΕΙΣΑΓΩΓΗ ΜΕΤΑ ΑΠΟ ΔΕΔΟΜΕΝΟ ΚΟΜΒΟ
void insend(NodePtr *list, int data) { NodePtr p,q; p=(NodePtr)malloc(sizeof (struct node)); p->info=data; p->next=NULL; if (*list==NULL) *list=p; else { for (q=*list; q->next; q=q->next) ; q->next=p; } return; void insafter(NodePtr p, int data) { NodePtr q; if (p==NULL) { printf(“error\n”); exit(1); } q=(NodePtr)malloc(sizeof (struct node)); q->info=data; q->next=p->next; p->next=q; return;
43
- ΕΞΑΓΩΓΗ ΜΕΤΑ ΑΠΟ ΔΕΔΟΜΕΝΟ ΚΟΜΒΟ - ΑΝΑΖΗΤΗΣΗ ΣΤΟΙΧΕΙΟΥ ΣΤΗ ΛΙΣΤΑ
- ΕΞΑΓΩΓΗ ΜΕΤΑ ΑΠΟ ΔΕΔΟΜΕΝΟ ΚΟΜΒΟ - ΑΝΑΖΗΤΗΣΗ ΣΤΟΙΧΕΙΟΥ ΣΤΗ ΛΙΣΤΑ void delafter(NodePtr p, int *data) { NodePtr q; if ((!p)||(!p->next)) { printf(“error\n”); exit(1); } q=p->next; *data=q->info; p->next=q->next; free(q); return; NodePtr search(NodePtr list, int x) { NodePtr p; for (p=list; p!=NULL; p=p->next) if (p->info==x) return p; /* επιστρέφεται η θέση της */ /* πρώτης εμφάνισης του x, */ /* αλλιώς NULL, αν το x δεν */ /* υπάρχει στη λίστα */ return NULL; }
44
ΔΙΑΓΡΑΦΗ ΟΛΩΝ ΤΩΝ ΚΟΜΒΩΝ ΜΕ ΔΕΔΟΜΕΝΗ ΤΙΜΗ
void removex(NodePtr *list, int x) { NodePtr p,q; int y; q=NULL; p=*list; while (p!=NULL) if (p->info==x) { p=p->next; if (q==NULL) { /* αρχή της λίστας */ free(*list); *list=p; } else delafter(q,&y); } else { /* διάσχιση λίστας */ q=p; p=p->next; return;
45
ΕΙΣΑΓΩΓΗ ΣΤΟΙΧΕΙΟΥ ΣΕ ΔΙΑΤΕΤΑΓΜΕΝΗ ΛΙΣΤΑ
void insert(NodePtr *list, int x) { NodePtr p,q; q=NULL; for (p=*list; p && p->info < x; p=p->next) q=p; if (!q) { /* αρχή της λίστας */ q=(NodePtr)malloc(sizeof (struct node)); q->info=x; q->next=*list; *list=q; } else insafter(q,x); return; }
46
ΣΥΝΔΕΔΕΜΕΝΕΣ ΛΙΣΤΕΣ: Άλλες παραστάσεις
ΣΥΝΔΕΔΕΜΕΝΕΣ ΛΙΣΤΕΣ: Άλλες παραστάσεις Υπάρχουν αρκετές παραλλαγές της βασικής τοπολογίας γραμμικής λίστας. Μερικές συνήθεις παραλλαγές είναι: 1. Ο τελευταίος κόμβος συνδέεται με τον πρώτο (κυκλικές λίστες) 2. Ο κάθε κόμβος συνδέεται με τον επόμενο και με τον προηγούμενο (διπλά συνδεδεμένες λίστες). 3. Τοποθέτηση ενός εικονικού κόμβου στην αρχή της λίστας (κόμβος-κεφαλή) για διευκόλυνση των ελέγχων κατά την εισαγωγή και διαγραφή. 4. Τοποθέτηση ενός εικονικού κόμβου στο τέλος της λίστας (κόμβος-φρουρός) για διευκόλυνση των ελέγχων κατά την σειριακή αναζήτηση.
Παρόμοιες παρουσιάσεις
© 2024 SlidePlayer.gr Inc.
All rights reserved.