开篇:上次我们学习了基本的数组结构。

今天,我们来学习另一个线性的数据结构,栈。

 

栈这种数据结构,无时无刻不在我们的身边。是种极其重要的数据结构。

所以,什么是栈呢?(不要废话了,快说)

先来看我们生活中,比如我们经常操作的word文档。

我们比如写入四个字, (天气真好)。

我们不想要了这句话,Ctrl+Z 回撤掉我们所打的。你会很自然发现,消失的顺序会是,好->真->气->天。

 

别急。 我们再来个例子。

比如那我们的函数调用,

计算机需要有个系统栈来记录我们的函数调用。

public void A()
{
        B();
}

public void B()
{
        C();
}

public void C()
{
        //....
}

A为我们的主函数,当A调用B的时候,进入B函数时,会在A函数中断的位置把函数地址信息压入到系统栈里。

此时B函数又在用掉C函数,此时又会在B函数中断的位置把函数地址信息压入到系统栈里。

此时C执行完后,该怎么办呢。此时系统栈里会取出栈顶元素为返回的地址,为B,程序便正确的回到B处。

同样的。B执行完,系统栈又会取出栈顶元素为返回的地址,为A,程序便正确的回到A处。

此时我们正完成了我们的函数调用。

如我们的图所示:

所以。栈(stack)又名堆栈,它是一种运算受限的线性表。其限制是仅允许在表的一端进行插入和删除运算。

插入和删除都在栈顶这一端操作。

包括我们的经常使用编程的Ide,会自动检查括号的匹配等等。都是基于栈的结构。

 

现在,我们基于我们上次的线性数组。来实现我们的自定义栈结构。

我们让我们的结构实现我们的泛型IStack接口来实现。

分别有pop出栈,push入栈。判断是否为空和清空操作等。

/// <summary>
    ////// </summary>
    /// <typeparam name="T"></typeparam>
    public interface IStack<T>
    {
        void Push(T value);
        T Pop();
        T Peek();
        bool IsEmpty();
        void Clear();
    }

    public class Stack<T> : IStack<T>
    {
        private Array<T> Data;
        public Stack(int capacity=20)
        {
            this.Data = new Array<T>(capacity);
        }

        public void Clear()
        {
            this.Data.SetEmpty();
        }

        public bool IsEmpty()
        {
            return this.Data.GetSize() == 0;
        }

        public T Peek()
        {
            return this.Data.Search(this.Data.GetSize());
        }

        public T Pop()
        {
            return this.Data.Delete(this.Data.GetSize());
        }

        public void Push(T value)
        {
            this.Data.Add(value);
        }
    }

 

由此可见。这是一个重要的数据结构。

届时,我们来看看leetcode上的一道典型的链表题目。20题

题目是这样的。

给定一个只包括 ‘(‘,’)’,'{‘,’}’,'[‘,’]’ 的字符串,判断字符串是否有效。

有效字符串需满足:

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

先给出代码(C#)。

public class Solution {
    public bool IsValid(string str) {
        var stack = new Stack();
            for (int i = 0; i < str.Length; i++)
            {
                if (str[i] == '[' || str[i] == '{' || str[i] == '(')
                    stack.Push(str[i]);
                else if(str[i] == ']' || str[i] == '}' || str[i] == ')')
                {
                    if (stack.Count == 0)
                        return false;
                    var top = (char)stack.Pop();
                    if (str[i] == ')' && top != '(')
                        return false;
                    if (str[i] == ']' && top != '[')
                        return false;
                    if (str[i] == '}' && top != '{')
                        return false;
                }
            }
            return stack.Count==0;
    }
}
使用的Stack类为我们的C#本身为我们提供的栈结构。
本题目是 [,(,,{ 三种括号的匹配。
我们判断。如果是这三种,我们就相应的入栈。当遇到他们所匹配的结尾括号时,],),}时候。
便相应的出栈。如果不是他们对应的标签。便是不符合要求的。当一一遍历出栈后。
如果栈为空时。便说明便是符合要求的。

今天我们的栈就到这里啦,下一次,我们来实现另一种线性结构,队列。

 

版权声明:本文为GuanZx原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/GuanZx/p/11048388.html