树形结构是一种非常重要的==非线性结构==,树形结构中数据元素之间具有==一对多==的逻辑关系。
树是由n(n>=0)个结点所构成的有限集合
当n=0时,称为空树
当n>0时,n个结点满足以下条件
有且仅有一个称为根的结点
其余结点可分为m个互不相交的有限集合,且每一个集合又构成一棵树,该树称为根节点的子树。
对于一颗非空树,其中有且仅有一个没有前驱的结点,这个结点就是==根节点==,其余结点有且仅有一个前驱,但可以有多个后继。
A
A
B
C
A
B
C
D
E
F
G
H
I
J
K
L
M
N
O
P
树的表示法:树形表示法、文氏图表示法、凹入图表示法和广义表(括号)表示法
树形表示法
文氏图表示法
凹入图表示法
广义表(括号)表示法
术语 | 描述 |
---|---|
树的结点 | 由一个数据元素及关联其子树的边所组成。 |
结点的边 | 实体与实体之间的逻辑关系 |
结点的==路径== | 从根结点到该结点所经历的结点和分支的顺序排列。 结点J的路径:A-->C-->G-->J |
路径的长度 | 结点路径中所包含的分支数。例如:结点J的路径长度为3. |
结点的==度== | 该结点所拥有的子树的数目。例如:结点A的度为3,结点B的度为1 |
树的==度== | 树中所有结点度的最大值。 |
叶结点 | 树中度为0的结点,也称为终端结点。 |
分支结点 | 树中度不为0的结点,也称为非终端结点。除叶子结点之外的所有结点都是分支结点。 |
孩子结点 | 结点的子树的根节点,也称为子节点。结点A的孩子结点是BCD |
双亲结点 | 某结点有孩子结点,则该结点称为孩子的双亲结点,也称为父节点。 |
子孙结点 | 该结点所有子树中的任意结点。 |
祖先结点 | 该结点的路径中除此结点之外的所有结点。 |
兄弟结点 | 具有同一个双亲的结点。 |
结点的==层次== | 规定树中根节点的层次为0,其他结点的层次是双亲结点的层次数加1,结点P层次数为4 |
树的==深度== | 树中所有结点的层次数的最大值加1。(a) 深度为1 (b)深度为3 (c)深度为5 |
有序树 | 各节点的所有子树之间从左到右有严格的次序关系,不能交换。 |
无序树 | 树中各节点的所有子树之间没有严格的次序关系。从左到右没有次序之分。 |
森林 | 由m(m>=0)棵互不相交的树所构成的集合 |
二叉树是一个特殊的树,每个结点最多只有两棵子树,且两棵子树也是二叉树。
精确定义:二叉树是由n(n>=0)个结点所构成的有限集合。当n=0时,这个集合为空,此时二叉树为空树,当n>0时,这个集合是由一个根结点和两个互不相交的分别称为左子树和右子树的二叉树构成。
二叉树的两棵子树有左右之分,所以二叉树是有序树
。
A
B
C
D
E
F
G
H
I
J
K
L
M
N
O
二叉树的5种基本形态:空树、只有根结点、只有左子树、只有右子树、既有左子树又有右子树
/
X
X
X
/
X
/
X
X
X
X
满二叉树是二叉树的一种特殊情况。
如果在一棵二叉树中,它的所有结点或者叶结点,或者是左、右子树都非空,并且所有叶结点都在同一层上,则称这棵二叉树为满二叉树。
A
B
C
D
E
F
G
H
I
J
K
L
M
N
O
如果在一棵具有n个结点的二叉树中,它的逻辑结构与满二叉树的前n个结点的逻辑结构相同,则称这样的二叉树为完全二叉树。
A
B
C
D
E
F
G
H
I
J
K
左支树:所有结点都没有右孩子的二叉树。
右支树:所有结点都没有左孩子的二叉树。
1)特性1:i层最多结点数 2^i
二叉树中第i(i>=0)层上的结点数最多为2^i
i层012345⋯i最多结点数202122232425⋯2i最多结点数12481632⋯2i
2)特性2:最多结点个数 2^h-1
深度为h(h>=1)的二叉树中最多有2^h-1个结点
Sn=a1+a2+a3+⋯+an−1+anSn=a1+a1q+a1q2+⋯+a1qn−2+a1qn−1qSn=a1q+a1q2+a1q3+⋯+a1qn−1+a1qnSn−qSn=a1−a1qnSn=a1−a1qn1−qSn=a1(1−qn)1−q
S_n=\dfrac{a_1(1-q^n)}{1-q} = 2^n-1 & (a_1=1, q=2) \\ S_n= 2^h-1 & (h \ge 1 , 最多) \\ S_n= 2^{h-1} & (h \ge 1 , 最少) \\ \tag{二叉树求和}
3)特性3:叶子结点关系 n_0 = n_2 + 1
对于任意一颗二叉树,若其叶结点的个数为n_0,度为2的结点个数为n_2,则有n_0=n_2+1
n_0 = n_2 + 1 & (n_0叶子节点个数,n_2度为2的结点个数) \\ \tag {}
验证1:
验证2:
证明
& n_1 度为1的结点个数 ,n 总结点个数,e分支的个数 \\ n = n_0 + n_1 + n_2 & 总数 = 叶结点 + 度为1结点 + 度为2结点 \\ e = n_1 + 2 × n_2 & 度为1结点有1个分支,度为2的结点有2个分支 \\ n = e + 1 & 除了根结点,其他每个结点均对应一个进入它的分值 \\ n_0 = n_2 + 1
4)特性4:深度 ⌊log2n⌋ + 1
具有n个结点的完全二叉树的深度为⌊log2n⌋ + 1 或 ⌊log2(n+1)⌋
h=⌊log2n⌋+1
数的深度取值公式log2n的值⌊log2n⌋的值34≤n<822≤n<232≤log2n<3248≤n<1623≤n<243≤log2n<43516≤n<3224≤n<254≤log2n<54632≤n<6425≤n<265≤log2n<65h2h−1≤n<2hh−1≤log2n<hh−1
数学常识
向下取整的运算称为Floor,用数学符号⌊ ⌋表示;向上取整的运算称为Ceiling,用数学符号⌈ ⌉表示
例如: ⌊59/60⌋=0 ⌈59/60⌉=1 ⌊-59/60⌋=-1 ⌈-59/60⌉=0
5)特性5:判断是否
若对含n个结点的完全二叉树从上到下且从左至右进行0至n-1的编号,则对完全二叉树中任意一个编号为1的结点有:
若i=0,则该结点是二叉树的根,无双亲,否则编号为(i-1)/2的结点为其双亲结点。
若2i+1>=n,则该结点无左孩子,否则,编号为2i+1的结点为其左孩子结点
如果2i+2>=n,则该结点无右孩子结点,否则,编号为2i+2的结点为其右孩子结点。
0
1
2
3
4
5
6
7
8
9
10
序号i结论5.1双亲节点i−12个数n2i+1结论5.2左孩子2i+2结论5.3:右孩子55−12=2711无12无33−12=1872×3+1=78无44−12=11192×4+1=9102×4+2=10
1)顺序存储结构
完全二叉树存储:
用一组地址连续的存储单元从根结点开始依次自上而下,并按层次从左到右存储完全二叉树上的各节点元素,即将完全二叉树编号为i的结点元素存储在下标为i数组元素中。
非完全二叉树:
先在树中增加一些并不存在的虚结点并使其成为一棵完全二叉树,然后用与完全二叉树相同的方法对结点进行编号,再将编号为i的结点的值存放到数组下标为i的数组单元中,虚结点不存放任何值。
顺序存储适用于满二叉树和完全二叉树。
对于非完全二叉树来说,一个深度为h的树,需要的存储单元为2^h-1,会造成空间的浪费,如:对于右支树来说,只需要h个存储单元,但是存储的时候却要使用2^h-1个空间。
2)链式存储结构
二叉树的链式存储:将二叉树的各个结点随机的存放在位置任意的内存空间中,各个结点之间的逻辑关系通过指针来反映。
链式存储有2种方式:二叉链表存储结构、三叉链表存储结构
二叉链表存储结构有3个域:数据域data、左孩子域lchild、右孩子域rchild
三叉链表存储结构有4个域:数据域data、左孩子域lchild、右孩子域rchild、父节点域parent
二叉链表存储结构示意图
三叉链表存储结构示意图
二叉链式存储结构是二叉树最常用的存储结构。
结点类
public class BiTreeNode { public Object data; //数据域 public BiTreeNode lchild, rchild; //左、右孩子域 }
二叉树类
public class BiTree { private BiTreeNode root; //树的根节点 public BiTree() { //构建一颗空树 this.root = null; } public BiTree(BiTreeNode root) { //构建一棵树 this.root = root; } }
root.lchild = new BiTreeNode("B");
root.rchild = new BiTreeNode("C");