树的常见概念
节点的度:一个节点含有的子节点的个数称为该节点的度。
树的度:一棵树中,最大的节点的度称为树的度。
叶节点或终端节点:度为0的点称为叶节点。
非终端阶段或分支节点:度不为0的节点。
双亲节点或父节点:若一个节点含有子节点,则这个节点称为其子节点的父节点。
孩子节点或子节点:一个节点含有的子树的根节点称为该节点的子节点。
兄弟节点:具有相同父节点的节点互称为兄弟节点。
节点的先祖:从根到该节点所经过分支上的所有节点。
子孙:以某个节点为根的子树中任一节点都称为该节点的子孙。
森林:由m(m >= 0)棵互不相交的树的集合称为森林。
无序树:树中任意节点的子节点之间没有顺序关系,这种树称为无序树,也称自由树。
有序树:树中任意节点的子节点之间有顺序关系,这种树称为有序树。
二叉树:每个节点最多含有两个子树的树称为二叉树。
树的性质
性质1:在二叉树的第i层上至多有2^(i - 1)个节点(i > 0)。
性质2:深度为k的二叉树之多有2^k - 1 个节点(k > 0)。
性质3:对于任意一颗二叉树,如果其叶子节点数为N0,而度数为2的节点总数为N2,则N0 = N2 + 1。
性质4:具有n个节点的完全二叉树的深度必为log2(n+1)。
性质5:对完全二叉树,若从上至下,从左至右编号,则编号为i的节点,其左孩子编号必为2i,其右孩子编号必为2i + 1;其双亲的编号必为i/2(i = 1时为根除外)。
树的定义与存储方式
二叉树的性质和链表本质相似,比链表多了一个指针,如果是二叉树,只需要在链表的定义上增加一个指针。
public class TreeNode {
int val;
TreeNode left;
TreeNode right;
}
如果是N叉树,又该怎么去定义呢?就是将节点指向一个List就行。
public class TreeNode{
int val;
List<TreeNode> nodes;
}
树的遍历方式
树的常见遍历方式:
深度优先遍历:先往深处走,遇到叶子节点在往回走。
广度优先遍历:一层一层的走,一层走完,再走下一层。
深度优先遍历又有前中后三种:
前序遍历:先遍历中间节点,在遍历左节点,最后遍历右节点。
中序遍历:先遍历左节点,在遍历中间节点,最后遍历右节点。
后序遍历:先遍历左节点,在遍历右节点,最后遍历中间节点。
通过序列构造二叉树
给出三个序列:
前序:1 2 3 4 5 6 7 8 9 10 11 12 13 15 14
中序:3 4 8 6 7 5 2 1 10 9 11 15 13 14 12
后序:8 7 6 5 4 3 2 10 15 14 13 12 11 9 1
通过中序和后序序列恢复二叉树
由后序可以知道,1为二叉树的根节点。再由中序可以知道 3 4 8 6 7 5 2 在根节点的左边,10 9 11 15 13 14 12在根节点的右边。
此时树结构为:
这时,先看左边,中序 3 4 8 6 7 5 2 ,后序 8 7 6 5 4 3 2,这里可知左子树的根节点为2,此时可知 3 4 8 6 7 5在节点2 的左边,节点2的右边为空。
再看左边,中序 10 9 11 15 13 14 12,后序10 15 14 13 12 11 9,这里可知右子树的根节点为9,此时可知10在节点9的左边,11 15 13 14 12在节点9的右边。
先看左边,中序3 4 8 6 7 5,后序8 7 6 5 4 3,这里可以得知3为左子树的根节点,节点3的左边为null,节点3的右边为4 8 6 7 5。
再看右边,中序11 15 13 14 12,后序 15 14 13 12 11,可得11为右子树的根节点,节点11的左边为空,节点11的右边为 15 13 14 12。
先看左边,中序为4 8 6 7 5,后序8 7 6 5 4,可得4为左子树的根节点,节点4的左边为null,节点4的右边为 8 6 7 5。
再看右边,中序为15 13 14 12,后序15 14 13 12,可得12为左子树的根节点,节点12的左边为15 13 14,节点12的右边为null。
先看左边,中序 8 6 7 5,后序8 7 6 5,可得5为左子树的根节点,节点5的左边为8 6 7 ,节点5的右边为null。
再看右边,中序为15 13 14,后序 15 14 13,可得13为右子树的根节点,节点13的左边为15,节点13,右边为14。
看左边,中序为 8 6 7,后序为 8 7 6,可得6为左子树的根节点,节点6的左边为8,节点6的右边为7,最终可得二叉树。