Παρασκευή, 15 Ιανουαρίου 2016

Συνδεδεμένες Λίστες FIFO και LIFO για αντικείμενα!

Υπάρχει πιο προχωρημένο θέμα εδώ  (στο παράδειγμα με την Class LList) όπου χρησιμοποιούμε δείκτες σε ομάδες, και η δομή κρατιέται από τους δείκτες μόνο (ενώ στο παράδειγμα εδώ τα αντικείμενα βρίσκονται σε πίνακα, και οι δείκτες δείχνουν στοιχεία πίνακα)


Το παράδειγμα είναι αρκετά προχωρημένο και είναι στα Αγγλικά. Η κλάση Mem() που είχε δοθεί σε προηγούμενες αναρτήσεις εμπλουτίστηκε με "λογική" για υποστήριξη συνδεδεμένων λιστών τύπου LIFO και FIFO. Μπορούμε να φτιάξουμε όσες λίστες θέλουμε! Η κλάση Mem() αν χρειάζεται περισσότερα στοιχεία επεκτείνεται μόνη της! Μας παρέχει μνήμη για να βάλουμε αντικείμενα σε ένα πίνακα.
Στη Μ2000 μπορούμε σε στοιχεία πίνακα να γράφουμε αντικείμενα. Αντί να χρησιμοποιήσουμε τη συνάρτηση Malloc() που δίνει το αντικείμενο για να κάνουμε λίστες χρησιμοποιούμε τις μεθόδους PushFirst και PushLast, οι οποίες προσθέτουν μια ιδιότητα την pnext.
Η Mem() δεν ασχολείται με το τι κλάση δίνουμε! Αν χρησιμοποιούμε τις μεθόδους αυτές, για οποιοδήποτε αντικείμενο, τότε θα φτιάχνεται κανονικά η λίστα που θέλουμε! Οι δείκτες αρχής-τέλους για την FIFO και αρχής για τη LIFO είναι μεταβλητές που παρέχουμε με αναφορά.
Επιπλέον υπάρχουν και μέθοδοι και συναρτήσεις υποστηρικτικές. Δεν θα αναφέρω κάτι παραπάνω!
Μπορεί κανείς να δει το κώδικα - αλλά μπορεί και να τον τρέξει!
Η Μ2000 έχει σωρό τιμών που χειρίζεται ως στοίβα FIFO και LIFO, ότι βάλουμε,  αλλά εδώ μας ενδιαφέρει η χρήση μια κλάσης. Όλο το MEM()  είναι ένα αντικείμενο και μπορεί να μπει σε ένα άλλο!

Διορθώθηκε ο παλιός κώδικας (έβαζε 100 στοιχεία κάθε φορά που ζητάγαμε 1, αλλαγή συνθήκης < σε >= στο .topfree>=.Items, στην Malloc)
Προστέθηκε η PopOne για να βγάζουμε στοιχεία. Επίσης σε αυτήν την έκδοση δεν γίνεται χρήση της .Porperty$() της Mem, αλλά έχει εισαχθεί μια ιδιότητα Item() (με ένα όρισμα) η οποία γυρνάει αντίγραφο του αντικειμένου και συνδυάζεται με .name$ (αυτό γίνεται στην 9). Για το διάβασμα η Item() διαβάζει το αντικείμενο και το συνδέει. Πρέπει όμως να υπάρχει ήδη αντικείμενο εκεί που το βάζουμε!




