知识点14:栈(stacks)

Now we're going to talk about a couple of variations on arrays and linked lists. We're going to talk about stacks.

Specifically we're going to talk about a data structure called a stack.

Recall from previous discussions about pointers and memory, that the stack is also the name for a segment of memory where statically declared memory -- memory that you name, variables that you name, et cetera and function frames which we also call stack frames exist.

So this is a stack data structure not a stack segment of memory.


So because of this restriction on how information can be added to and removed from a stack, there's really only two things we can do with a stack.

So we're going to look at both implementations, both array based and linked list based.

And we're going to start with array based.

value array[]略

We also keep track of the top of the stack. What element is the most recently added to the stack? And so we keep track of that in a variable called top.

And all of this gets wrapped up together into a new data type called a stack.

And once we're created this new data type, we can treat it like any other data type.

We can declare stack s, just like we could do int x, or char y. And when we say stack s, well what happens is we get a set of memory set aside for us.

In this case capacity I've apparently decided is 10 because I've got a single variable of type stack which contains two fields recall.

An array, in this case is going to be an array of integers as is the case in most of my examples. And another integer variable capable of storing the top, the most recently added element to the stack.

So one single stack of what we just defined looks like this. It's a box containing an array of 10 what will be integers in this case and another integer variable there in green to indicate the top of the stack.

To set the top of the stack we just say s.top. That's how we access a field of a structure recall.

s.top equals 0 effectively does this to our stack.

So again we have two operations that we can perform now. We can push and we can pop.

Let's start with push.

Well in general the push function is going to need to accept a pointer to the stack. Now take a second and think about it. Why would we want to accept a pointer to the stack?

Recall from previous videos on variable scope and pointers, what would happen if we just sent stack, s rather in as a parameter? What would actually be passed in there?

Remember we're creating a copy when we pass it to a function unless we use pointers. And so this function push needs to accept a pointer to the stack so that we're actually changing the stack we intend to change.

The other thing push probably wants to accept is a data element of type value. In this case, again, an integer that we're going to add to the top of stack. So we've got our two parameters. What are we going to now do inside of push?

Well, simply, we're just going to add that element to the top of the stack and then change where the top of the stack is, that s dot top value.

So this is what a function declaration for push might look like in an array-based implementation.

Again this isn't a hard and fast rule that you could change this and have it vary in different ways.

Perhaps s is declared globally. And so you don't even need to pass it is as a parameter. This is again just a general case for push. And there are different ways to implement it. But in this case our push is going to take two arguments, a pointer to a stack and a data element of type value, integer in this case.

So we declared s, we said s.top equals 0. Now let's push the number 28 onto the stack.

Well what does that mean?

Well currently the top of the stack is 0. And so what's basically going to happen is we're going to stick the number 28 into array location 0. Pretty straightforward, right, that was the top and now we're good to go. And then we need to change what the top of the stack will be.

So that the next time we push an element in, we're going to store it in array location, probably not 0. We don't want to overwrite what we just put there. And so we'll just move the top to 1.

That probably makes sense.

Now if we want to put another element onto the stack, say we want to push 33,

well now we're just going to take 33 and put it at array location number 1, and then change the top of our stack to be array location number two.

So if the next time we want to push an element onto the stack, it'll be put in array location 2.

And let's do that one more time. We'll push 19 off of the stacks.

We'll put 19 in array location 2 and change the top of our stack to be array location 3 so if the next time we need to make a push we're good to go.


OK, so that's pushing in a nutshell. What about popping?

So popping is the sort of counterpart to pushing. It's how we remove data from the stack.

And in general pop needs to do the following. It needs to accept a pointer to the stack, again in the general case. In some other case you might have declared the stack globally, in which case you don't need to pass it in because it already has access to it as a global variable.

But then what else do we need to do? Well we were incrementing the top of the stack in push, so we're probably going to want to decrement the top of the stack in pop, right?

And then of course we're also going to want to return the value that we remove. If we're adding elements, we want to get elements out later on, we probably actually want to store them so we don't just delete them from the stack and then do nothing with them.

Generally if we're pushing and popping here we want to store this information in a meaningful way and so it doesn't make sense to just discard it. So this function should probably return a value to us.

So this is what a declaration for pop might look like there at the top left.

This function returns data of type value. Again we've been using integers throughout. And it accepts a pointer to a stack as its sole argument or sole parameter.

So what is pop going to do? Let's say we want to now pop an element off of s.

So remember I said that stacks are last in, first out, LIFO data structures.

Which element is going to be removed from the stack?

Did you guess 19?

Because you'd be right.

19 was the last element we added to the stack when we were pushing elements on, and so it's going to the first element that gets removed.

It's as if we said 28, and then we put 33 on top of it, and we put 19 on top of that. The only element we can take off is 19.

Now in the diagram here what I've done is sort of deleted 19 from the array. That's not actually what we're going to do.

We're just going to kind of pretend it isn't there. It's still there in that memory location, but we're just going to ignore it by changing the top of our stack from being 3 to 2.

So if we were to now push another element onto the stack, it would overwrite 19. But let's not go through the trouble of deleting 19 from the stack.

