二叉树是n个结点所构成的集合,它或为空树或为非空树。
对于非空树T:1.有且仅有一个称之为根的结点;2.除根节点之外的其余结点分为两个互不相交的子集T1和T2,分别称为左子树和右子树,且T1和T2也都是二叉树。
满二叉树:深度为k且含有个节点的二叉树。
完全二叉树:深度为k的,有n个结点的二叉树,当且仅当其每一个结点都与深度为k的满二叉树中编号从1-n的结点一一对应,称之为完全二叉树。
二叉树的性质:
1.在二叉树的第i层上至多有个结点(i >= 1)。
2.深度为k的二叉树至多有个结点(k >= 1)。
3.对任何一颗二叉树T,若其终端节点数(叶子节点数)为a ,度(结点拥有的子树数)为2的节点数为b ,则 a = b + 1
4.具有n个结点的完全二叉树的深度为floor()+1
5.如果一颗含有n个结点的完全二叉树的结点按层序编号(即从上到下,从左到右编号),如果某个结点的编号为i,那么它的左孩子的编号为2*i ,若2*i > n则表示结点i无左孩子,右孩子的编号为2*i+1
下面是Java实现的二叉树,里面包括 建树,树的遍历,求树的深度,节点个数,树的路径长度,树的带权路径长度,根节点到叶子节点组成的数字之和
import java.util.Scanner;
/**
* 二叉树
* 包括前序,中序,后序遍历
* 求树的深度,节点个数,树的路径长度,树的带权路径长度,根节点到叶子节点组成的数字之和
* @author tiny_spot
*
*/
public class BinaryTree {
static Scanner s = new Scanner(System.in);
public static void main(String []args) {
System.out.println("树的叶子节点的左右节点用0表示,前序输入");
BiTree root = new BiTree();
createTree(root);
preOrder(root);
System.out.println();
inOrder(root);
System.out.println();
postOrder(root);
System.out.println();
System.out.println("深度:"+depth(root));
System.out.println("节点个数:"+nodeCnt(root));
System.out.println("数字之和:"+numberSum(root, 0));
System.out.println("树的路径长度:"+treePathLen(root ,0));
System.out.println("树的带权路径长度:"+weightPathLen(root ,0));
}
/**
* 创建二叉树
* @param root
*/
public static void createTree(BiTree root) {
int t = s.nextInt();
root.setData(t);
if(t == 0)
return ;
else {
root.setData(t);
root.left = new BiTree();
createTree(root.left);
if(root.left.getData() == 0)
root.left = null;
root.right = new BiTree();
createTree(root.right);
if(root.right.getData() == 0)
root.right = null;
}
}
/**
* 先序遍历
* @param root
*/
public static void preOrder(BiTree root) {
if(root == null)
return;
System.out.print(root.getData()+" ");
preOrder(root.left);
preOrder(root.right);
}
/**
* 中序遍历
* @param root
*/
public static void inOrder(BiTree root) {
if(root == null)
return;
inOrder(root.left);
System.out.print(root.getData()+" ");
inOrder(root.right);
}
/**
* 后序遍历
* @param root
*/
public static void postOrder(BiTree root) {
if(root == null)
return ;
postOrder(root.left);
postOrder(root.right);
System.out.print(root.getData()+" ");
}
/**
* 计算二叉树的深度
* @param root
* @return 二叉树的深度
*/
public static int depth(BiTree root) {
if(root == null)
return 0;
int left = 1+depth(root.left);
int right = 1+depth(root.right);
return left > right ? left : right;
}
/**
* 计算二叉树节点个数
* @param root
* @return 二叉树节点个数
*/
public static int nodeCnt(BiTree root) {
if(root == null)
return 0;
int left = nodeCnt(root.left);
int right = nodeCnt(root.right);
return 1+left+right;
}
/**
* 求所有根到叶子节点组成的数字之和 1
* 所有路径:1->2->4, 1->2->5, 1->3 2 3
* 124+125+13=262 4 5
* @param root 树的根节点
* @param n 一开始的数字
* @return 数字之和
*/
public static int numberSum(BiTree root ,int n) {
if(root == null)
return 0;
int left = numberSum(root.left , n*10+root.getData());
int right = numberSum(root.right, n*10+root.getData());
if(left+right == 0)
return n*10+root.getData();
return left + right;
}
/**
* 求树的路径长度:即从树根到每一个节点的路径长度之和
* @param root
* @param n
* @return 树的路径长度之和
*/
public static int treePathLen(BiTree root ,int n) {
if(root == null)
return 0;
int left = treePathLen(root.left ,n+1);
int right = treePathLen(root.right, n+1);
return left + right + n;
}
/**
* 求树的带权路径长度:即树中所有叶子节点的带权路径长度之和
* 节点的带权路径长度:从该节点到树根之间的路径长度与节点上权值的乘积
* @param root
* @param n
* @return
*/
public static int weightPathLen(BiTree root ,int n) {
if(root == null)
return 0;
int left = weightPathLen(root.left, n+1);
int right = weightPathLen(root.right, n+1);
if(left+right == 0)//若左右子树的带权路径长度为0,则说明该节点是叶子节点
return n*root.getData();
return left + right;
}
}
class BiTree{
public BiTree left = null;
public BiTree right = null;
private int data ;
public void setData(int data) {
this.data = data;
}
public int getData() {
return data;
}
}
//1 2 3 0 0 4 5 0 6 0 0 7 0 0 0
//1 2 4 0 0 5 0 0 3 0 0
//1 3 7 0 0 5 0 0 6 2 0 0 4 0 0