树在计算机科学的许多领域中使用,包括操作系统,图形,数据库系统和计算机网络。树数据结构与他们的植物表亲有许多共同之处。树数据结构具有根,分支和叶。自然界中的树和计算机科学中的树之间的区别在于树数据结构的根在顶部,其叶在底部。

1 树的相关定义

节点:树的基本部分。它可以有一个名称,我们称之为“键”。节点也可以有附加信息。我们将这个附加信息称为“有效载荷”。虽然有效载荷信息不是许多树算法的核心,但在利用树的应用中通常是关键的。

:树的另一个基本部分。边连接两个节点以显示它们之间存在关系。每个节点(除根之外)都恰好从另一个节点的传入连接。每个节点可以具有多个输出边。

:树的根是树中唯一没有传入边的节点。

路径:路径是由边连接节点的有序列表。
子节点:具有来自相同传入边的节点 c 的集合称为该节点的子节点。
父节点:具有和它相同传入边的所连接的节点称为父节点。
兄弟节点:树中作为同一父节点的子节点的节点被称为兄弟节点。
子树:由父节点和该父节点的所有后代组成的一组节点和边。
叶节点:叶节点是没有子节点的节点。
高度:树的高度等于树中任何节点的最大层数。

定义一:树由一组节点和一组连接节点的边组成。树具有以下属性:

  • 树的一个节点被指定为根节点。
  • 除了根节点之外,每个节点 n 通过一个其他节点 p 的边连接,其中 p 是 n 的父节点。
  • 从根路径遍历到每个节点路径唯一。
  • 如果树中的每个节点最多有两个子节点,我们说该树是一个二叉树。下图展示了合适定义一的。

定义二:树是空的,或者由一个根节点和零个或多个子树组成,每个子树也是一棵树。每个子树的根节点通过边连接到父树的根节点。 下图 说明了树的这种递归定义。使用树的递归定义,我们知道 下图中的树至少有四个节点,因为表示一个子树的每个三角形必须有一个根节点。 它可能有比这更多的节点,但我们不知道,除非我们更深入树。



2 列表表示树结构

2.1 结构示意图

列表为我们提供了一个简单的递归数据结构,我们可以直接查看和检查。在列表树的列表中,我们将根节点的值存储为列表的第一个元素。列表的第二个元素本身将是一个表示左子树的列表。列表的第三个元素将是表示右子树的另一个列表。下图展示了一个简单的树和相应的列表实现。



myTree = ['a',   #root
['b', #left subtree
['d', [], []],
['e', [], []] ],
['c', #right subtree
['f', [], []],
[] ]
]

树的根是 myTree[0],根的左子树是 myTree[1],右子树是 myTree[2]

2.2 数的函数表达

下面我们用列表作为树的函数来形式化树数据结构的定义(并非定义一个二叉树类),帮助我们操纵一个标准列表。

def BinaryTree(r):
return [r, [], []]

BinaryTree 函数简单地构造一个具有根节点和两个子列表为空的列表。

2.3 插入子节点

要将左子树添加到树的根,我们需要在根列表的第二个位置插入一个新的列表。我们必须小心。如果列表已经在第二个位置有东西,我们需要跟踪它,并沿着树向下把它作为我们添加的列表的左子节点。下面代码展示了插图左子节点和右子节点的 python 代码。

def insertLeft(root,newBranch):
t = root.pop(1)
if len(t) > 1:
root.insert(1,[newBranch,t,[]])
else:
root.insert(1,[newBranch, [], []])
return root
def insertRight(root,newBranch):
t = root.pop(2)
if len(t) > 1:
root.insert(2,[newBranch,[],t])
else:
root.insert(2,[newBranch,[],[]])
return root

要插入一个左子节点,我们首先获得与当前左子节点对应的(可能为空的)列表。然后我们添加新的左子树,添加旧的左子数作为新子节点的左子节点。这允许我们在任何位置将新节点拼接到树中。

下面编写一些访问函数来获取和设置根节点的值,以及获取左或右子树,完成这组树形函数。

def getRootVal(root):
return root[0] def setRootVal(root,newVal):
root[0] = newVal def getLeftChild(root):
return root[1] def getRightChild(root):
return root[2]

3 节点表示

3.1 结构示意图

