简述
这一节比较重要,讲述树这种数据结构以及一些常用的知识和应用。树这种结构,比 线性结构要复杂和灵活一点,所以可以实现更多的逻辑难题,相比于图的话用的又更多一点,所以需要多多练习。
树常见的几种例子:
1、生物物种分类体系;
2、计算机里面的文件系统;
3、HTML文档里面的嵌套标记
4、域名体系;
相关术语:
1、节点Node:里面保存着相应的数据值;
2、边Edge:每条边连接两个节点。具有出入方向,每个节点(除了根节点),有一个入边;
3、根root:没有入边的节点,在上面;
4、路径Path:由边依次连接在一起的一个列表
5、子节点:入边来自于同一节点的,称为这个节点的子节点;
6、父节点:有一个出边是所有连接节点的,是父节点;
7、兄弟节点:具有同一个父节点的,之间称为兄弟节点;
8、子树:一个节点和它的所有子孙节点,以及相关边的集合;
9、叶节点:没有子节点的节点称为叶节点;
10、层级:从根节点到达一个节点的路径包含的边的数量。如根节点是0层,根的子节点是1层;
11、高度:树中所有节点的最大层级称为树的高度;
二叉树的链表实现
一般的,习惯运用之前的链表去表示我们的树,为了快速理解和实现,我们主要研究二叉树:
class BinaryTree:
def __init__(self,rootObj):
self.key=rootObj
self.left=None
self.right=None
def insertLeft(self,newObj):
if self.left==None:
self.left=BinaryTree(newObj)
else:
t=BinaryTree(newObj)
t.left=self.left
self.left=t
def insertRight(self,newObj):
if self.right==None:
self.right=BinaryTree(newObj)
else:
t=BinaryTree(newObj)
t.right=self.right
self.right=t
首先实现了几个基本的点:
1、每个节点其实有三个内容,自身的值key,到左节点的链接left,和到右节点的链接right;
2、主要功能是–添加左节点和添加右节点:
3、按照正常思维,将新节点添加到叶子节点,就很复杂,需要确定很多参数;这里选择的是把新节点放到根的的下面节点,类似于一个插入的概念。
(在以前的链表章节,添加一个新节点,其实也是用的这种思维)
下面实现了一些二叉树的其他方法
def getRight(self):
return self.right
def getLeft(self):
return self.left
def setRootObj(self,obj):
self.key=obj
def getRootObj(self):
return self.key
主要就是获取左右子树,根节点数值,以及将根节点数值进行修改。
树的应用:表达式解析
表达式可以解析成树的结构,叶子节点放操作数,内部的节点则放相应的操作符。
将全括号表达式转换成相应的树结构:
1、碰到**(** 则添加左子节点,当前节点下降到该子节点;
2、碰到 + - * / 等操作符,则当前节点设置为操作符,新建右子节点,并下降到该右子节点;
3、碰到的是操作数,则当前节点设置为操作数,再上升到父节点;
4、碰到 ) 则上升到父节点;
def buildParseTree(fpexp):
fplist = fpexp.split()
pStack = Stack()
eTree =BinaryTree('')
pStack.push(eTree)
currentTree=eTree
for i in fplist:
if i=='(':
currentTree.insertLeft('')
pStack.push(currentTree)
currentTree=currentTree.getLeft()
elif i not in ['+','-','*','/',')']
currentTree.setRootObj(int(i))
parent=pStack.pop()
currentTree=parent
elif i in ['+','-','*','/']:
currentTree.setRootObj(i)
currentTree.insertRight('')
pStack.push(currentTree)
currentTree=currentTree.getRight()
elif i == ')':
currentTree=pStack.pop()
else:
raise ValueError
return eTree
树的遍历
对一个数据机构中的所有数据进行访问,叫做遍历。线性结构中的访问太简单了,而对于树,图等数据结构则较为复杂,所以值得研究。
就二叉树来说,分为前序遍历,中序遍历和后序遍历。使用递归思想,完成遍历非常的简洁明了。
def preoder(tree):
if tree:
print(tree.getRootObj)
preoder(tree.getLeft())
preoder(tree.getRight())
def postorder(tree):
if tree:
postorder(tree.getLeft)
postorder(tree.getRight)
print(tree.getRootObj)
def inorder(tree):
if tree:
inorder(tree.getLeft)
print(tree.getRootObj)
inorder(tree.getRight)