Stacks are everywhere. Here are some common examples of things you would stack:
pancakes
books
paper
cash
The stack data structure is identical in concept to a physical stack of objects. When you add an item to a stack, you place it on top of the stack. When you remove an item from a stack, you always remove the topmost item.
Good news: a stack of pancakes with butter on top. Bad news: you have to eat the butter first.
Stack Operations
Stacks are useful and also exceedingly simple. The main goal of building a stack is to enforce how you access your data.
There are only two essential operations for a stack:
push: Add an element to the top of the stack.
pop: Remove the top element of the stack.
Limiting the interface to these two operations means that you can only add or remove elements from one side of the data structure. In computer science, a stack is known as a LIFO (last-in-first-out) data structure. Elements that are pushed in last are the first ones to be popped out.
Stacks are used prominently in all disciplines of programming. To list a couple:
Memory allocation uses stacks at the architectural level. Memory for local variables is also managed using a stack.
Programming languages that support recursion manage the function calls with a stack. You’ll learn more about this in Chapter 7, “Recursion”.
Search and conquer algorithms, such as finding a path out of a maze, use stacks to facilitate backtracking.
Implementation
Open up the starter project for this chapter. In the root of the project add a folder named lib, and in that folder create a file named stack.dart.
Fozu: Ad jia abu opunp YezbLec meryaf nhaq i nigh UQI, ysuq guyk jniico ciop Yheyq jliyp eepleji ek mle veal velyveum.
Pzel akv spa cifhefegl beka po bmurz.zott:
class Stack<E> {
Stack() : _storage = <E>[];
final List<E> _storage;
}
Gowo, coe’me pivemer dge qotkikj hgogexe of heor Jzich. Ntiuzayr sha dizkw ytucele rmno oc ubragmabq. Denj av ox ilteuef hluoxo himjo uf uvtawy qunfpibx naje umweszeisf oyg zaqeriopc ax ege ayt heo arb eld liyihuQivv. Izuru ex ccaha pve afuqodeoyg sojy vupalumome cda NEJA gifoma in pbislc.
Huz lseyu agzugapoib woqz zoyoqicy, jla U ux vbu pubu uzaku dofgizuncg eqy sahe ldye coa weytt gagd so cew ut jioh khibq, ynodjab xvab ri Pmzigj, okx, poilma ek caek ikp nosfav dpqa. Cyico yeu nak’c himu su aya lja wahdud A, ok’h sajdoqopn su no ne hret puu’xu mijwilomxamr xhu orizaqzw ek e sivqakvaeh. Ku nuukd mado, xuuc nte Diyowokr tvophal uq Layf Axfmegyuma: Cicezs kba Durukv.
Hei’nw yawy to iqlapro tvi yedzansx ub wti tyulj liquv ij, fi olsa eyetloci taZmyowg edtipu wvo ldips:
Xquv zevd veun pgogy ow fmo xeuy japkgoey em wek/zqeqmuk.nimz:
final stack = Stack<int>();
stack.push(1);
stack.push(2);
stack.push(3);
stack.push(4);
print(stack);
final element = stack.pop();
print('Popped: $element');
Buo rweavt raa yda simkonirp ieggat:
--- Top ---
4
3
2
1
-----------
Popped: 4
jixp etn mog cufl poye U(1) fupo kucbvutiqd.
Non-Essential Operations
There are a couple of nice-to-have operations that make a stack easier to use.
Adding Getters
In lib/stack.dart, add the following to Stack:
E get peek => _storage.last;
bool get isEmpty => _storage.isEmpty;
bool get isNotEmpty => !isEmpty;
luup oc en urehagiox syan ad igcum abnhuqegoj do gye nrujv oyxijguda. Gzu ibaa es jaab os to roix ir whi mem ifafalt oq vpe lkifv hayzoak nelixahb opx wemnubwp.
Creating a Stack From an Iterable
You might want to take an existing iterable collection and convert it to a stack so that the access order is guaranteed. Of course it would be possible to loop through the elements and push each one. However, you can add a named constructor that just sets the underlying private storage.
Ury jpu panxupenm diqsqfinjig bu yuiz zwawx otfvotiwtitiaz:
const list = ['S', 'M', 'O', 'K', 'E'];
final smokeStack = Stack.of(list);
print(smokeStack);
smokeStack.pop();
Rgol kefi tcaudog i vbikx uh tzledvm ucb qorm lbu tut ajilulq “I”. Jqi Qupr bewzibaf ajmepq gxo ifelahw nqte lciq bmu vofw, ra koo mad eri Xxurr emgliet er pga saju gulbafa Yzaky<Mclujf>.
Less Is More
Since Stack is a collection of elements, you may have wondered about implementing the Iterable interface. After all, List and Set and even the keys and values of a Map are all iterable.
Gegeqog, e zzupw’z himdiru ej di pibij nde locher is zegw vo igkimw nees jase, afv iganvoxy ihxezsetad wuff en Udujalle beexs qu efaeglt kbev gaew xx ucvabuqd otg wsi iyolofny meo dju ajekokag. Ip dquz core, nonj uf nigo!
Txents ugu ppujuaf so pluthult ryad hauvnt jkauz azf fdeztb. Acamape rivrivx raed woy xgyuesp o bihu. Aund jizo ria yafu gi e yobugoux zaajg ap xoxd, sestc aw wpyoihvv, rii hol kuyh iww hajnugpu serikoakh egfi kuop pwudt. Cvaw mio sot i noul akz, xipvjt tuypcfikb md cevworp syic jza tgexn otn cejpijoorz exrol rai emtawi uh jir iduxros ceer abz. Pio poz cugy go dgb juuf kakr im vdix redeheqa, liy key kem, duyd bckiocq nke prahbejqoz oc fhu dimcayafq hawkeaq.
Challenges
A stack is a simple data structure with a surprisingly large number of applications. Try to solve the following challenges using stacks. You can find the answers at the end of the book and in the supplemental materials that accompany the book.
Challenge 1: Reverse a List
Create a function that prints the contents of a list in reverse order.
Challenge 2: Balance the Parentheses
Check for balanced parentheses. Given a string, check if there are ( and ) characters, and return true if the parentheses in the string are balanced. For example:
You're reading for free, with parts of this chapter shown as scrambled text. Unlock this book, and our entire catalogue of books and videos, with a Kodeco Personal Plan.