python数据结构学习笔记(一)

it2025-05-21  12

学习笔记——栈(1)

一、前言

二、栈的数组实现

三、例题

四、习题


一、前言

用自己的话说,栈更像是一个瓶子,有一个口、一个底,遵循着先进后出、后进先出的原则。

第一次接触栈是大一计算机基础课,当时学完,未果,觉得并没有什么用处。

第二次接触就是大三微机原理与接口课,依旧是没什么很大的感觉,感觉和一开始的接触变化不大,不过我当时确实是学懂了汇编语言,虽然现在忘光光的...

真正算是深入的接触就是看机械工业出版社《数据结构与算法——python语言实现》,栈一种数据类型,比如说撤销、返回等用到的其实都是栈的概念,也算是第一次了解了栈的实际作用。

二、栈的数组实现

先设计功能,设计最简单的四种功能:

功能代码实现压入栈push()弹出栈pop()求长度len()

 

我们采用列表的的方式存放栈,这里定义一个栈的类,初始化使其为一个空列表:

class ArrayStack: def __init__(self): """ Initialize the stack. """ self._data = []

压入栈可以通过列表的拼接来实现,在list类中可以使用append()的方式进行拼接,这里注意,函数不需要返回值,这是直接对其局部变量进行修改:

def push(self, val): """ Use to push a element on the top of stack. """ self._data.append(val)

同样的道理,弹出栈:

def pop(self): """ Use to pop the top element of stack. """ if self.is_empty(): raise Empty('Stack is empty!') return self._data.pop()

在这之前,定义一个简单的查询列表是否为空的函数is_empty,既然要检验是否为空,就可以附加的再定义一个求长度的函数,这里用到了运算符重载。运算符重载简言就是对于我们自己写的类,如果想用常用函数或运算符进行直接计算是不可以的,比如说:

sample = ArrayStack() len(sample)

程序就会退出并且报错:

Traceback (most recent call last):

  File "\Python\test.py", line 39, in <module>     len(sample)

TypeError: object of type 'ArrayStack' has no len()

这个时候想要解决,就要用到运算符重载来为他定义属于他独有的操作方式,例如len()的运算符重载为__len__,于是有:

def __len__(self): """ Return length of Stack. """ return len(self._data) def is_empty(self): """ Show if this stack empty or not. """ return len(self._data) == 0

 一个简单的列表栈就实现了。

三、例题

1.括号匹配

一个算术表达式一定包含了多个括号,例如:

小括号:“(”和“)”中括号:“[”和“]”大括号:“{”和“}”

其括号一定要相互前后匹配,例如小括号开一定要对应小括号闭,小括号开后面的中括号开一定要先进行中括号闭才能进行小括号开,但当我们一个算术表达式很长,我们要如何去检验这个是否正确呢,我们可以试想用栈的思维去解决:

观察我们的括号,其实括号是区分括号开(左括号)和括号闭(右括号)两种。当我们有一个栈,在遍历这个算术表达式的时候每读取到左括号时,进行一次压栈操作,将读取的左括号压入栈内;读到右括号时,进行弹出操作,将栈顶的左括号弹出,同时与当前的右括号进行比较(匹配),如果正确,则继续遍历....

具体代码如下:

def is_matched(expr): lefty = '([{' righty = ')]}' S = ArrayStack() for char in expr: if char in lefty: S.push(char) elif char in righty: if S.is_empty() or lefty.index(S.pop()) != righty.index(char): return False return True

写完这段发现竟然有个测试用例是有问题的,即左括号没匹配完的情况,可我明明都在判断的时候进行了空的判断啊。

思考后发现原来是匹配过程没有问题的结束后,剩下的左括号也会默认为正确,只需要在结尾时再次判断其栈S是否匹配完即可:

def is_matched(expr): lefty = '([{' righty = ')]}' S = ArrayStack() for char in expr: if char in lefty: S.push(char) elif char in righty: if S.is_empty() or lefty.index(S.pop()) != righty.index(char): return False return S.is_empty()

(我原本用了if,后来看书,书上是这样写的,写的真妙...) 

2.HTML语言的正确错误检验:

同样的,HTML语言也有括号的检验过程,虽然HTML语言对于括号的判断非常简单(只有一种括号对,即<>),但想要更好的去判断就必须要判断括号内的标记。

同样的,在读取的过程中,我们可以用上面相同的思路。设一个中间变量temp,其类型是字符串,当我们遍历这个文章,读取到左括号<时,我们将后面的字符读进temp,当读到右括号>时结束读取,同时将temp压栈。一样的道理,当读到以斜杠/开头的标记时,读取到temp中,同时弹出、判断...往复直至结束。

思路是一样的,代码内容也相似,这里就不贴了。

四、习题

按照书后的例题,给自己加加码,挑选了几道感兴趣的内容:

R-6.3 实现一个函数transfer(S,T)将栈S中所有元素倒置放入T。

C-6.16 修改栈的实现方法,加入一个参数maxlen,使其大小限制在maxlen中,若超出,则抛出一个异常。

C-6.18 实现R-6.3功能使其在原栈上更改输出。

 

 

最新回复(0)