med dessa viktiga metoder förklarade, låt oss ta en titt på den slutliga implementeringen av vår Stack class:
push-och pop-metoderna visas exakt som vi förväntar oss (lines13–32). Vi kan använda vår push-metod för att skapa en anpassad initialiserare med vissa variadiska värden (linjer 7-11). Dessutom kan vi söka efter en tom stapel genom att kontrollera om vår rootNode har ett värde (linjer 34-36) och har en grundläggande utskriftsmetod som itererar genom vår lista så länge den kan komma åt noder genom nästa egenskap (linjer 38-44).
ett grundläggande test av vår stackfunktionalitet ser ut så här:
att veta hur man implementerar en stack är en sak, men ännu viktigare är att känna igen situationer för vilka en stack är väl lämpad. I nästa avsnitt kommer vi att titta på tre sådana fall.
Användningsfall 1: Omvänd ordning
eftersom ordningen på en stapel är fast kan omvänd ordning uppnås mycket enkelt genom att poppa element från en stapel och omedelbart på en annan. Ingen röra runt med att byta index!
användningsfall 2: Testa symmetri
ett annat bra användningsfall för staplar testar symmetri. I exemplet nedan testar vi en sträng parentes för att säkerställa att varje stängningsfäste är rätt motsvarighet till en tidigare öppningsfäste.
vi börjar med att kontrollera att teckenräkningen är delbar med två som ett udda antal tecken skulle omedelbart genom asymmetrisk (rad 6). Därefter kontrollerar vi att vi har giltig inmatning genom att definiera en teckenuppsättning olagliga tecken och sedan kontrollera att vår inmatningssträng har ett nollområde av olagliga tecken (linjer 7-8). För att kontrollera våra stängnings-och öppningsfästen är en matchning, lägger vi dem i en ordbok som nyckelvärdespar (rad 10). I andra situationer kan du kanske beräkna det inversa värdet utan att behöva lagra par i en ordlista. Sedan har vi vår stack (linje 11). Syftet med vår stack i detta fall är att lagra öppningsfästen. När vi itererar genom vår sträng kan vi kontrollera om vår karaktär är en öppningsfäste genom att testa om det är en nyckel i vår ordlista. Om det är, skjuter vi det på vår stack. När vi väl har hittat vår första stängda konsol vet vi att vi arbetar genom den andra halvan av vårt mönster, så vi sätter vår förstahälften boolean till false (linje 12). Om vi hittar några fler öppningsfästen efter denna punkt kan vi kontrollera boolean och ange ett misslyckat test. För varje stängningsfäste, vi dyker upp den sista öppningsfästet och kontrollerar om de är ett korrekt nyckelvärdespar. Återigen behöver vi bara iterera genom strängen en gång, så vi får mycket värde ur en linjär algoritm.
Använd fall 3: ångra kommandon
slutligen kommer vi att använda en stapel tillsammans med kommandomönstret för att skapa en ångrahistorik. För att börja, låt oss ta en titt på ett enkelt bankkontoobjekt. Den har en balans och en övertrasseringsgräns och några enkla metoder för att deponera och ta ut pengar:
istället för att ringa insättnings-och uttagsmetoderna direkt kan vi lagra relevant information i ett kommando. I utdraget nedan anger vi vilken typ av åtgärd vi vill utföra med en enum-egendom (insättning eller uttag) och ett belopp . Vi lagrar också en boolesk för att ange om kommandot kunde utföras (linjerna 4-11). Observera att om uttagsbegäran överstiger kassakreditgränsen kommer inget att hända med bankkontot och den framgångsrika boolean kommer att förbli falsk, annars blir det sant när kommandot har slutförts (raderna 18-26). Vi har två metoder för att ringa eller Ångra kommandot, var och en tar ett bankkonto som ett argument (rader 18 & 28). Dessa metoder tar bankkontot och kallar dess instansmetoder som vi såg i föregående utdrag.
när vi går tillbaka till bankkontot kan vi nu presentera vår commandStack-egendom, som har initierats med vår BankAccountType (linje 47). Vi markerar våra insättnings-och uttagsmetoder som fileprivate så att de endast kan nås av vårt BankAccountCommand (rader 62 & 66). Nu har vi två exponerade metoder: process (kommando:) och undoLastCommand (). Den första accepterar ett kommando som en ingång, kör det med bankkontot som ingång och trycker sedan kommandot på stapeln. Under tiden undoLastCommand-metoden dyker upp det sista kommandot från stacken och utför en ångra (rader 51-60).
detta är ett mycket enkelt mönster, och en som är mycket kraftfull. De möjliga applikationerna är oändliga och ger en tillfredsställande användarupplevelse.
och nu får vi se mönstret i aktion:
Wrap Up
i den här artikeln undersökte vi begreppet en stack och LIFO-beteende. Vi implementerade vår egen stack med en dubbelt länkad lista och visade hur den allokerar och avallokerar minnet när storleken på stacken ändras. Vi tittade också på tre vanliga användningsfall för staplar: omvänd, testa symmetri och ångra. Var och en av dessa tre situationer kommer upp otaliga gånger i verkliga projekt. Jag hoppas att du kommer att tänka på en stack som en lämplig struktur för att hantera dessa behov. Som alltid, tack för att du läste!