Η παρουσίαση φορτώνεται. Παρακαλείστε να περιμένετε

Η παρουσίαση φορτώνεται. Παρακαλείστε να περιμένετε

6-1 ΜΑΘΗΜΑ 6 ο Ανασκόπηση σε Δείκτες, Ουρές, Στοίβες, Συνδεδεμένες Λίστες.

Παρόμοιες παρουσιάσεις


Παρουσίαση με θέμα: "6-1 ΜΑΘΗΜΑ 6 ο Ανασκόπηση σε Δείκτες, Ουρές, Στοίβες, Συνδεδεμένες Λίστες."— Μεταγράφημα παρουσίασης:

1 6-1 ΜΑΘΗΜΑ 6 ο Ανασκόπηση σε Δείκτες, Ουρές, Στοίβες, Συνδεδεμένες Λίστες

2 6-2 Δείκτες (pointers) - Ανασκόπηση(i) • Μεταβλητές –που δεν περιέχουν μια τιμή κάποιου απλού τύπου δεδομένων –αλλά τη διεύθυνση μιας άλλης μεταβλητής • Παράδειγμα int x, *p; x δ124 p δ δ124

3 6-3 Δείκτες (pointers)(ii) • Τελεστής διεύθυνσης: & –η διεύθυνση μιας μεταβλητής p = &x; • Τελεστής έμμεσης αναφοράς: * –το περιεχόμενο μιας διεύθυνσης printf("%d", *p); *p = 7; x δ124 p δ δ124

4 6-4 Πίνακες και δείκτες(i) • Αριθμητική δεικτών int a[3] = {7, 6, 42}; int *p; p δ247 a δ124 7 δ125 6 δ δ124 p = &(a[0]); p = &a; p = a; printf("%d\n", *p); printf("%d\n", *(p+1)); p = p+2; printf("%d\n", *p);

5 6-5 Πίνακες και δείκτες(ii) • Ισοδυναμία πινάκων και δεικτών –Ένας πίνακας είναι ένας δείκτης στο πρώτο στοιχείο. –a[i] ισοδύναμο με *(a+i) –Οι πίνακες όμως είναι σταθεροί δείκτες, δηλαδή δεν μπορούν να αλλάξουν τιμή. int a[3] = {7, 6, 42}; int *p = &a; p++; /* σωστό */ a++; /* λάθος! */

6 6-6 Πίνακες και δείκτες(iii) • Παράδειγμα: αντιγραφή πινάκων int a[10], b[10]; int *p = a, *q = b, i; /* ο πίνακας b έχει λάβει αρχικές τιμές */ for (i=0; i<10; i++) *p++ = *q++;

7 6-7 Πίνακες και δείκτες(iv) • Παράδειγμα: εκτύπωση συμβολοσειράς void putchar (char c); char s[] = "Hello world!\n"; char *p; for (p = s; *p != '\0'; p++) putchar(*p);

8 6-8 Κενός δείκτης και δείκτης σε κενό • Ο κενός δείκτης: NULL –Απαγορεύεται η έμμεση αναφορά! int *p = NULL; *p = 42; /* λάθος! */ –Ο μόνος δείκτης που αντιστοιχεί στην ψευδή λογική τιμή, όταν χρησιμοποιείται σε συνθήκη • Ο δείκτης σε κενό: void * –Γενική μορφή δείκτη –Απαγορεύεται η έμμεση αναφορά! –Απαγορεύεται η αριθμητική δεικτών!

9 6-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 6-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 6-11 Μετατροπή τύπου(i) • Έμμεση (coercion) double d = 3; (με ανάθεση) int x = 3.14; int f (int x); (με μεταβίβαση παραμέτρου) f(3.14); • Άμεση (type casting) ( τύπος ) έκφραση (double) 3 (int) 3.14 (int *) NULL

12 6-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 6-13 Δυναμική παραχώρηση μνήμης(i) • Συναρτήσεις βιβλιοθήκης –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 6-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; free(p); Το αποτέλεσμα της malloc πρέπει να ελεγχθεί ότι δεν είναι NULL !

