《数据结构与算法Python语言描述》学习笔记(3)--栈

《数据结构与算法Python语言描述》学习笔记(3)–栈和队列

栈和队列都是保存数据元素的容器,主要用于在计算过程中保存临时数据。
在计算机中,工作中产生的中间数据暂时不用换或者用不完,就有必要把当时不能立刻用掉的数据存起来。设置变量作为临时存储,这种存储机制称为缓冲存储或者缓存,栈和队列就是使用最多的缓冲存储结构。

应用环境:
计算过程分为一些顺序进行的步骤;
计算中执行的某些步骤会不断产生一些后面可能需要的中间数据;
产生的数据中有些不能立即使用,但又需要在将来使用;
需要保存的数据的项数实现不能确定。

栈:先进后出
栈的线性表实现
栈可以看作是在一端进行插入和删除的线性表;
执行插入和删除的一端称为栈顶,另一端称为栈底。
对于顺序表:后端插入和删除 应作为栈顶;
对于链接表:前端插入和删除 应作为栈顶。

使用list实现栈

1)建立空栈对应于创建一个空表[],判空栈对应于检查是否为空表;
2)由于list采用动态顺序表计数(分离式实现),作为栈的表不会满;
3)压入元素操作应在表的尾端进行:list.append(x)
4)访问栈顶元素因该用list[-1]
5)弹出操作应该在表的尾端进行list.pop()

# 栈的顺序表实现


class StackUnderflow(ValueError): # 栈下溢(空栈访问)
    pass


class SStsck(): # 基于顺序表技术实现的栈类
    def __init__(self): # 用list对象,_elems存储栈中元素
        self._elems = []

    def is_empty(self):
        return self._elems == []

    def top(self):
        if not self._elems:
            raise StackUnderflow("in SStack.top()")
        return self._elems[-1]

    def push(self,elem):
        self._elems.append(elem)

    def pop(self):
        if not self._elems:
            raise StackUnderflow
        return self._elems.pop()


ss1 = SStsck()
for i in range(0,5):
    ss1.push(i)

while not ss1.is_empty():
    print(ss1.pop())

运行结果:

4
3
2
1
0
栈的链表实现
# 栈的链表实现
# 链表
class LNode:
    """"定义一个链表的结点类"""
    def __init__(self,elem,next_ = None):
        self.elem = elem
        self.next = next_


class LStack(): # 基于链表技术实现的栈,用lNode作为节点
    def __init__(self):
        self._top = None

    def is_empty(self):
        return self._top is None

    def top(self):
        if self._top is None:
            raise  StackUnderflow("in LStack")
        return self._top.elem

    def push(self,elem):
        self._top = LNode(elem,self._top)

    def pop(self):
        if self._top is None:
            raise  StackUnderflow(" in LStack pop()")
        p = self._top
        self._top = p.next
        return p.elem

if __name__ == '__main__':
    st1 = LStack()
    for i in range(0,5):
        st1.push(i)

    print(st1.top())
    st1.pop()
    print((st1.top()))
    st1.push(9)
    while not st1.is_empty():
        print(st1.pop())

运行结果:

4
3
9
3
2
1
0
栈的简单应用
括号匹配问题

考虑圆括号,方括号和花括号
每种括号都包含一个开括号和一个闭括号,相互对应,括号括起的片段可能嵌套,各种括号应该正确地嵌套并分别配对。

括号配对的原则:
在扫描正文的过程中,遇到的比括号应该与在此前最近遇到且尚未获得匹配的开阔号配对。如果最近的未匹配开括号与当前比括号不配对,或者找不到这样的开阔号,就是匹配失败,说明这段正文里的括号不配对。

由于存在多种不同的括号对,每种括号都可能存在任意多次,而且还坑你嵌套,未来检查是否匹配,扫描中必须保存遇到的开括号,由于写程序时无法预知要处理的正文里会有多少数据需要保存,因此不能采用固定数目的变量保存,必须用缓存结构。

由于括号的出现可能出现嵌套,需要逐对进行皮牌,后入者先匹配,符合LIFO原则,所以用栈实现。
进而,一个开阔号已经配对,就应该删除这个括号,为随后的匹配做好准备。
所以处理这个问题的思路为:
1)顺序扫描被检查正文了的一个个字符;
2)跳过无关字符(所有非括号字符)
3)遇到开括号时将其压入栈;
4)遇到闭括号时弹出当时的栈顶元素与之匹配;
5)如果匹配成功则继续,发现不匹配时检查已失败结束。

# 栈的应用:括号匹配


def check_parens(text):
    """括号配对检查函数,text是被检查的正文串"""
    parens = "()[]{}"  # 所有括号字符
    open_parens = "([{"  # 开括号字符
    opposite = {")": "(", "]": "[", "}": "{"}  # 表示配对关系的字典

    def parentheses(text):
        """括号生成器,每次调用返回text里下一括号及其位置"""
        i,text_len = 0,len(text)
        while True:
            while i < text_len and text[i] not in parens:
                i += 1
            if i >= text_len:
                return
            yield text[i],i
            i += 1

    st = SStack()
    for pr, i in parentheses(text):      # 对text里各括号和位置迭代
        if pr in open_parens:           # 开括号,压进栈并继续
            st.push(pr)
        elif st.pop() != opposite[pr]:      # 不匹配就是失败,退出
            print("Unmatching is found at",i,"for",pr)
            return False
        # else:这是一次括号配对成功,什么也不做,继续

    print("All parentheses are correctly matched.")
    return True

text = "90[]{}[]ioinyui()pp"
check_parens(text)

运行结果
All parentheses are correctly matched.

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值