We can just pretend it isn't there. For purposes of the stack it's gone if we change the top to be 2 instead of 3. All right, so that was pretty much it. That's all we need to do to pop an element off. Let's do it again. So I've highlighted it in red here to indicate we're making another call. We're going to do the same thing.

So what's going to happen? Well, we're going to store 33 in x and we're going to change the top of the stack to 1.

So that if we were now to push an element into the stack which we're going to do right now, what's going to happen is we're going overwrite array location number 1.

So that 33 that was sort of left behind that we just pretended isn't there anymore, we're just going to clobber it and put 40 there instead.

And then of course, since we made a push, we're going to increment the top of the stack from 1 to 2 so that if we now add another element it'll go into array location number two.


Now linked lists are another way to implement stacks.

And if this definition on the screen here looks familiar to you, it's because it looks almost exactly the same, in fact, it pretty much is exactly the same as a singly linked list.

The only restriction here is for us as programmers, we're not allowed to insert or delete randomly from the singly linked list which we could previously do. We can only now insert and delete from the front or the top of the linked list.

That's really the only difference though. This is otherwise a singly linked list. It's only the restriction replacing on ourselves as programmers that changes it into a stack.

The rule here is to always maintain a pointer to the head of a linked list. This is of course a generally important rule first. For singly linked list anyway you only need a pointer to the head in order to have that chain be able to refer to every other element in the linked list.

But it's particularly important with a stack. And so generally you're going to actually want this pointer to be a global variable. It's probably going to be even easier that way. So what are the analogs of push and pop?

Right. So pushing again is adding a new element to the stack. In a linked list that means we're going to have to create a new node that we're going to add into the linked list, and then follow the careful steps that we've outlined previously in singly linked lists to add it to the chain without breaking the chain and losing or orphaning any elements of the linked list. And that's basically what that little blob of text there summarizes. And let's take a look at it as a diagram.

So here's our linked list. It concurrently contains four elements.

And more perfectly here's our stack containing four elements. And let's say we now want to push a new item onto this stack. And we want to push a new item whose data value is 12.

Well what are we going to do? Well first we're going to malloc space, dynamically allocate space for a new node.

And of course immediately after we make a call to malloc we always make sure to check for null, because if we got null back there was some sort of problem.

We don't want to dereference that null pointer or you will suffer a seg fault. That's not good.

So we've malloced of the node. We'll assume we've had success here. We're going to put 12 into the data field of that node.

Now do you recall which of our pointers moves next so we don't break the chain?

We have a couple of options here but the only one that's going to be safe is to set news next pointer to point to the old head of the list or what will soon be the old head of the list.

And now that all of our elements are chained together, we can just move list to point to the same place that new does. And we have now effectively pushed a new element onto the front of the stack.


To pop we just want to delete that first element. And so basically what we have to do here, well we have to find the second element. Eventually that will become the new head after we delete the first one.

So we just need to start from the beginning, move one forward. Once we've got a hold on one forward of where we currently are we can delete the first one safely and then we can just move the head to point to what was the second term and then now is the first after that node has been deleted.

So again, taking a look at it as a diagram we want to now pop an element off of this stack.

So what do we do?

Well we're first going to create a new pointer that's going to point to the same spot as the head.

We're going to move it one position forward by saying trav equals trav next for example(trav = trav next), which would advance the trav pointer one position forward.

Now that we've got a hold on the first element through the pointer called list, and the second element through a pointer called trav, we can safely delete that first element from the stack without losing the rest of the chain because we have a way to refer to the second element forward by way of the pointer called trav.

So now we can free that node. We can free list.

And then all we need to do now is move list to point to the same place that trav does, and we're sort of back where we started before we pushed 12 on in the first place, right.

This is exactly where we were. We had this four element stack. We added a fifth. We pushed a fifth element on, and then we popped that most recently added element back off.


That's really pretty much all there is to stacks. You can implement them as arrays.

You can implement them as linked lists.There are, of course, other ways to implement them as well.

Basically the reason we would use stacks is to maintain data in such a way that the most recently added element is the first thing we're going to want to get back.

The End
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,686评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,668评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,160评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,736评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,847评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,043评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,129评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,872评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,318评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,645评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,777评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,470评论 4 333
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,126评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,861评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,095评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,589评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,687评论 2 351

推荐阅读更多精彩内容

  • **2014真题Directions:Read the following text. Choose the be...
    又是夜半惊坐起阅读 9,442评论 0 23
  • 心直口快小宁宁, 漆水河畔开发屋。 满腔热情待叟童, 染烫吹剪样样通。 价格适宜技艺精, 客坐满堂人赞称。 忙忙碌...
    许永杰阅读 261评论 0 0
  • 搬家的事忙的好点了,这周以来又开始每天晚上九点把自己赶进书房。这种不乐意让自己太舒服的性格我还是挺欣赏的,不过节奏...
    写字的蜗牛阅读 265评论 0 1
  • 几天前,看到新闻说, 一个在农村的脑瘫诗人与丈夫离婚.当时的第一反映是,呵呵,又一个哗众取宠的人,就那么想红啊,脑...
    0ed5831d916d阅读 604评论 0 0