15 6-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 6-16 ΔΟΜΕΣ & ΔΙΑΝΥΣΜΑΤΑ • Οι δομές και τα διανύσματα μπορούν να συνδυαστούν χωρίς περιορισμούς. typedef struct { char firstName[10]; char lastName[10]; } personType; typedef struct { personType aPerson; int id; int age; int sex; } classType; Οπότε μπορούμε να ορίσουμε μία τάξη μαθητών σαν ένα διάνυσμα στοιχείων τύπου classType. classType class101Var[10]; Σε κάθε «κελί» του διανύσματος υπάρχει μία δομή tύπου classType. Για να βρούμε το μικρό όνομα του τρίτου μαθητή της class101Var[2], γράφουμε: (class101Var[2].aPerson).firstName

17 6-17 ΔΟΜΕΣ & ΔΙΑΝΥΣΜΑΤΑ & ΔΕΙΚΤΕΣ typedef struct { char firstName[10]; char lastName[10]; int id; int age; int sex; } personType; typedef struct { 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 6-18 • Εάν θέλουμε να φτιάξουμε μία κατασκευή, π.χ. το μοντέλο μίας τάξης από μαθητές, ένας τρόπος θα ήταν να ορίσουμε ένα διάνυσμα από δομές σαν και αυτή που ορίσαμε παραπάνω, ή ακόμη καλύτερα ένα διάνυσμα από δείκτες σε τέτοιες δομές. F3F2F1 F1 F2 F3 Δομή Διάνυσμα Δομή

19 6-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; …………… F1F2F3 structArray[ ] aStructType

20 6-20 ΣΥΝΔΕΔΕΜΕΝΕΣ ΛΙΣΤΕΣ - 1 • Μέχρι τώρα έχουμε μιλήσει για απλές κατασκευές δεδομένων όπως δομές, διανύσματα, και πίνακες. • Επίσης χρησιμοποιήσαμε αυτές τις απλές κατασκευές για να ορίσουμε πιο σύνθετες κατασκευές, όπως διανύσματα από δομές, διανύσματα από δείκτες σε δομές κλπ. • Το κοινό χαρακτηριστικό των κατασκευών που είδαμε μέχρι τώρα είναι ότι το μέγεθός τους ορίζεται στατικά κατά τη σχεδίαση του προγράμματος. Για παράδειγμα, τα διανύσματα έχουν πεπερασμένο μήκος, μέγεθος, και πλήθος διαστάσεων. • Το ζητούμενο είναι να ορίσουμε κατασκευές (π.χ. Λίστες) για τις οποίες δεν χρειάζεται να ορίσουμε πόσα στοιχεία έχουν, αλλά θα μπορούμε να προσθέτουμε όσα στοιχεία θέλουμε δυναμικά, δηλαδή κατά την εκτέλεση, και σύμφωνα με τις ανάγκες του προγράμματος μας.

21 6-21 ΣΥΝΔΕΔΕΜΕΝΕΣ ΛΙΣΤΕΣ - 2 • Η παρακάτω κατασκευή ορίζει μια δομή με τρία μέλη (members). struct { int id; char * name; char * surname; } int idchar* namechar * surname

22 6-22 ΣΥΝΔΕΔΕΜΕΝΕΣ ΛΙΣΤΕΣ - 3 • Ας δούμε τώρα τι θα γινόταν εάν εισήγαμε σε μία δομή ένα νέο πεδίο το οποίο θα ήταν ένας δείκτης σε δομή του ιδίου τύπου. struct Student { int id; char * name; char * surname; struct Student *next; }; int idchar *namechar *surname Student * next

23 6-23 ΣΥΝΔΕΔΕΜΕΝΕΣ ΛΙΣΤΕΣ - 4 int idchar *namechar *surname Student * next int idchar *namechar *surname Student * next Int idchar *namechar *surname Student * next temp NULL list temp 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

24 6-24 Ο ΑΤΔ ΣΤΟΙΒΑ • Οι κατασκευές που έχουμε δει μέχρι τώρα (διανύσματα, συνδεμένες λίστες) αποτελούν τη βάση για πιο εξειδικευμένες κατασκευές. • Μία τέτοια κατασκευή είναι η στοίβα. Η στοίβα είναι και αυτή μία «λίστα» αντικειμένων, μόνο που έχει διαφορετική συμπεριφορά (δηλαδή έγκυρες πράξεις). • Η συμπεριφορά του ΑΤΔ Στοίβα περιγράφεται ως εξής: –Τα νέα στοιχεία εισάγονται στην αρχή (ή καλύτερα) πάνω από τα ήδη υπάρχοντα στοιχεία. –Το στοιχείο που μπορεί να εξαχθεί από τη Στοίβα είναι το πάνω-πάνω στοιχείο, δηλαδή το στοιχείο που εισήχθη τελευταίο σε σειρά (Last-In- First-Out, LIFO). –Επίσης μπορούμε να ελέγξουμε αν η Στοίβα είναι άδεια, και ποιο είναι το πάνω-πάνω στοιχείο της (κορυφή).

25 6-25 Ο ΑΤΔ ΣΤΟΙΒΑ • Εάν θεωρήσουμε την έννοια της Στοίβας αντικειμένων σαν ένα Αφηρημένο Τύπο Δεδομένων τότε αυτός θα έχει τις παρακάτω λειτουργίες (έγκυρες πράξεις). 1.Δημιουργία: Δημιουργεί μία κενή στοίβα. 2.Κενή: Ελέγχει εάν μία στοίβα είναι κενή. 3.Εισαγωγή : Εισάγει ένα στοιχείο πάνω από όλα τα άλλα στοιχεία της στοίβας. Η λειτουργία αυτή αναφέρεται στη βιβλιογραφία ως ώθηση (push). 4.Διαγραφή: Διαγράφει το πάνω-πάνω στοιχείο από τη στοίβα. Η λειτουργία αυτή αναφέρεται στη βιβλιογραφία ως εξώθηση (pop). 5.Έλεγχος πρώτου στοιχείου: Επιστρέφει το στοιχείο που βρίσκεται πάνω-πάνω χωρίς να το διαγράφει από τη στοίβα. Η λειτουργία αυτή αναφέρεται στη βιβλιογραφία ως top.

26 6-26 Ο ΑΤΔ ΣΤΟΙΒΑ • Χαρακτηριστικά: –Μέγεθος • Έγκυρες Πράξεις –Δημιουργία() : Στοίβα –Είναι_Κενή?(Στοίβα): λογικό –Push(Στοίβα, στοιχείο) : Στοίβα –Pop(Στοίβα) : στοιχείο –Top(Στοίβα) : στοιχείο

27 6-27 ΥΛΟΠΟΙΗΣΗ ΤΟΥ ΑΤΔ ΣΤΟΙΒΑ • Ο ΑΤΔ Στοίβα, μπορεί να υλοποιηθεί είτε με τη χρήση διανυσμάτων είτε με τη χρήση συνδεμένων λιστών. • Εάν η υλοποίηση βασίζεται στη χρήση διανύσματος, τότε: –Πρέπει να γνωρίζουμε το μέγιστο επιτρεπτό μέγεθος της στοίβας. –Θα μπορούσαμε να θεωρήσουμε ότι το πάνω-πάνω στοιχείο είναι το πρώτο στοιχείο του διανύσματος, οπότε σε αυτή την περίπτωση κάθε φορά που θα εισήγαμε ένα νέο στοιχείο θα έπρεπε να μετατοπίζουμε τα στοιχεία του διανύσματος μία θέση δεξιά. Αντί αυτού, το πάνω στοιχείο εισάγεται στο τέλος του διανύσματος, οπότε πρέπει να γνωρίζουμε το τρέχον μέγεθος της στοίβας. ABCDEF top

28 6-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)) { if (empty(*ps)) { printf(“stack underflow"); printf(“stack underflow\n"); exit(1); exit(1); } return ps->elements[ps->top--]; }

