数据结构自学笔记二、栈
(温馨提示:本人是一名正在自学数据结构的小白,如果你是想要得到某个疑问的答案,请另觅高就,不要别我浅薄的学识耽误了)
栈的定义
刚刚我们学了线性表,其实栈在也可以算作是线性表,甚至在进行某些操作的时候要比之前讲的一般的线性表更为简单。
栈是只能在一端进行操作的线性表。
小学的时候很喜欢玩《穿越火线》,当时玩终结者模式,一堆人钻在一条狭窄的胡同里,因为幽灵只能从一端进攻,所以只要火力充足,基本都能苟到最后。
但有一个问题,就是胡同太窄了,大家只能排成一列,所以如果前面的人不出去,后面的人也出不去。栈就是像这样的一种数据结构,它是一种线性表,但是只能从线性表的一段进行操作,如添加元素(压入栈push)和删除元素(弹出栈pop)等。
栈中元素的特性是先进后出,后进先出。我们把栈可以进行操作的一端称为栈顶,另一端称为栈底。用户只能对栈顶的元素进行操作。
栈的作用
可能初学者会和我一样想:栈到底有什么用?它是线性表,却比线性表多了很多约束条件,反而不能自由的处理它的任意一个元素,这不是变麻烦了吗?
且慢,我们来看看栈有什么用吧。
我相信很多人在学C语言的函数模块时,一定做过这样一个题:输出斐波那契数列的前多少多少个。
比如:请输出斐波那契数列的前10个数。
而且这个题一定在学循环的时候出现一次,在学函数的时候又会出现一次。
如果我们用循环来写,可以这样:
int a[10];//由于只输出十个,我们可以声明数组来存放
a[0]=a[1]=1;
cout<<a[0]<<endl<<a[1];//输出前两个
for(int i=2;i<10;i++)//循环八次
{
a[i]=a[i-1]+a[i-2];
cout<<a[i];//输出数字
}
当然,这并不是一个非常睿智的写法,因为它需要开数组。用两个变量进行循环同样可以达到目的,聪明的你一定能够想到,此处不赘述。
但是,在我们学函数模块时,老师会鼓励我们设计一个递归函数,请看代码:
int Fibonacci(int n)//一个整型函数,传入一个int型n,返回斐波那契数列的第n个数
{
if(n==1||n==2)return 1;
else return Fibonacci(n-1)+Fibonacci(n-2);
}
这个代码就非常的简洁而明智。因为C语言是允许函数调用其他函数的(包括自身),这样递归调用函数实现了代码的简化。
这和栈有什么关系吗?
别急,再讲一个故事。还是初学C语言的时候,做了这么一个题:输出斐波那契数列的第10000个数。当时我自信满满的用了刚学的递归,写了一个函数,结果一运行,编译器就报错了。
我