前面我们学了线性表的两类:
1.顺序表
2.链表
他们都有各自的特点和好处具体见如下:
那么我们下面要学习一种非线性的数据结构----树
树是图的一种特殊类型,且有着属于自己的独特用途
什么是树?
一种 非线性的数据结构,在操作系统,图形学(场景树),数据库系统(索引树),计算机网络(域名树)均有用处.模仿自然界中的树一样,数据结构树也分为:根,枝,叶等三个部分
例子:
比如说生物的物种分类,可以用一种树的形态来表示.而在这个树中,他是一种层次化的分类体系:
分类树的三个特征:
一:
越接近顶层的越普遍
越接近底层的越普通
界门纲目科属种
二:
一个节点的子节点与另一个节点的子节点之间是没有任何关系的(隔离,独立)
三:
每一个叶节点都具有唯一性
再比如说文件的检索系统,也是一种树结构查找的平均是O(logn)
学习爬虫的时候的HTML的文档也是一种树结构
通过这些例子可以看到现实生活中有很多树的例子,所以树是一种很重要的数据结构类型.
树的相关术语
节点Node组成树的基本部分,节点可以用来保存数据项,数据项根据不同的性质而变.
边Edge边是组成树的另一基本部分,每条边恰好连接两个节点,表示节点之间具有关联,边具有出入两个方向.每个节点(除根节点)恰有一条有来自另一节点的入边.每一个节点可以有多条连接其他节点的出边.
根Root树中唯一一个没有入边的节点
路径Path由边依次连接在一起的节点的有序列表
**子节点(Children)**入边均来自同一节点的若干节点,称为这个节点的子节点.
父节点Parent一个节点是其所有出边所连接节点的父节点
子树Subtree一个节点和其所有子节点,以及相关边的集合
二叉树 每个节点最多有两个子节点
树的列表嵌套实现
这个不是重点
树的链表实现
这是树的一种主要实现方式
![在这里插入图片描述](https://img-blog.csdnimg.cn/20210627214133162.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzUzMTgzNjA4,size_16,color_FFFFFF,t_70)
一个节点中可以有需保存的数据项,和指向left,right的指针
代码实现
class Tree():
def __init__(self,item,left=None,right=None):
self.item=item
self.left=left
self.right=right
树的应用:表达式的解析
![在这里插入图片描述](https://img-blog.csdnimg.cn/20210627215345742.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzUzMTgzNjA4,size_16,color_FFFFFF,t_70)
这样的话,每一个表达式的子树都是一个子表达式,这样的话自底向上是可以进行求值的.
全括号表达式具体有一下几个值,"()",操作符±*/,数字
左括号是表达式的开始,右括号是表达式的结束
创建树的过程
创建空树,当前节点为根节点
读入"(",创建左子节点,当前节点下降
读入数字,当前节点数据项设为数字,上升到父节点.
读入操作符,当前节点设置为此操作符,创建右子节点,当前节点下降
读入")",上升到父节点
#需要注意的是上升到父节点这个行为,没有对应的指针,所以可以用栈来记录自己走过的路
def biaodashijiexi(bds):
#首先是转化成列表
bds_list=list(''.join(bds))
#树的根节点
head=Tree('')
#创建一个树,设置当前节点
current_node=head
#建栈
stack=[current_node]
#开始对字符串进行循环
for i in bds_list:
if i=='(':
#当前节点创建左子节点,并下降
t=Tree('')
current_node.left=t
#入栈
stack.append(current_node)
current_node=t
elif i in '+-*/':
#当前节点数据项设为此操作符,创建右子节点,当前节点下降
current_node.item=i
t=Tree('')
current_node.right=t
#入栈
stack.append(current_node)
current_node=t
elif i==')':
#什么都不干上升到父节点
current_node=stack.pop()
else:
#默认输入是正确的所以此时只能是为数字的情况
current_node.item=i
current_node=stack.pop()
return head
bds='((1+2)*(4+3))'
head=biaodashijiexi(bds)
def fun(head):
if head:
print(head.item)
fun(head.left)
fun(head.right)
fun(head)
代码实现就按照上述思路来就行了,主要是创建栈之后就先需要对当前节点进行一个保存,为了让在循环结束时左括号所产生的入栈可以抵消右括号所产生的出栈