29 6-29 ΥΛΟΠΟΙΗΣΗ ΣΤΟΙΒAΣ ΜΕ ΔΙΑNΥΣΜΑ StackType *ps 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 6-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 6-31 ΥΛΟΠΟΙΗΣΗ ΣΤΟΙΒAΣ ΜΕ ΣΥΝΔΕΔΕΜΕΝΗ ΛΙΣΤΑ stack info next struct node { int info; struct node *next; }; typedef struct node *NodePtr; NodePtr stack;

32 6-32 ΥΛΟΠΟΙΗΣΗ ΤΗΣ ΣΤΟΙΒAΣ ΜΕ ΣΥΝΔΕΔΕΜΕΝΗ ΛΙΣΤΑ int empty(NodePtr s) { if (!s) return TRUE; else return FALSE; } NodePtr *s 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"); printf(“stack underflow\n"); exit(1); exit(1); }p=*s;x=p->info;*s=p->next;free(p); return x; }

33 6-33 ΟΥΡΕΣ • Ο ΑΤΔ Ουρά περιγράφει μία «λίστα» αντικειμένων, η οποία όμως έχει ειδικό τρόπο λειτουργίας για την εισαγωγή νέων στοιχείων και την εξαγωγή στοιχείων που υπάρχουν ήδη στη λίστα. –Τα νέα στοιχεία τοποθετούνται πάντα στο τέλος της λίστας («πίσω»). –Το μόνο στοιχείο το οποίο μπορεί να εξαχθεί από τη λίστα κάθε φορά είναι το πρώτο στοιχείο της λίστας, δηλαδή το στοιχείο της κεφαλής της λίστας («εμπρός»).

