概念:
树:
一种数据结构,由n个节点组成的具有层次关系的集合(n>0,n有穷)
树的特点:
1、每个节点有0个或多个子节点;
2、没有父节点的节点称为根节点;
3、每一个非根节点有一个父节点;
4、除了根节点外,每个子节点可以分为多个不相交的子树。
树的术语:
度数:一个节点的子节点个数称为该节点的度数
树的度数:树中节点最大的度
兄弟节点:父节点相同的节点称为兄弟节点
页节点:没有子节点(度为零的节点)的节点成为叶节点
分支节点:度不为零的节点
层次:根节点层次为1,除根节点外的节点的层次为其父节点层次加1
高度(深度):树中节点最大的层次
森林:0个或多个不相交的树组成,对森林加上一个共同的跟,则课组成一颗树。
二叉树:
二叉树定义:每个节点最多两个子树的树结构
二叉树性质:
1、二叉树第i层上的节点最多为
2、深度(高度)为k的树的节点最多为
3、有n个节点的二叉树的高度最少为
4、任一棵二叉树,如果叶子节点为n0,度为2的节点为n2,则n0 = n2 + 1
5、满二叉树中的叶子节点数比分支数多1
满二叉树:
高度为h,共有个节点的二叉树。即除了叶结点外每一个结点都有左右子叶且叶子结点都处在最底层的二叉树。
完全二叉树:
一棵二叉树中,只有最下面两层结点的度可以小于2,并且最下一层的叶结点集中在靠左的若干位置上。这样的二叉树称为完 全二叉树。叶子结点只能出现在最下层和次下层,且最下层的叶子结点集中在树的左部。显然,一棵满二叉树必定是一棵完全 二叉树,而完全二叉树未必是满二叉树。
二叉查找树(二叉搜索树,二叉排序树):
1,任意节点x,其左子树中的key不大于x.key(如果左子树存在),其右子树中的key不小于x.key(如果右子树存在)。
2,不同的二叉搜索树可以代表同一组值的集合。
3,二叉搜索树的基本操作和树的高度成正比,所以如果是一棵完全二叉树的话最坏运行时间为Θ(lgn),但是若是一个n个节 点连接成的线性树,那么最坏运行时间是Θ(n)。
4,每一个节点至少包括key、left、right与parent四个属性,构建二叉搜索树时,必须存在针对key的比较算法。
二叉查找树经过中序遍历后应该返回的是有序数组。
二叉树实现:
二叉树(Binary Tree)是每个节点最多有两个子树的有序树。
二叉树常用链式存储。如下图;
构建二叉树(python实现):
#定义节点类
class Node:
def __init__(self,x):
self.val = x
self.left = None
self.right = None
# 定义树
class Tree:
def __init__(self):
self.root = None
# 添加节点
def add(self,value):
node = Node(value)
if self.root == None:
self.root = node
return
else:
q = [self.root] #构建队列,每添加一个新节点都需要扫描树中已有的所有节点
while q:
curNode = q.pop(0) # 先进先出
# print(curNode.val,curNode.left,curNode.right)
# 先判断左节点
if curNode.left is None:
curNode.left = node
return
else:
q.append(curNode.left)
# 后判断右节点
if curNode.right is None:
curNode.right = node
return
else:
q.append(curNode.right)
myTree = Tree()
# 为对象myTree添加节点
for i in range(10):
myTree.add(i)
二叉树的集中遍历方式:
深度遍历(前序,中序,后序)
1.前序遍历(根左右)
访问根节点
前序遍历根节点的左子树
前序遍历根节点的右子树
2.中序遍历(左根右)
中序遍历根节点的左孩子
访问根节点
中序遍历根节点的右孩子
3.后序遍历(左右根)
后序遍历根节点的左子树
后序遍历根节点的右子树
访问根节点
4.层次遍历(广度遍历)
对整棵二叉树按从上到下,对每一层按从左到右的顺序进行遍历。这里我们需要借助队列:先访问节点的孩子节点也应比后访问节点的孩子节点先访问。故这就类似于队列先进先出的性质,每访问一个节点时,它的孩子节点(如果存在)就随着入队。
遍历实现:
root = myTree.root
# 前序遍历(递归实现)
def preorderTraversal(root):
result = []
if root == None:
return result
rootV = root.val
result.append(rootV)
leftV = preorderTraversal(root.left)
rightV = preorderTraversal(root.right)
result += leftV + rightV
return result
print(preorderTraversal(root))
# 中序遍历(递归实现)
def inorderTraversal(root):
result = []
if root == None:
return result
rootV = root.val
leftV = inorderTraversal(root.left)
rightV = inorderTraversal(root.right)
result = leftV + [rootV] + rightV
return result
print(inorderTraversal(root))
# 后序遍历(递归实现)
def postorderTraversal(root):
result = []
if root == None:
return result
rootV = root.val
leftV = postorderTraversal(root.left)
rightV = postorderTraversal(root.right)
result = leftV + rightV + [rootV]
return result
print(postorderTraversal(root))
# 广度遍历(层次遍历)
def breadthTraversal(root):
result = []
if root == None:
return result
# 和构建节点类似,需要逐层从左至右访问每个节点
q = [root]
while q:
curNode = q.pop(0)
result.append(curNode.val)
if curNode.left != None:
q.append(curNode.left)
if curNode.right != None:
q.append(curNode.right)
return result
print(breadthTraversal(root))