无序树:树中任意节点的子节点之间没有有顺序关系,这种树成为无序树,也成为自由树
有序树:树中任意节点的子节点之间有顺序关系,这种树称为有序树
- 二叉树:每个节点最多含有两个子树的树称为二叉树
- 完全二叉树:除了最后一层,每层节点都达到最大数量
- 满二叉树:所有层的结点都达到最大数量
- 排序二叉树(二叉查找树(BinarySearch Tree), 也称二叉搜索树,有序二叉树)
- 霍夫曼树:带权路径最短的二叉树称为哈夫曼树或最优二叉树
- B树:一种对读写操作进行优化的自平衡的二叉树查找,能够保持数据有序,拥有多余两个子树
二叉树特性
度数就是它有几个子节点 度数为2的有3个节点
- 完全二叉树——二叉树除了最后一层,其他层结点都达到最大个数,就是完全二叉树。
- 满二叉树——除了叶结点外,每一个结点都有左右子叶且叶子结点都处在最底层的二叉树。
- 性质1:在二叉树的第i层上至多有2^(i-1)个结点(i>0)。 如果在第三层 2^(3-1)= 4 有4个节点
- 性质2:深度为k的二叉树至多有2^k - 1个结点(k>0)。 深度为3 2^3-1= 7 有7个节点
- 性质3:对于任意一棵二叉树,如果其叶结点数为N0,而度数为2的结点总数为N2,则N0=N2+1。 3+1=4
- 性质4:具有n个结点的完全二叉树的深度必为log2(n+1)。
- 性质5:对完全二叉树,若从上至下、从左至右编号,则编号为i 的结点,其左孩子编号必为2i,其右孩子编号必为2i+1,其父节点的编号必为i/2(i=1 时为根,除外)。
什么是二叉树的遍历
- 指对树中所有结点的数据的访问,即依次对树中每个结点访问一次且仅访问一次,把这种对所有节点的访问称为遍历(traversal)。
- 树的两种重要的遍历模式:深度优先遍历和广度优先遍历。
- 深度优先一般用递归,广度优先一般用队列。
- 一般情况下能用递归实现的算法大部分也能用栈来实现。
遍历
- 前序遍历:根左右
- EACBDGF
- 中序遍历:左根右
- ABCDEGF
- 后序遍历:左右根
- BDCAFGE
- 层次遍历:从上到下,从左到右
- EAGCFBD
深度优先遍历
- 对于一颗二叉树,深度优先搜索(Depth First Search)是沿着树的深度遍历树的节点,尽可能深的搜索树的分支。
- 深度遍历有重要的三种方法,这三种方式常被用于访问树的节点,它们之间的不同在于访问每个节点的次序不同。
- 三种遍历分别叫做先序遍历(preorder),中序遍历(inorder)和后序遍历(postorder)。
二叉树的定义
- 树中每个节点最多只能有两棵树,即每个节点的度最多为2。
- 二叉树的子树有左右之分,即左子树与右子树,次序不能颠倒。
- 二叉树即使只有一个子树时,也要区分是左子树还是右子树。
二叉树的链式存储: 将二叉树的节点定义为一个对象,节点之间通过类似链表的链接方式来连接
from collections import deque
class BiTreeNode:
def __init__(self, data):
self.data = data
self.lchild = None # 左孩子
self.rchild = None # 右孩子
a = BiTreeNode("A")
b = BiTreeNode("B")
c = BiTreeNode("C")
d = BiTreeNode("D")
e = BiTreeNode("E")
f = BiTreeNode("F")
g = BiTreeNode("G")
#e的左边是a,右边是G
#a的右孩子是c
#c的左孩子是b,c的右孩子是d
#g的右的孩子是f
e.lchild = a
e.rchild = g
a.rchild = c
c.lchild = b
c.rchild = d
g.rchild = f
#跟节点
root = e
#链表形式
print(root.lchild.rchild.data)
树的遍历
前序: 先从左边开始,左完了在是右边
后序 BDCAFGE
层次遍历 EAGFBD
#! /usr/bin/env python
# -*- coding: utf-8 -*-
from collections import deque
class BiTreeNode:
def __init__(self, data):
self.data = data
self.lchild = None # 左孩子
self.rchild = None # 右孩子
a = BiTreeNode("A")
b = BiTreeNode("B")
c = BiTreeNode("C")
d = BiTreeNode("D")
e = BiTreeNode("E")
f = BiTreeNode("F")
g = BiTreeNode("G")
#e的左边是a,右边是G
#a的右孩子是c
#c的左孩子是b,c的右孩子是d
#g的右的孩子是f
e.lchild = a
e.rchild = g
a.rchild = c
c.lchild = b
c.rchild = d
g.rchild = f
#跟节点
root = e
print(root.lchild.rchild.data)
#前序
def pre_order(root):
if root:
#访问跟节点
print(root.data, end=',')
#访问左子树
pre_order(root.lchild)
#访问右子树
pre_order(root.rchild)
#中序,左子树A是根节点,左边没有,右边是BCD,在BCD中,C是中间,C的左是B,右边是D
def in_order(root):
if root:
#先递归左子树
in_order(root.lchild)
#访问自己
print(root.data, end=',')
in_order(root.rchild)
#后续遍历 左右根
#根是在最后,所有左边的根就是在最后
def post_order(root):
if root:
post_order(root.lchild)
post_order(root.rchild)
print(root.data, end=',')
#先是空队,e进去了,e走了,ag进去了,a出队了,c进去了,g出队,f进队,c出队bd进队,fbd出队都没有孩子**
def level_order(root):
#空队列
queue = deque()
queue.append(root)
while len(queue) > 0: # 只要队不空
#出队
node = queue.popleft()
print(node.data, end=',')
#左孩子有
if node.lchild:
queue.append(node.lchild)
if node.rchild:
queue.append(node.rchild)
pre_order(root)
print("-------------")
in_order(root)
print("-------------")
post_order(root)
print("-------------")
level_order(root)
print("-------------")
参考文章
https://blog.csdn.net/yht201293018/article/details/81198827