34 6-34 Ο ΑΤΔ Ουρά • Χαρακτηριστικά: –Μήκος • Έγκυρες Πράξεις –Δημιουργία() : Ουρά –Εύρεση_Μήκους(Ουρά) : ακέραιος –Είναι_Κενή?(Ουρά): λογικό –Εισαγωγή(Ουρά, στοιχείο) : Ουρά –Εξαγωγή(Ουρά) : στοιχείο –Αντιγραφή(Ουρά, Ουρά) : Ουρά –Σύγκριση(Ουρά, Ουρά) : λογικό

35 6-35 ΥΛΟΠΟΙΗΣΗ ΤΟΥ ΑΤΔ ΟΥΡΑ • Ο ΑΤΔ Ουρά, μπορεί να υλοποιηθεί είτε με τη χρήση διανυσμάτων είτε με τη χρήση συνδεμένων λιστών. • Εάν η υλοποίηση βασίζεται στη χρήση διανύσματος, τότε: –Πρέπει να γνωρίζουμε το μέγιστο επιτρεπτό μέγεθος της ουράς. –Το διάνυσμα λειτουργεί κυκλικά, δηλαδή θεωρούμε ότι η επόμενη της τελευταίας θέσης του διανύσματος είναι η θέση 0. –Ο δείκτης rear δείχνει τη θέση του τελευταίου στοιχείου της ουράς. Ο δείκτης front δείχνει την αμέσως προηγούμενη της θέσης του πρώτου στοιχείου της ουράς. –Συνεπώς, η συνθήκη ισότητας των front και rear συνεπάγεται άδεια ουρά. Ποιά, όμως, θα είναι η συνθήκη γεμάτης ουράς;

36 6-36 ΥΛΟΠΟΙΗΣΗ ΟΥΡΑΣ ΜΕ ΔΙΑΝΥΣΜΑ ABC front rear BC front rear BCDE front rear

37 6-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)) { if (empty(*pq)) { printf(“queue underflow"); printf(“queue underflow\n"); exit(1); exit(1); } if (pq->front==SIZE-1) if (pq->front==SIZE-1)pq->front=0; else else(pq->front)++; return pq->elements[pq->front]; }