\\ Example of using Mem() to build \\ Language M2000 ver 9 \\ use of public and private in class/group definitions \\ Stacks, FIFO and LIFO \\ We provide a class AnyName wihout pnext \\ and inside Mem() we add This property \\ We use PushFirst and PushLast methods Form 80,40 Gosub MyClass Class AnyName {       name$       Module AnyName {             Read .name$       } } A=Mem(100) Print "A FIFO, First In First Out" A1=A.Null() A2=A.Null() Stack New {       Data "First","Second","Third", "Forth","Fifth"       While Not Empty {             A.PushFirst &A1,&A2, AnyName(letter$)       }       ShowList(A1) } Print "A LIFO, Last In First Out" A3=A.Null() Stack New {       Data "First","Second","Third", "Forth","Fifth"       While Not Empty {             A.PushLast &A3, AnyName(letter$)       }       ShowList(A3) } Print "Change one item ********************" bb=A.CopyObj(A3) Print bb.name$ bb.name$=bb.name$+"!" A.CopyBack A3, BB \\Print A.Property$(A3,"name$") Print A.Item(A3).name$ Print "Swap 1st with 3rd using external copies***" x=A3 : For i=1 to 2 : x=A.Pnext(x) : Next i Dim aa(2) aa(0)=A.CopyObj(A3) aa(1)=A.CopyObj(x) Swap aa(0),aa(1) 'fast using pointers \\ CopyBack preserve link pointer if found A.CopyBack A3, aa(0) A.CopyBack x, aa(1) Dim aa() ' erase Print "Show List - Swap 1 with 3rd **" ShowList(A3) \\ using object method A.SwapLinked A3, x Print "Show List - Right Order ***" ShowList(A3) Print "Show List - Delete Second from Last***" A.DeleteLinked A3 '' delete second ShowList(A3) Print "Show List - Delete Last ***" For A {       \\ newA3 is a temporary variable       newA3=.Pnext(A3)       .MFree A3       A3=newA3 } ShowList(A3) OldA3=A3 OldA1=A1 Dim bbb(1) bbb(0)=A Print bbb(0).ItemsCount For bbb(0) {       Print "A1"       x=A1       While x<>.Null() {             Print .Item(x).name$             x=.Pnext(x)       }       Print "A3"       x=A3       While x<>.Null() {             Print .Item(x).name$             x=.Pnext(x)       }       Print "Pop from A3"       M=.PopOne(&A3)       Print M.name$       Print .itemscount       M=.PopOne(&A3)       Print M.name$       Print .itemscount       Print "A3"       x=A3       While x<>.Null() {             Print .Item(x).name$             x=.Pnext(x)       }       Print "Pop from A1"       M=.PopOne(&A1)       Print M.name$       Print .itemscount       M=.PopOne(&A1)       Print M.name$       Print .itemscount       Print "A1"       x=A1       While x<>.Null() {             Print .Item(x).name$             x=.Pnext(x)       } } \\ bbb(0) has a copy of A, so we have in A all 8 items, as was before copy A to bbb(0) Print "Original A1" ShowList(OldA1) Print A.Item(OldA1).name$ For This {       M=A.Item(OldA1)       M.name$="new name"       A.Item(OldA1)=M } Print A.Item(OldA1).name$ Print "Original A1 with changed name in A1" ShowList(OldA1) Print "Original A3" ShowList(OldA3) End Sub ShowList(Root)       local x=Root       While x<>A.Null() {             Print A.Item(x).name$             x=A.Pnext(x)       }       Print "Press any key"       a$=key$ End Sub MyClass: Class Global Mem { Private:       Dim d()       noUsed=-1       topfree=0       Items, Count, AddMore=100       Group Null { Null }       Function IsNull {             =Valid(.d(Number).Null)       } Public:       Group Item {             value (x) {                   Link parent d() to d()                   IF valid(d(x).Null) then Error "Null at"+Str$(x)                   IF Type$(d(x))<>"Group" then Error "Empty at"+Str$(x)                   =d(x)             }             Set (x) {                   Link parent d() to d()                   IF valid(d(x).Null) then Error "Null at"+Str$(x)                   IF Type$(d(x))<>"Group" then Error "Empty at"+Str$(x)                   b=d(x).pnext                   Read a                   Group a {                         pnext=b                   }                   d(x)=a             }       }       Group ItemsCount {             Value {                   link parent count to count                   =count             }       }       Function Pnext {             Read where             if .isNull(where) Then "Error pointer is Null"             =.d(where).pnext       }       Module PushLast {       If not Match("SG") Then Error "Bad Parameters"             Read &First             Push 1 ' For malloc             Shift 2 ' so we get Group first             \\ we call Malloc module using parameters in stack             Call .Malloc             Read Last             If First=.Null() Else {                   .d(Last).pnext<=First             }             First=Last       }       Module PushFirst {             If not Match("SSG") Then Error "Bad Parameters"             Read &Root, &Last             Push 1 ' For malloc             Shift 2 ' so we get Group first             \\ we call Malloc module using parameters in stack             Call .Malloc             Read First             If Root=.Null() Then {                         Root=First                         Last=First                   } Else {                         .d(Last).pnext<=First                         Last=First                   }       }       Function Null {             =-1       }       Module AddMore {             Read K             If K<=0 Then Exit             Try ok {             Dim .d(K+.items)             }             If ok Then .Items+=K       }       Module Mem {             Read .Items             If Match("G") Then Read N             N=.Null \\ This is a Union If N is a Group             Dim .d(.Items)=N       }       Function Malloc {             If Not Match("G") Then Error "No Group Found"             Call .Malloc             =Number       }       Module Malloc {             If .noUsed=-1 Then {                   If .topfree>=.Items Then {                         Try {                             .AddMore .AddMore                             ok2=true                         }                         If valid(ok2) Else Error "Memory Full"                   }                   Read .d(.topfree)                   Gosub CheckCommand(.topfree)                   Push .topfree                   .topfree++                   .count++             } Else {                   temp=.d(.noUsed).Null                   Read .d(.noUsed)                   Gosub CheckCommand(.noUsed)                   Push .noUsed                   .noUsed<=temp                   .count++             }                    Sub CheckCommand(X)                   If Match("N") Then {                         If Number=1 Then { \\ use Interface                               For .d(X) {                                     Group kk { pNext=-1}                                     This=kk                               }                         }                   }             End Sub       }       Module Mfree {             Read mf             If .IsNull(mf) Then Error "Invalid Pointer"             old=.noUsed            .noUsed<=mf            .d(mf)=.Null            .d(mf).Null<=old            .count--       }       Function Property {             Read A, A$             A$=".d(A)."+A$ ' M2000 has string pointers             If .IsNull(A) Then Error "Invalid Pointer "+str$(A)             =Eval(A$)             If Match("N") Then A$.=Number       }       Function Property$ {             Read A, A$             A$=".d(A)."+A$             If .IsNull(A) Then Error "Invalid Pointer"             =Eval$(A$.) ' look . after A$             \\ A$. is Not A$ is a pointer To             If Match("S") Then A$. = letter$       }       Function CopyObj {             Read A             If .IsNull(A) Then Error "Invalid Pointer"             =.d(A)       }       Module CopyBack {             Read A             If .IsNull(A) Then Error "Invalid Pointer"             If valid(.d(A).pnext) Then {                   k=.d(A).pnext                   Read .d(A)                   If valid(.d(A).pnext) Else {                         For .d(A) {                               Group kk { pnext }                               This=kk                         }                   }                   .d(A).pnext<=k             } Else {                   Read .d(A)             }       }       Module SwapFast {       Read A, B             If .IsNull(A) Then Error "Invalid Pointer A"             If .IsNull(B) Then Error "Invalid Pointer B"             Swap .d(A), .d(B)       }       Module SwapLinked {             Read A, B             \\ no error checking if we don't have linked list             If .IsNull(A) Then Error "Invalid Pointer A"             If .IsNull(B) Then Error "Invalid Pointer B"             ka=.d(A).pnext : kb=.d(B).pnext             Swap .d(A), .d(B)             .d(A).pnext<=ka : .d(B).pnext<=kb       }       Module DeleteLinked {             Read A             \\ no error checking if we don't have linked list             If .IsNull(A) Then Error "Invalid Pointer"             B=.d(A).pnext             If .IsNull(B) Then Exit 'deleted             .d(A).pnext<=.d(B).pnext             .MFree B       }       Function PopOne {             Read &A             If .IsNull(A) Then Error "Invalid Pointer"             =.d(A)             B=.d(A).pnext             .MFree A             A=B       } } Return

Δεν υπάρχουν σχόλια:

Δημοσίευση σχολίου