480 likes | 643 Views
Två sätt att hantera data, stack och kö. Två sätt att hantera data, stack och kö. sist in. Stack. LIFO. först ut. Två sätt att hantera data, stack och kö. sist in. Stack. först in. först ut. LIFO. Kö. först ut. FIFO. Stack. Likna stacken vid en stege.
E N D
Två sätt att hantera data,stack och kö sist in Stack LIFO först ut
Två sätt att hantera data,stack och kö sist in Stack först in först ut LIFO Kö först ut FIFO
Stack • Likna stacken vid en stege • man kan bara kliva på i nedre ändan, push • man kan bara kliva av i nedre ändan, pop • när någon ny kliver på måste alla andra på stegen ta ett kliv uppåt • när någon kliver av tar alla ett steg nedåt • den som kliver på sist kliver av först, lifo( last in first out )
Stackexempel • Ett exempel på hur man m h a en länkad lista och funktionerna push() och pop() skapar en datastack ( datastruktur ). • Programmet vänder på teckenordningen i en sträng • Att lagra och vända på ordningen är typiskt för stacken
Stackexempel Det data som vi vill lagra på stacken. Om man konstruerar Push() och Pop() för att ta en struct blir dessa funktioner generella. #include <stdio.h> #include <stdlib.h> typedef struct { int heltalsData; } DataTyp ; typedef struct StackElementTyp { DataTyp d; struct StackElementTyp *next ; } StackElementTyp ; typedef StackElementTyp* BottenPekarTyp ; void Pop( BottenPekarTyp *b, DataTyp *x ); void Push( BottenPekarTyp *b , DataTyp x ) ; int ArTom( BottenPekarTyp b ); void Baklanges( char xString[] ); datatyper och funktionsprototyp Push()
Stackexempel För att kunna lagra som en stack m h a en länkad lista så måste det finnas en next-pekare. Denna tillfogas av Push() m h a denna struct #include <stdio.h> #include <stdlib.h> typedef struct { int heltalsData; } DataTyp ; typedef struct StackElementTyp { DataTyp d; struct StackElementTyp *next ; } StackElementTyp ; typedef StackElementTyp* BottenPekarTyp ; void Pop( BottenPekarTyp *b, DataTyp *x ); void Push( BottenPekarTyp *b , DataTyp x ) ; int ArTom( BottenPekarTyp b ); void Baklanges( char xString[] ); datatyper och funktionsprototyp DataTyp Push() StackElementTyp NULL
Stackexempel #include <stdio.h> #include <stdlib.h> typedef struct { int heltalsData; } DataTyp ; typedef struct StackElementTyp { DataTyp d; struct StackElementTyp *next ; } StackElementTyp ; typedef StackElementTyp* BottenPekarTyp ; void Pop( BottenPekarTyp *b, DataTyp *x ); void Push( BottenPekarTyp *b , DataTyp x ) ; int ArTom( BottenPekarTyp b ); void Baklanges( char xString[] ); För att tydligt kunna skapa en pekare, handtag, till stacken (botten). OBS pekare! datatyper och funktionsprototyp DataTyp Push() StackElementTyp NULL BottenPekarTyp
NULL Stackexempel #include <stdio.h> #include <stdlib.h> typedef struct { int heltalsData; } DataTyp ; typedef struct StackElementTyp { DataTyp d; struct StackElementTyp *next ; } StackElementTyp ; typedef StackElementTyp* BottenPekarTyp ; void Pop( BottenPekarTyp *b, DataTyp *x ); void Push( BottenPekarTyp *b , DataTyp x ) ; int ArTom( BottenPekarTyp b ); void Baklanges( char xString[] ); För att lägga till, i botten, stackelement på stacken datatyper och funktionsprototyp DataTyp Push() StackElementTyp BottenPekarTyp
NULL Stackexempel #include <stdio.h> #include <stdlib.h> typedef struct { int heltalsData; } DataTyp ; typedef struct StackElementTyp { DataTyp d; struct StackElementTyp *next ; } StackElementTyp ; typedef StackElementTyp* BottenPekarTyp ; void Pop( BottenPekarTyp *b, DataTyp *x ); void Push( BottenPekarTyp *b , DataTyp x ) ; int ArTom( BottenPekarTyp b ); void Baklanges( char xString[] ); För att ta bort, i botten, stackelement på stacken datatyper och funktionsprototyp DataTyp Pop() StackElementTyp BottenPekarTyp
Stackexempel Funktionen ändrar i strängen så att tecknen kommer i omvänd ordning. main() int main( void ){ char strang[21] = {'\0'} ; printf("Ge en sträng, max 20 tecken: --> "); scanf("%s", strang ); Baklanges( strang ); printf ("\nBaklänges blir det:\t%s", strang ); return 0; } på nästa bild
NULL Stackexempel Fyller på stacken Baklanges() void Baklanges( char xString[] ){ int i; DataTyp data; BottenPekarTyp bottenPek = NULL ; for ( i=0 ; xString[i] != '\0' ; ++i ){ data.heltalsData = xString[i]; Push( &bottenPek , data ); } for ( i=0 ; xString[i] != '\0' ; ++i ){ Pop( &bottenPek , &data ); xString[i] = data.heltalsData ; } return; } A n d på nästa bild e r s bottenPek
NULL Stackexempel Både data in resp data ut Skapar stackelement , data + pekare Push() A n void Push( BottenPekarTyp *b , DataTyp x ) { BottenPekarTyp temp ; temp = malloc(sizeof( StackElementTyp )); temp->d = x ; temp->next = *b ; *b = temp ; return; } d invärde e r s utvärde bottenPek
NULL Stackexempel Fyller på stacken Var borttagit data skall lagras Baklanges() void Baklanges( char xString[] ){ int i; DataTyp data; BottenPekarTyp bottenPek = NULL ; for ( i=0 ; xString[i] != '\0' ; ++i ){ data.heltalsData = xString[i]; Push( &bottenPek , data ); } for ( i=0 ; xString[i] != '\0' ; ++i ){ Pop( &bottenPek , &data ); xString[i] = data.heltalsData ; } return; } A n d e tillbaka r ut s på nästa bild bottenPek
NULL Stackexempel Både data in resp data ut Tar bort stackelement och återför data i den borttagna tunnan via *x . Pop() A n void Pop( BottenPekarTyp *b, DataTyp *x ){ BottenPekarTyp b1 = *b ; if ( !ArTom( b1 )) { *x = b1 -> d ; *b = b1 -> next ; free( b1 ); } else printf("Tom stack!\n"); return; } d e utvärde r s invärde bottenPek
NULL Stackexempel Funktionen Baklanges() tar slut och har via referensen xString uppdaterat strängen i main(). Baklanges() void Baklanges( char xString[] ){ int i; DataTyp data; BottenPekarTyp bottenPek = NULL ; for ( i=0 ; xString[i] != '\0' ; ++i ){ data.heltalsData = xString[i]; Push( &bottenPek , data ); } for ( i=0 ; xString[i] != '\0' ; ++i ){ Pop( &bottenPek , &data ); xString[i] = data.heltalsData ; } return; } A n d e r s bottenPek
Stackexempel int main( void ){ char strang[21] = {'\0'} ; printf("Ge en sträng, max 20 tecken: --> "); scanf("%s", strang ); Baklanges( strang ); printf ("\nBaklänges blir det:\t%s", strang ); return 0; } Funktionen ändrar i strängen så att tecknen kommer i omvänd ordning. main()
Stackexempel ”polsk notation” Programmerings-strategi 13, 4, -, 2, 3, *, + : polsk notation ( utan parenteser ) (13-4) + (2*3) = 15 : vanlig notation Ett c-program kan beräkna det ”polska” uttrycket mha två stackar. En stack ,röd, innehåller uttrycket ”pushat” baklänges och den andra, grön, används för beräkning. Värde flyttas i tur och ordning från röd till grön, när en operator står på tur utförs operationen i beräkningsstacken (gröna). tidsaxel
Stackexempel ”polsk notation” #include <stdio.h> #include <stdlib.h> #include <ctype.h> #include <conio.h> /* ej ANSI-C, getch()*/ typedef struct { enum {operation , varde } sort ; union { int tal ; char op ; } u ; } DataTyp ; typedef struct StackElementTyp { DataTyp d; struct StackElementTyp *next ; } StackElementTyp ; typedef StackElementTyp* BottenPekarTyp ; void Pop( BottenPekarTyp *b, DataTyp *x ); void Push( BottenPekarTyp *b , DataTyp x ) ; int ArTom( BottenPekarTyp b ); BottenPekarTyp SkapaPolskStack( void ); int BeraknaStack( BottenPekarTyp *polskStackPek ); DataTyp* InmatningFranKBD( char* cFranKBDPek ); Det som är ändrat sen föregående program är datatypen. Den kan nu lagra en flagga (sort) som talar om ifall innehållet är en operation eller tal. Dessutom kan den lagra en char eller en int, mer om detta i ett kommande avsnitt om union. Några nya funktioner har tillkommit. definitioner ochdeklarationer
Stackexempel ”polsk notation” #include <stdio.h> #include <stdlib.h> #include <ctype.h> #include <conio.h> /* ej ANSI-C, getch()*/ typedef struct { enum {operation , varde } sort ; union { int tal ; char op ; } u ; } DataTyp ; typedef struct StackElementTyp { DataTyp d; struct StackElementTyp *next ; } StackElementTyp ; typedef StackElementTyp* BottenPekarTyp ; void Pop( BottenPekarTyp *b, DataTyp *x ); void Push( BottenPekarTyp *b , DataTyp x ) ; int ArTom( BottenPekarTyp b ); BottenPekarTyp SkapaPolskStack( void ); int BeraknaStack( BottenPekarTyp *polskStackPek ); DataTyp* InmatningFranKBD( char* cFranKBDPek ); Observera att funktionerna Pop(), Push() och ArTom() är exakt desamma som i föregående exempel. De har som parameter en struct, eller pekare till en struct, av typen DataTyp. Hur sedan denna struct ser ut spelar ingen roll definitioner ochdeklarationer
Stackexempel ”polsk notation” Självförklarande? Här skapas stacken ( polsk) som innehåller det ”polska” uttrycket. main() int main( void ){ BottenPekarTyp polsk = NULL ; polsk = SkapaPolskStack(); printf("\n\nSvaret blev:\t%d ", BeraknaStack( &polsk )); return 0; } på nästa bild polsk
13, 4, -, 2, 3, *, + Stackexempel ”polsk notation” Programmerings-strategi BottenPekarTyp SkapaPolskStack() { char franKBD = ' ' ; DataTyp *xPek ; BottenPekarTyp polskStackPek = NULL; xPek = InmatningFranKBD( &franKBD ); if (franKBD == '\r') return NULL; else { polskStackPek = SkapaPolskStack(); Push( &polskStackPek, *xPek ); free( xPek ); return polskStackPek; } } SkapaPolskStack() Eftersom det ”polska” uttrycket inmatas från vänster till höger och beräkning skall göras först med det först inmatade (FIFO) så ”pushas” det inmatade uttrycket i omvänd ordning på stacken. Detta uppnås genom att funktionen arbetar rekursivt och på så sätt utnyttjar programmets exekveringsstack. se anteckningar programstack polskStackPek
Stackexempel ”polsk notation” main() int main( void ){ BottenPekarTyp polsk = NULL ; polsk = SkapaPolskStack(); printf("\n\nSvaret blev:\t%d ", BeraknaStack( &polsk )); return 0; } på nästa bild polsk
Programmerings-strategi Denna funktion plockar (Pop()) data från den ”polska” stacken (röd) och ”pushar” det på beräkningsstacken (grön).Om man ”popar” en operator så utförs beräkningen med de två nedersta elementen på beräkningsstacken som argument, dessa ”popas” bort. Resultatet ”pushas” på beräkningsstacken. Stackexempel ”polsk notation” int BeraknaStack( BottenPekarTyp *polskStackPek ) { BottenPekarTyp beraknaStackPek = NULL; DataTyp x; char binOp; int arg1, arg2 ; while ( !ArTom( *polskStackPek ) ) { Pop(polskStackPek, &x ); if ( x.sort == operation ) { binOp = x.u.op; Pop( &beraknaStackPek, &x ); arg2 = x.u.tal; Pop( &beraknaStackPek, &x ); arg1 = x.u.tal; x.sort = varde; switch ( binOp ) { case '+': x.u.tal = arg1 + arg2;break; case '-': x.u.tal = arg1 - arg2;break; case '*': x.u.tal = arg1 * arg2; } Push( &beraknaStackPek, x ); } else Push( &beraknaStackPek, x ); } Pop( &beraknaStackPek, &x ); return ( x.u.tal ); }
Stackexempel ”polsk notation” int main( void ){ BottenPekarTyp polsk = NULL ; polsk = SkapaPolskStack(); printf("\n\nSvaret blev:\t%d ", BeraknaStack( &polsk )); return 0; } main() 13, 4, -, 2, 3, *, +
Ett sätt att hantera data,kö (dataabstraktion) En kö är en kö ... • sin tur blir det när man blir först i kön • man får vackert gå och ställa sig sist Nu är det min tur! Äsch sist!
NULL ”köhandtaget” data data data data pekare pekare pekare pekare börjanPek Själva kön slutPek Hur kan en köimplementeras, dataabstraheras ? • en kö kan realiseras som en länkad lista • via ett ”köhandtag” (struktur) håller man reda på början och slut i kön • m h a ”köhandtaget” kan man då lägga till data sist i kön resp plocka bort i början
Kö Användbara funktionerprototyp • void StallDigIKon( KoTyp* , DataTyp); • placerar data sist i kön. • void Nasta( KoTyp* , DataTyp* ); • återför datat som är först i kön och tar sedan bort det från kön • int ArTom( KoTyp ); • returnerar 1 om kön är tom annars 0. • DataTyp VemPaTur( KoTyp ); • returnerar datat som ligger först i kön först in först ut Kö FIFO
Köett exempel Detta program tar emot heltal från tangentbordet och lagrar dem i en kö.På kommando kan det första talet i kön plockas bort. queue.exe
Programmerings-strategi NULL data data data data pekare pekare pekare pekare börjanPek slutPek Köhur programmet fungerar /* queue.c */ #include <stdio.h> #include <stdlib.h> typedef struct { int heltal; } DataTyp ; typedef struct KoElementTyp { DataTyp d; struct KoElementTyp *next ; } KoElementTyp ; Datat som programmet skall bearbeta inläses till en struct av typen DataTyp. Funktionen StallDigIKon() tillfogar en next-pekare och lagrar detta , data och pekare, i en ny struktur av typen KoElementTyp. Denna inlänkas sedan sist i kön. DataTyp data StallDigIKon() KoElementTyp ”köhandtaget” Själva kön
NULL data data data data pekare pekare pekare pekare börjanPek slutPek Köhur programmet fungerar typedef struct KoElementTyp { DataTyp d; struct KoElementTyp *next ; } KoElementTyp ; typedef KoElementTyp* KoElementPekarTyp ; typedef struct KoTyp { KoElementPekarTyp koBorjanPek, koSlutPek ; } KoTyp ; KoElementTyp ”köhandtaget” KoTyp Själva kön
NULL data data data data pekare pekare pekare pekare börjanPek slutPek Köhur programmet fungerar Tillfogar en ”tunna” sist i kön. void StallDigIKon( KoTyp* , DataTyp); void Nasta( KoTyp* , DataTyp* ); int ArTom( KoTyp ); void Info( void ); använda funktioner och typer data DataTyp StallDigIKon() KoElementTyp DataTyp KoTyp KoElementPekarTyp
NULL data data data data pekare pekare pekare pekare börjanPek slutPek Köhur programmet fungerar Tar bort första ”tunnan” i kön void StallDigIKon( KoTyp* , DataTyp); void Nasta( KoTyp* , DataTyp* ); int ArTom( KoTyp ); void Info( void ); använda funktioner och typer data DataTyp Nasta() KoElementTyp DataTyp KoTyp KoElementPekarTyp
börjanPek slutPek Köhur programmet fungerar void StallDigIKon( KoTyp* , DataTyp); void Nasta( KoTyp* , DataTyp* ); int ArTom( KoTyp ); void Info( void ); använda funktioner och typer Funktionen ArTom() testar om koBorjanPek == NULL Funktionen Info() skriver ut lite information om inmatning och terminering av programmet. NULL KoTyp NULL
Köhur programmet fungerar int main( void ) { char c ; DataTyp data; KoTyp ko = {NULL, NULL}; Info(); while (printf("--> "),scanf(" %c",&c), c != 'a' ) { if ( c=='+' ) { scanf("%d", &data.heltal); StallDigIKon( &ko, data ); } else if ( c=='-' ) if ( ArTom( ko )) printf("Tom kö! \n"); else { Nasta( &ko, &data ); printf("%d har tagits bort från kön!\n", data.heltal); } } return; } data heltal main() NULL Ko data NULL koBorjanPek heltal kopia koSlutPek
x heltal koBorjanPek koSlutPek Köhur programmet fungerar void StallDigIKon( KoTyp* koPek, DataTyp x) { KoElementPekarTyp temp; temp = malloc(sizeof(KoElementTyp)) ; temp->d = x; temp->next = NULL ; if ( ArTom( *koPek )) koPek->koBorjanPek = koPek->koSlutPek = temp ; else { koPek->koSlutPek->next = temp ; koPek->koSlutPek = temp ; } return ; } koPek StallDigIKon() ? kopia från main() NULL Ko NULL
x heltal koBorjanPek koSlutPek Köhur programmet fungerar void StallDigIKon( KoTyp* koPek, DataTyp x) { KoElementPekarTyp temp; temp = malloc(sizeof(KoElementTyp)) ; temp->d = x; temp->next = NULL ; if ( ArTom( *koPek )) koPek->koBorjanPek = koPek->koSlutPek = temp ; else { koPek->koSlutPek->next = temp ; koPek->koSlutPek = temp ; } return ; } koPek StallDigIKon() temp ? NULL Ko d=? pekare NULL skapas på heapen
x heltal NULL d heltal next koBorjanPek koSlutPek Köhur programmet fungerar void StallDigIKon( KoTyp* koPek, DataTyp x) { KoElementPekarTyp temp; temp = malloc(sizeof(KoElementTyp)) ; temp->d = x; temp->next = NULL ; if ( ArTom( *koPek )) koPek->koBorjanPek = koPek->koSlutPek = temp ; else { koPek->koSlutPek->next = temp ; koPek->koSlutPek = temp ; } return ; } koPek StallDigIKon() temp NULL Ko NULL
x heltal NULL d heltal next koBorjanPek koSlutPek Köhur programmet fungerar void StallDigIKon( KoTyp* koPek, DataTyp x) { KoElementPekarTyp temp; temp = malloc(sizeof(KoElementTyp)) ; temp->d = x; temp->next = NULL ; if ( ArTom( *koPek )) koPek->koBorjanPek = koPek->koSlutPek = temp ; else { koPek->koSlutPek->next = temp ; koPek->koSlutPek = temp ; } return ; } koPek StallDigIKon() temp OBS! Köhandtaget, röda tunnan, tillhör main() NULL Ko NULL
data heltal NULL d heltal koBorjanPek next koSlutPek Köhur programmet fungerar int main( void ) { char c ; DataTyp data; KoTyp ko = {NULL, NULL}; Info(); while (printf("--> "),scanf(" %c",&c), c != 'a' ) { if ( c=='+' ) { scanf("%d", &data.heltal); StallDigIKon( &ko, data ); } else if ( c=='-' ) if ( ArTom( ko )) printf("Tom kö! \n"); else { Nasta( &ko, &data ); printf("%d har tagits bort från kön!\n", data.heltal); } } return; } main() Om igen! Ko data heltal
x heltal d NULL d heltal heltal next next koBorjanPek koSlutPek Köhur programmet fungerar void StallDigIKon( KoTyp* koPek, DataTyp x) { KoElementPekarTyp temp; temp = malloc(sizeof(KoElementTyp)) ; temp->d = x; temp->next = NULL ; if ( ArTom( *koPek )) koPek->koBorjanPek = koPek->koSlutPek = temp ; else { koPek->koSlutPek->next = temp ; koPek->koSlutPek = temp ; } return ; } koPek StallDigIKon() temp Ko
NULL d d heltal heltal next next koBorjanPek koSlutPek Köhur programmet fungerar int main( void ) { char c ; DataTyp data; KoTyp ko = {NULL, NULL}; Info(); while (printf("--> "),scanf(" %c",&c), c != 'a' ) { if ( c=='+' ) { scanf("%d", &data.heltal); StallDigIKon( &ko, data ); } else if ( c=='-' ) if ( ArTom( ko )) printf("Tom kö! \n"); else { Nasta( &ko, &data ); printf("%d har tagits bort från kön!\n", data.heltal); } } return; } data heltal Dags att plocka bort en tunna main() ko
koPek xPek NULL d d heltal heltal next next koBorjanPek koSlutPek Köhur programmet fungerar Dags att plocka bort en tunna void Nasta( KoTyp* koPek, DataTyp* xPek) { KoElementPekarTyp temp = koPek->koBorjanPek ; if ( !ArTom( *koPek ) ) { *xPek = temp -> d ; koPek->koBorjanPek = temp->next ; free( temp ); } else printf("Tom kö! \n"); return; } Nasta() data heltal De röda tunnorna hör hemma i main() ko
koPek xPek NULL d d heltal heltal next next koBorjanPek koSlutPek Köhur programmet fungerar Dags att plocka bort en tunna void Nasta( KoTyp* koPek, DataTyp* xPek) { KoElementPekarTyp temp = koPek->koBorjanPek ; if ( !ArTom( *koPek ) ) { *xPek = temp -> d ; koPek->koBorjanPek = temp->next ; free( temp ); } else printf("Tom kö! \n"); return; } Nasta() temp data heltal De röda tunnorna hör hemma i main() Ko
koPek xPek NULL d d heltal heltal next next koBorjanPek koSlutPek Köhur programmet fungerar Dags att plocka bort en tunna void Nasta( KoTyp* koPek, DataTyp* xPek) { KoElementPekarTyp temp = koPek->koBorjanPek ; if ( !ArTom( *koPek ) ) { *xPek = temp -> d ; koPek->koBorjanPek = temp->next ; free( temp ); } else printf("Tom kö! \n"); return; } Nasta() temp data heltal ko De gröna tunnorna hör hemma på heapen
koPek xPek NULL d d heltal heltal next next koBorjanPek koSlutPek Köhur programmet fungerar Dags att plocka bort en tunna void Nasta( KoTyp* koPek, DataTyp* xPek) { KoElementPekarTyp temp = koPek->koBorjanPek ; if ( !ArTom( *koPek ) ) { *xPek = temp -> d ; koPek->koBorjanPek = temp->next ; free( temp ); } else printf("Tom kö! \n"); return; } Nasta() temp data heltal Ko De röda tunnorna hör hemma i eller kommer från, main()
ko NULL d heltal koBorjanPek next koSlutPek Köhur programmet fungerar int main( void ) { char c ; DataTyp data; KoTyp ko = {NULL, NULL}; Info(); while (printf("--> "),scanf(" %c",&c), c != 'a' ) { if ( c=='+' ) { scanf("%d", &data.heltal); StallDigIKon( &ko, data ); } else if ( c=='-' ) if ( ArTom( ko )) printf("Tom kö! \n"); else { Nasta( &ko, &data ); printf("%d har tagits bort från kön!\n", data.heltal); } } return; } data heltal Innehåller nu det borttagna datat main() osv .... queue.exe