38 6-38 ΥΛΟΠΟΙΗΣΗ ΟΥΡAΣ ΜΕ ΔΙΑNΥΣΜΑ QueueType *pq 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 6-39 ΥΛΟΠΟΙΗΣΗ ΟΥΡAΣ ΜΕ ΣΥΝΔΕΔΕΜΕΝΗ ΛΙΣΤΑ info next frontrear struct node { int info; struct node *next; }; typedef struct node *NodePtr; struct queue { NodePtr front, rear; };

40 6-40 ΥΛΟΠΟΙΗΣΗ ΟΥΡAΣ ΜΕ ΣΥΝΔΕΔΕΜΕΝΗ ΛΙΣΤΑ int empty(struct queue q) { if (!q.front) return TRUE; else return FALSE; } queue *q 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; else (q->rear)->next=p; q->rear=p; return; } int dequeue(struct queue *q) { int x; NodePtr p; if (empty(*q)) { printf(“queue underflow"); printf(“queue underflow\n"); exit(1); exit(1); }p=q->front;x=p->info;q->front=p->next; if (!q->front) q->rear=NULL; free(p); return x; }

41 6-41 ΠΡΑΞΕΙΣ ΣΥΝΔΕΔΕΜΕΝΗΣ ΛΙΣΤΑΣ info next list struct node { int info; struct node *next; }; typedef struct node *NodePtr;

42 ΕΙΣΑΓΩΓΗ ΣΤΟ ΤΕΛΟΣ ΤΗΣ ΛΙΣΤΑΣ - ΕΙΣΑΓΩΓΗ ΜΕΤΑ ΑΠΟ ΔΕΔΟΜΕΝΟ ΚΟΜΒΟ NodePtr *list 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; } NodePtr p 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 ΕΞΑΓΩΓΗ ΜΕΤΑ ΑΠΟ ΔΕΔΟΜΕΝΟ ΚΟΜΒΟ - ΑΝΑΖΗΤΗΣΗ ΣΤΟΙΧΕΙΟΥ ΣΤΗ ΛΙΣΤΑ NodePtr p 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 list 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 6-44 ΔΙΑΓΡΑΦΗ ΟΛΩΝ ΤΩΝ ΚΟΜΒΩΝ ΜΕ ΔΕΔΟΜΕΝΗ ΤΙΜΗ NodePtr *list 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 6-45 ΕΙΣΑΓΩΓΗ ΣΤΟΙΧΕΙΟΥ ΣΕ ΔΙΑΤΕΤΑΓΜΕΝΗ ΛΙΣΤΑ NodePtr *list void insert(NodePtr *list, int x) { NodePtr p,q; q=NULL; for (p=*list; p && p->info 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 6-46 ΣΥΝΔΕΔΕΜΕΝΕΣ ΛΙΣΤΕΣ: Άλλες παραστάσεις • Υπάρχουν αρκετές παραλλαγές της βασικής τοπολογίας γραμμικής λίστας. Μερικές συνήθεις παραλλαγές είναι: 1. Ο τελευταίος κόμβος συνδέεται με τον πρώτο (κυκλικές λίστες) 2. Ο κάθε κόμβος συνδέεται με τον επόμενο και με τον προηγούμενο (διπλά συνδεδεμένες λίστες). 3. Τοποθέτηση ενός εικονικού κόμβου στην αρχή της λίστας (κόμβος- κεφαλή) για διευκόλυνση των ελέγχων κατά την εισαγωγή και διαγραφή. 4. Τοποθέτηση ενός εικονικού κόμβου στο τέλος της λίστας (κόμβος- φρουρός) για διευκόλυνση των ελέγχων κατά την σειριακή αναζήτηση.


Κατέβασμα ppt "6-1 ΜΑΘΗΜΑ 6 ο Ανασκόπηση σε Δείκτες, Ουρές, Στοίβες, Συνδεδεμένες Λίστες."

Παρόμοιες παρουσιάσεις


Διαφημίσεις Google