概念
树:树是一些节点的集合。这个集合可以是空集;若集合不是空集,则树由根节点r以及0个或多个子树组成。
边:两个节点之间的连线就是边。
树叶:没有儿子的节点称为树叶。
节点的度:节点拥有的子树数称为节点的度。
度:节点的度的最大值称为树的度。
兄弟:具有相同父亲节点的节点称为兄弟。
路径:从节点n1到节点nk的路径定义为n1,n2,…,nk的一个序列,但是ni必须是n(i+1)的父节点。这也要求了路径必须从根节点往下遍历,而不能逆向而上。而且对于任意节点,有且只有一条路径。
路径的长:某条路径上的边的个数就是路径的长。
深度:ni的深度表示从根节点到ni的路径的长。根的深度为0。
高度:ni的高度为从ni到其树叶的最大的深度。因此,所有树叶的高度都是0。一棵树的高等于它根的高,一棵树的深度等于它最深的叶子节点的深度。
遍历
对于一般的树来说,只有先序遍历与后序遍历,木有中序遍历——因为子树的个数不确定,无法决定访问根节点的时机。
先序遍历
1,先访问根节点。
2,依次先序遍历根节点的每棵子树。
这也是一个递归定义。
后序遍历
1,先依次后序遍历每棵子树。
2,再访问根节点。
性质
普通性质
1,有n个节点的树必然有n-1条边。 因为除根节点以外,每一个节点都有一条边通向它。
2,每一个节点有k个指向子树的域以及一个值域,那么在一棵有n个节点且度为k的树中,必有n(k-1)+1个空域。证明:空域的个数为k*n0+(k-1)*n1+...+n[k-1]。而n = n0+n1+...+nk,同时边数为n-1,边数也为k*n0+(k-1)*n1+...+n[k-1],三式结合即可得证。
二叉树性质
1,二叉树的第i层上最多有2的(i-1)次方个节点,注:i大于等于1——根节点为第一层。
2,深度为k的二叉树最多有2^k-1个节点。注:此处根的深度为1。
3,记叶子节点的个数为n0,度为2的节点个数为n2,则n0=n2+1。证明过程如下:
设n1表示度为1的节点数,则总节点数n=n1+n0+n2——式1。同理,也可知总边数为n-1=n1+2*n2——式2。则式2带入式1中就可证明性质3。
4,含有n个节点的二叉链表必含有n+1个空域(二叉链表——树的每一个节点都有三个域:值域,左子树域和右子树域,左右子树域用来指向左右子树根节点)。证明:空域的个数为2*n0+n1。而n = n0+n1+n2,同时n2=n0-1,所以2*n0+n1-1=n,性质得证。
树的表示法
对任意一棵树,常用的表示方法为孩子兄弟法——以二叉链表做树的存储结构,左链域指向第一个孩子节点,右链域指向下一个兄弟节点。该表示法又称二叉链表表示法或二叉树表示法。如(图片来源于维基百科)
以二叉链表表示一棵树,可以将任意一棵树转换为二叉树,而且该二叉树的根节点无右子树(因为原树的根结点没有兄弟节点)。利用这个性质,可以将一个森林转换成二叉树。
森林转二叉树
将森林中第二棵树的根节点看成第一棵树根结点的兄弟结点,则可以将森林转为二叉树。
1,先将各树转为二叉树。
2,将第i+1棵树的作为第i棵树的右子树。
或者:
1,第一棵树的根节点root为整个二叉树的根节点。
2,root的左子树为第一棵树的root的子树组成的二叉树。
3,root右子树为森林中除第一棵树之外的树组成的二叉树。
很明显第二种方法是一种递归方法,使用递归很容易写出相应的代码。