示意图第二种表示树的方法使用节点和引用。在这种情况下,我们将定义一个具有根值属性的类,以及左和右子树。 它的结构类似于下图:

3.2 构造类

这个表示重要的事情是 left和 right 的属性将成为对 BinaryTree 类的其他实例的引用。 例如,当我们在树中插入一个新的左子节点时,我们用 python 创建另一个 BinaryTree 实例如下,并在根节点中修改self.leftChild 来引用新树节点。

class BinaryTree:
def __init__(self,rootObj):
self.key = rootObj
self.leftChild = None
self.rightChild = None

构造函数希望获取某种对象存储在根中。 就像你可以在列表中存储任何你喜欢的对象一样,树的根对象可以是对任何对象的引用。 对于我们的先前示例,我们将存储节点的名称作为根值。使用节点和引用来表示 Figure 2 中的树,我们将创建 BinaryTree 类的六个实例。

3.2.1 添加节点

要向树中添加一个左子树,我们将创建一个新的二叉树对象,并设置根的左边属性来引用这个新对象。 代码如下:

def insertLeft(self,newNode):
if self.leftChild == None:
self.leftChild = BinaryTree(newNode)
else:
t = BinaryTree(newNode)
t.leftChild = self.leftChild
self.leftChild = t

我们必须考虑两种插入情况。 第一种情况的特征没有现有左孩子的节点。当没有左子代时,只需向树中添加一个节点。 第二种情况的特征在于具有现有左子代的节点。在第二种情况下,我们插入一个节点并将现有的子节点放到树中的下一个层。第二种情况由 Listing 5 第 4 行的 else 语句处理。同理,在根和现有的右子代之间插入节点。

def insertRight(self,newNode):
if self.rightChild == None:
self.rightChild = BinaryTree(newNode)
else:
t = BinaryTree(newNode)
t.rightChild = self.rightChild
self.rightChild = t

3.2.2 获取左右子代和根植

def getRightChild(self):
return self.rightChild def getLeftChild(self):
return self.leftChild def setRootVal(self,obj):
self.key = obj def getRootVal(self):
return self.key

3 完整的二叉树结构

使用节点 a 作为根的简单树,并将节点 b 和 c 添加为子节点。下面代码创建树并查看存储在 key,left 和 right 中的一些值。

class BinaryTree:
def __init__(self,rootObj):
self.key = rootObj
self.leftChild = None
self.rightChild = None def insertLeft(self,newNode):
if self.leftChild == None:
self.leftChild = BinaryTree(newNode)
else:
t = BinaryTree(newNode)
t.leftChild = self.leftChild
self.leftChild = t def insertRight(self,newNode):
if self.rightChild == None:
self.rightChild = BinaryTree(newNode)
else:
t = BinaryTree(newNode)
t.rightChild = self.rightChild
self.rightChild = t def getRightChild(self):
return self.rightChild def getLeftChild(self):
return self.leftChild def setRootVal(self,obj):
self.key = obj def getRootVal(self):
return self.key r = BinaryTree('a')
print(r.getRootVal())
print(r.getLeftChild())
r.insertLeft('b')
print(r.getLeftChild())
print(r.getLeftChild().getRootVal())
r.insertRight('c')
print(r.getRightChild())
print(r.getRightChild().getRootVal())
r.getRightChild().setRootVal('hello')
print(r.getRightChild().getRootVal())

参考资料:《problem-solving-with-algorithms-and-data-structure-using-python》 
http://www.pythonworks.org/pythonds

