树(二叉树)的基本概念
编程语言:python
作者:黑暗主宰
邮箱:shengzhanhe@gmail.com
数据结构–树
树的概念
树是一种非线性的数据结构,是由 n ( n > = 0 ) n(n >=0) n(n>=0)个结点组成的有限集合;它是一种类似于链表的数据结构,不过链表的结点是以线性方式简单地指向其后继结点,而树的一个结点可以指向许多个结点。它具有以下的特点:
- 每个节点有零个或多个子节点
- 没有父节点的节点成为根节点
- 每一个非根节点有且只有一个父节点
- 除了根节点外,每个子节点可以分为多个不想交的子树
相关术语
- 节点的度:一个节点含有的子树的个数称为该节点的度(如上图1节点的度为2;2节点的度为1);
- 叶子节点或终端节点:度为零的节点(如节点4、5、8、9);
- 树的度:一个树种,最大的节点的度称为树的度(如上图,0节点的度为3,所以这个数的度为3);
- 父节点:若一个节点含有子节点,则这个节点称为其子节点的父节点;
- 兄弟节点:具有相同父节点的节点称为兄弟节点(如4、5节点,1、2、3节点为兄弟节点);
- 节点的大小:节点的大小是指子孙的个数,包括自身(如子树1的大小为2,子树3的大小为3);
- 树的层:位于相同深度的所有节点的集合叫作树的层(如1、2、3具有相同的层,其中根节点算一层);
- 节点的层次:从根节点开始定义,根为第一层,根的子节点为第二次,以此类推;
- 树的深度或高度:树中节点的最大层次
二叉树
二叉树的定义:每个节点最多含有两个子树的树称为二叉树,通常子树被称为左子树和右子树。
二叉树的性质:
- 在二叉树的第 i i i层至多有 2 i − 1 {2^{{\rm{i}} - 1}} 2i−1个节点 ( i > 0 ) (i>0) (i>0)
- 深度为 k k k 的二叉树至多 2 m − 1 2^m-1 2m−1 个节点 ( k > 0 ) (k>0) (k>0)
- 对于任意一颗二叉树,如果其叶节点数为 N 0 N_0 N0,而度数为2的节点总数为 N 2 N_2 N2, 则 N 0 = N 2 + 1 N_0 = N_2 + 1 N0=N2+1。(对于这个性质的证明可以看这个博客)
- 具有 n n n 个节点(这里的节点不包括叶子节点)的完全二叉树的深度必为 log 2 ( n + 1 ) \log 2\left( {n + 1} \right) log2(n+1)
- 对完全二叉树,若从上至下、从左到右编号,则编号为 i i i 的节点,其做孩子编号必为 2 i 2i 2i, 其右孩子编号必为 2 i + 1 2i+1 2i+1;其双亲的编号必为 i / 2 i/2 i/2 ( i = 1 i=1 i=1 时为根除外)
二叉树的遍历
对于二叉树的遍历,主要分为三种:先序遍历、中序遍历和后续遍历(还有一个层次遍历可以算是第四种吧)。
如上图,先序遍历(根->左->右)是:145;中序遍历(左->根->右)是(415);后续遍历(左->右->根)是451,即根节点的位置决定遍历的种类。
对于复杂一点的二叉树,看下图
在上述,先序、中序、后续三种遍历中,给出两种方式就可以写出整个树,其中必须要包括中序。
代码实现树的遍历
节点的构建
class Node(object):
def __init__(self, item):
self.elem = item
self.lchild = None
self.rchild = None
然后使用上述节点构建树,并实现树节点的添加、层次遍历、前序遍历、中序遍历和后序遍历。
class Tree(object):
def __init__(self):
self.root = None
def add(self, item):
node = Node(item)
# 根节点为空的特殊清楚
if self.root is None:
self.root = node
return
queue = [self.root]
while queue:
cur_node = queue.pop(0)
if cur_node.lchild is None:
cur_node.lchild = node
return
else:
queue.append(cur_node.lchild)
if cur_node.rchild is None:
cur_node.rchild = node
return
else:
queue.append(cur_node.rchild)
def breadth_travel(self):
#根节点为空的情况
if self.root is None:
return
queue = [self.root]
while queue:
cur_node = queue.pop(0)
print(cur_node.elem, end = ' ')
if cur_node.lchild is not None:
queue.append(cur_node.lchild)
if cur_node.rchild is not None:
queue.append(cur_node.rchild)
'''
先序遍历
'''
def preorder(self, node):
if node is None:
return
print(node.elem, end=" ")
self.preorder(node.lchild)
self.preorder(node.rchild)
'''
中序遍历
'''
def inorder(self, node):
if node is None:
return
self.inorder(node.lchild)
print(node.elem, end=" ")
self.inorder(node.rchild)
'''
后序遍历
'''
def postorder(self, node):
if node is None:
return
self.postorder(node.lchild)
self.postorder(node.rchild)
print(node.elem, end=" ")
代码测试
tree = Tree()
tree.add('0')
tree.add('1')
tree.add('2')
tree.add('3')
tree.add('4')
tree.add('5')
tree.add('6')
tree.add('7')
tree.breadth_travel()
print()
tree.preorder(tree.root)
print()
tree.inorder(tree.root)
print()
tree.postorder(tree.root)
欢迎大家关注我的个人公众号,同样的也是和该博客账号一样,专注分享技术问题,我们一起学习进步
注: 文中有写错的地方,欢迎大家不吝指正!!!