【面试攻略】C++面试-栈


面试攻略栈

什么是栈
先进后出,后进先出,这就是典型的栈结构。
从栈的操作特性来看,是一种操作受限的线性表,只允许在端插入和删除数据。
为什么需要栈
任何数据结构都是对特定应用场景的抽象,数组和链表虽然使用起来更加灵活,但是暴露了几乎所有的操作,难免会引发错误。
当某个数据集合只涉及在某端插入和删除数据,且满足先进者后出,后进者先出的操作特性时,我们应该首选栈这种数据结构。

栈和队列数据结构的区别
栈是限定只能在表的一端进行插入和删除操作的线性表。队列是限定只能在表的一端进行插入和在另一端进行删除操作的线性表。

栈的应用
1.栈在函数调用中的应用:操作系统给每个线程分配了一块独立的内存空间,这块内存空间被组织成栈这种结构,用来存储函数调用时的临时变量。每进入一个函数,就会将其中的临时变量作为栈帧入栈,当被调用的函数执行完成,返回之后,讲这个函数对应的栈帧出栈。
2.栈在表达式求值(比如:34+13*9+44-12/13)中的应用:利用两个栈,其中一个用来保存操作,另一个用来保存运算符。我们从左向右遍历表达式,当遇到数字我们就压入操作数栈;当遇到运算符,就与运算符栈的栈顶元素进行比较,若比运算符栈顶元素的优先级高,就当将当前运算符压入栈;若比运算符栈顶元素优先级低或者相同,从运算符中取出栈顶运算符,从操作数栈顶取出2个操作数,然后进行计算,把计算完的结果压入操作数栈,继续比较。
3.栈在括号匹配(比如{[]{}})中的应用:用栈保存为匹配的左括号,从左到右依次扫描字符串,当扫描到左括号时,则将其压入栈中;当扫描到右括号时,从栈顶取出一个左括号,如果能匹配上,则继续扫描剩下的字符串。如果扫描过程中,遇到不能配对的右括号,或者栈中没有数据,则说明为非法格式。当所有的括号都扫描完成之后,如果栈为空,就说明字符串合法;反之字符串非法。
4.实现浏览器的前进和后退功能:我们使用两个栈X和Y,我们把首次浏览的页面依次压入X,当点击后退按钮时,再次依次从栈X中出栈,并将出栈的页面依次放入Y栈。当栈X中没有数据时,说明没有页面可以浏览后退浏览了。当Y栈没有数据,那就说明没有页面可以点击前进浏览了。

原文 https://blog.csdn.net/ruzewei/article/details/108547402


栈为什么会溢出

在一个算法中,如果递归函数调用过多次数,那么就会导致堆栈溢出。
原因就是,操作系统会自动给每个进程分配一个最大栈空间2M,如果超过了这个上限,就会导致递归函数执行终止,所以就会报错。递归就像你一直在往一个空间里放东西,也就是一直在入栈,调用一次会把内存地址进行一次入栈,直到调用结束,才会将地址出栈。想一想,是不是如果调用次数过多,入栈的内存地址大于2M,就会引起程序报错呢?
同样的,如果你创建一个数组过大,会引起堆溢出,操作系统给每个进程分配的最大堆空间是4G,如果过大会导致堆溢出。
※(调用一个方法,在这个方法执行前都会将之前的内存地址(也就是调用点)入栈,等被调用的方法执行完将地址出栈,程序根据这个数据返回调用点)
解决递归函数堆栈溢出的方法就是尾递归:
尾递归就是在函数返回return时调用函数本身,而不使用其他表达式。这样执行的时候尾递归函数只会占用一个栈帧,就不会引起栈溢出。

下面是2个例子:

def fact(n):
    if n==1:
        return 1
    return n * fact(n - 1)
def fact_iter(num, product):
    if num == 1:
        return product
    return fact_iter(num - 1, num * product)
第一个就是递归函数;第二个就是优化后的尾递归。

原文 https://blog.csdn.net/qq_41838901/article/details/89311268


堆栈区别
1.栈系统分配,堆人为申请
2.栈分配的空间较小,堆分配的空间较大
3.栈分配速度比堆快
4.栈系统分配,堆人为申请
5.栈是连续的空间,堆是不连续的空间

堆和栈的区别可以用如下的比喻来看出:
使用栈就象我们去饭馆里吃饭,只管点菜(发出申请)、付钱、和吃(使用),吃饱了就走,不必理会切菜、洗菜等准备工作和洗碗、刷锅等扫尾工作,他的好处是快捷,但是自由度小。
使用堆就象是自己动手做喜欢吃的菜肴,比较麻烦,但是比较符合自己的口味,而且自由度大。


 

原文地址:https://www.cnblogs.com/byfei/p/14104083.html