数据结构与算法(四):栈

数据结构与算法(四):栈

最近开始学习王争老师的《数据结构与算法之美》,通过总结再加上自己的思考的形式记录这门课程,文章主要作为学习历程的记录。

栈可以看作是一种“操作受限”的线性表,当某个数据只涉及在一端插入和删除数据,并满足后进先出,先进后出的特性,应首选“栈”这种数据结构。如下图:

数据结构与算法(四):栈_第1张图片

用数组实现的栈,叫做顺序栈,用链表实现的栈,叫做链式栈。不管是顺序栈还是链式栈,存储数据只需要一个大小为n的数组。在入栈和出栈过程中,只需要一两个临时变量存储空间,因此空间复杂度为O(1)。但这不意味空间复杂度为O(n)。因为这n个空间是必须的,无法省掉。因此说空间复杂度的时间,除了原本的数据存储空间,算法运行还需要额外的存储空间。

支持动态扩容的顺序栈

数据结构与算法(四):栈_第2张图片
动态过程如上,当数组空间不够时,我们就重新申请一块更大的内存,将原来的数组中的数据统统拷贝过去。

对于出栈操作来说,我们不会涉及内存的重新申请和数据搬移,所以出栈的时间复杂度仍是O(1).但当空间不够时,就需要重新申请内存和数据搬移,时间复杂度即为O(n)。因此最好情况时间复杂度是O(1),最坏情况时间复杂度是O(n)。平均情况下的时间复杂度可以用摊还分析法。如下图,因此可以得到入栈操作的均摊时间复杂度为O(1)。

数据结构与算法(四):栈_第3张图片

栈在函数调用中的应用

操作系统给每个线程分配了一块独立的内存空间,这块内存被组织成“栈”这种结构,用来存储函数调用时的临时变量。每进入一个函数,就会将临时变量作为一个栈帧入栈。当被调用函数执行完成,返回之后,将这个函数对应的栈帧出栈。


int main() {
   int a = 1; 
   int ret = 0;
   int res = 0;
   ret = add(3, 5);
   res = a + ret;
   printf("%d", res);
   return 0;
}

int add(int x, int y) {
   int sum = 0;
   sum = x + y;
   return sum;
}

函数调用栈情况如下:

数据结构与算法(四):栈_第4张图片

栈在表达式求值中的应用

编译器采用两个栈来实现。其中一个保存操作数的栈,另一个是保存运算符的栈。从左到右遍历表达式,若遇到数字,则进行压栈。当遇到运算符,与运算符栈的栈顶元素进行比较。如果比运算符栈顶元素优先级高,就将当前运算符压入栈。反之,从操作数栈中取2个操作数,从运算符栈中取栈顶运算符。计算后,再把计算结果压入操作数栈,继续比较。以(3+5*8-6为例)

数据结构与算法(四):栈_第5张图片

栈在括号匹配中的应用

除了用栈来实现表达式求值,我们还可以借助栈来检查表达式中的括号是否匹配。以LeetCode上第20题(有效的括号)为例:给定一个只包括 ‘(’,’)’,’{’,’}’,’[’,’]’ 的字符串,判断字符串是否有效。

有效字符串需满足:

左括号必须用相同类型的右括号闭合。
左括号必须以正确的顺序闭合。
注意空字符串可被认为是有效字符串。

以下是自己敲的代码,思路是当字符串长度为0时,返回True,当字符串长度为单数时,返回False,当字符串长度为双数时,遇到’(’,’[’,’{‘时压栈,遇到‘)’,‘]’,‘}’则将’(’,’[’,’{'删除。

class Solution(object):
    def isValid(self, s):
        """
        :type s: str
        :rtype: bool
        """
        l = []
        if len(s)==0:
            return True
        if len(s)%2!=0:
            return False
        for j in range(len(s)):
            c = s[j] 
            if c=='(':
                l.append(c)
            elif c=='[':
                l.append(c)
            elif c=='{':
                l.append(c)
            elif c==')' and ('(' in l):
                if l[-1]=='(':
                    del l[-1]
                else:
                    return False
            elif c==']' and ('[' in l):
                if l[-1]=='[':
                    del l[-1]
                else:
                    return False
            elif c=='}' and ('{' in l):
                if l[-1]=='{':
                    del l[-1]
                else:
                    return False
            else:
                return False
            if j==len(s)-1:
                if len(l)==0:
                    return True
                else:
                    return False

参考资料:王争《数据结构与算法之美》
LeetCode题库

你可能感兴趣的:(数据结构,栈,数据结构与算法)