python实现树结构的更多相关文章

  1. python 实现树结构

    简述: 研究  MCTS 过程中, 需要用到树结构.  baidu  google 了一番, 找不到自己能满足自己的库或代码参考,只好再造个轮子出来 我造的树用来下五子棋 和 围棋用的,   有其它不 ...

  2. python 实现树结构的打印

    class TreeNode: def __init__(self,value): self.children = [] self.value = value def add_child(self,* ...

  3. 一行python代码实现树结构

    树结构是一种抽象数据类型,在计算机科学领域有着非常广泛的应用.一颗树可以简单的表示为根, 左子树, 右子树. 而左子树和右子树又可以有自己的子树.这似乎是一种比较复杂的数据结构,那么真的能像我们在标题 ...

  4. 用python脚本通过excel生成文件夹树结构

    大概这样写标题是对的吧... 目标: 通过excel目录结构文档生成文件夹树结构. 也就是: 通过下面的excel

  5. Python 文件复制&按目录树结构拷贝&批量删除目录及其子目录下的文件

    文件复制&按目录树结构拷贝&批量删除目录及其子目录下的文件 by:授客 QQ:1033553122 测试环境: Python版本:Python 3.3.2 Win7 64 代码实践 # ...

  6. python 实现服务树结构化

    1.  所有服务树数据 tree_list = [{'id': 1, 'pid': 0, 'name': '1211', 'path': '1211', 'leaf': 0, 'type': 0}, ...

  7. 【Machine Learning】决策树案例:基于python的商品购买能力预测系统

    决策树在商品购买能力预测案例中的算法实现 作者:白宁超 2016年12月24日22:05:42 摘要:随着机器学习和深度学习的热潮,各种图书层出不穷.然而多数是基础理论知识介绍,缺乏实现的深入理解.本 ...

  8. Python多线程爬虫爬取电影天堂资源

    最近花些时间学习了一下Python,并写了一个多线程的爬虫程序来获取电影天堂上资源的迅雷下载地址,代码已经上传到GitHub上了,需要的同学可以自行下载.刚开始学习python希望可以获得宝贵的意见. ...

  9. PYTHON解析XML的多种方式效率对比实测

    在最初学习PYTHON的时候,只知道有DOM和SAX两种解析方法,但是其效率都不够理想,由于需要处理的文件数量太大,这两种方式耗时太高无法接受. 在网络搜索后发现,目前应用比较广泛,且效率相对较高的E ...

随机推荐

  1. 什么是API测试

    什么是API API是Application Programming Interface的简写. 实现了两个或多个独立系统或模块间的通信和数据交换能力. 什么是API测试 图片.png API测试是不 ...

  2. mono安装

    linux上的DotNET,安装mono 当前,在Linux系统上架设ASP.NET网站.建设WEB应用工程项目已经在国内流行起来,而“Mono+Jexus”架构模式是Linux承载ASP.NET企业 ...

  3. spring-data-jpa 介绍 复杂查询,包括多表关联,分页,排序等

    本篇进行Spring-data-jpa的介绍,几乎涵盖该框架的所有方面,在日常的开发当中,基本上能满足所有需求.这里不讲解JPA和Spring-data-jpa单独使用,所有的内容都是在和Spring ...

  4. PHP error_reporting() 错误控制函数功能详解

    定义和用法:error_reporting() 设置 PHP 的报错级别并返回当前级别. 函数语法:error_reporting(report_level) 如果参数 level 未指定,当前报错级 ...

  5. 2018 Multi-University Training Contest 3 Solution

    A - Problem A. Ascending Rating 题意:给出n个数,给出区间长度m.对于每个区间,初始值的max为0,cnt为0.遇到一个a[i] > ans, 更新ans并且cn ...

  6. hdu5102 枚举每条边的长度

    题意 给了 一颗 有 100000 个节点的树, 他们构成的边有 n*(n-1)/2 种. 每条边有一个长度,长度排序后 取前K条的 和, 枚举每条长度为1 的边 放进队列,然后通过成都为1 的表去 ...

  7. Linux /python --- zipinfo命令

    Linux zipinfo命令用于列出压缩文件信息. 执行zipinfo指令可得知zip压缩文件的详细信息. zipinfo [-12hlmMstTvz][压缩文件][文件...][-x <范本 ...

  8. sqoop2-1.99.5-cdh5.5.4.tar.gz的部署搭建

    不多说,直接上干货! 首先,说下博主我,为什么,好端端的Sqoop1用的好好的,然后又安装和学习Sqoop2? 因为,在Cloudera Hue里的Sqoop,是需要Sqoop2. HUE配置文件hu ...

  9. 20145221 《Java程序设计》实验报告五:网络编程及安全

    20145221 <Java程序设计>实验报告五:网络编程及安全 实验要求 掌握Socket程序的编写 运行TCP代码包,结对进行,一人服务器,一人客户端 掌握密码技术的使用 利用加解密代 ...

  10. Android项目开发第四周学习总结

    Android项目开发实战第四周 在本周,我们进行了Android项目第四周的项目开发,在本周,我们对原有的项目进行改进,我们的想法是使项目在原有的基础上增加一些新的功能,使得txt阅读器可以更加先进 ...