①二叉树的定义:
节点:在Java当中,为一个对象,拥有left和right两个属性,左节点用来存放左值,右节点用来存放右枝。
如图为一个简易 的二叉树构图
②完全二叉树、满二叉树的概念
完全二叉树:定义:节点存放的顺序为从上到下,从左到右依次存储,中间不能存在空隙。
例如如下:
举一个非完全二叉树的例子:
此时,由于左下角的第二个箭头没有指向,任何一个节点,因此此二叉树就不是完全二叉树
③二叉树的层数定义:根节点到最远处的节点的最短路径(包含根节点和最远的节点)。
如上图,二叉树的层数就是3。
④满二叉树:在二叉树当中,第k层的节点数为2的(k-1)次方。因此,k层的二叉树,总的节点数为2的0次方+2的1次方+2的2次方+......+2的k-1次方等于2的k次方-1.
即:任意一层都是满的的二叉树。
⑤二叉树的一些常用结论,术语:
叶子节点:一棵二叉树的某个节点,如果它既没有左枝,又没有右枝,那么这个节点就是叶子节点。
节点的度:一个节点往下有几条边,那么就称这个节点的度是几。
(1)对于任意一颗二叉树,有n个节点,就有n-1条边
(2)对于任意一棵完全二叉树,度为0的节点的数量等于度为2的节点的数量+1。
推导过程:
假设一棵二叉树有N个节点,那么N=n0+n1+n2;n0度为0的节点,n1为度为1的节点,n2为度为2的节点。
根据二叉树的性质可以得知:二叉树度为0的节点可以产生0条边,边为1的节点可以产生1条边,边为2的节点可以产生2条边,那么,总的边数为n0*0+n1*1+n2*2;
因此,根据1结论可以得知:n0+n1+n2-1=n1+2*n2;
化简得到:n0=n2+1;
(3)在具有2*n个节点的完全二叉树当中,叶子节点的个数为n。
根据完全二叉树的定义可以推到出来,在完全二叉树当中,当边数为1的节点存在时候,完全二叉树的节点总数为n0+1+n2;假设叶子节点个数为n0,度数为2的节点个数为n2。因此可以得出:
2*n=n0+1+n2;2*n=n0+1+n0-1;2*n=2*n0;即:n=n0;那么叶子节点的个数就是n。
那么当完全二叉树节点为基数时候呢?同理,可以得出答案:N=n0+n0-1;n0=(N+1)/2;
(4)具有N个节点的完全二叉树的深度为log2(n+1)向上取整。
⑥二叉树的遍历
第一种遍历方式:根--->左--->右
思路:从跟出发,先遍历左枝,再遍历右枝:
实现:A-->B-->D-->C-->E-->F。
代码实现:
/**
* 前序遍历
* 根节点@param root
*/
public void preOrder(TreeNode root) {
if (root == null) {
return;
}
System.out.print(root.val);
preOrder(root.left);
preOrder(root.right);
}
第二种遍历方式:中序遍历:
左--->根--->右:回到上图:
顺序为:D-->B-->A-->E-->C-->F
代码实现:
/**
* 中序遍历
* 根节点@param root
*/
public void infixOrder(TreeNode root) {
if (root == null) {
return;
}
infixOrder(root.left);
System.out.println(root.val);
infixOrder(root.right);
}
第三种遍历方式:左-->右-->根
D-->B-->E-->F-->C-->A
代码实现
/**
* 后序遍历
* 根节点@param root
*/
public void afterOrder(TreeNode root) {
if (root == null) {
return;
}
afterOrder(root.left);
afterOrder(root.right);
System.out.println(root.val);
}
递归:返回到上一个方法里面调用此方法的位置。
来一道题目:
假设一棵二叉树的中序遍历是:badce,后序遍历是:bdeca;
求前序遍历:
第一步:寻找到根节点:
已知:后序遍历最后遍历的是根节点,因此a为二叉树的根节点。然后再看中序遍历的结果:
a的左边为左树,右边为右树。
再看后序遍历的结果,c位于a的上一个位置,因此c为一个根,那么此时就可以绘制出来一个二叉树的头三个节点:a为根节点,b为a的左节点,c为a的右节点,再根据遍历的顺序判断,d为c的左节点,e为c的右节点
再来一道题目:
已知一棵二叉树的先序遍历为E->F->H->I->G-->J-->K;
中序遍历为:H-->F-->I-->E-->J-->K-->G;
画出这一棵二叉树:由题目可知:E为根节点,HFI为左树,JKG为右数
中序遍历:谁的左枝先为空,就先输出谁。
因此可以判定:在左数部分:H的左枝为NULL,因此H被先输出,然后再返回调用左枝的节点,即:F节点,输出F的值,接着,输出完成之后,由于F的右枝不为NULL,因此,可以往右走,走完之后,由于右枝(I)的左枝为NULL,因此返回上一个节点(I),并且输出I的值...
那么,树的右枝同样道理。