完整代码下载地址: 点击下载
1:二叉树的分类
(1)空二叉树——如图(a);
(2)只有一个根结点的二叉树——如图(b);
(3)只有左子树——如图(c);
(4)只有右子树——如图(d);
(5)完全二叉树——如图(e)。
2:二叉树的相关术语
树的结点:包含一个数据元素及若干指向子树的分支;
孩子结点:结点的子树的根称为该结点的孩子;
双亲结点:B 结点是A 结点的孩子,则A结点是B 结点的双亲;
兄弟结点:同一双亲的孩子结点; 堂兄结点:同一层上结点;
祖先结点: 从根到该结点的所经分支上的所有结点子孙结点:以某结点为根的子树中任一结点都称为该结点的子孙
结点层:根结点的层定义为1;根的孩子为第二层结点,依此类推;
树的深度:树中最大的结点层
结点的度:结点子树的个数
树的度: 树中最大的结点度。
叶子结点:也叫终端结点,是度为 0 的结点;
分枝结点:度不为0的结点;
有序树:子树有序的树,如:家族树;
无序树:不考虑子树的顺序;
3:二叉树的性质
(1) 在非空二叉树中,第i层的结点总数不超过
, i>=1;
(2) 深度为h的二叉树最多有
个结点(h>=1),最少有h个结点;
(3) 对于任意一棵二叉树,如果其叶结点数为N0,而度数为2的结点总数为N2,则N0=N2+1;
(4) 具有n个结点的完全二叉树的深度为
(5)有N个结点的完全二叉树各结点如果用顺序方式存储,则结点之间有如下关系:
若I为结点编号则 如果I>1,则其父结点的编号为I/2;
如果2*I<=N,则其左儿子(即左子树的根结点)的编号为2*I;若2*I>N,则无左儿子;
如果2*I+1<=N,则其右儿子的结点编号为2*I+1;若2*I+1>N,则无右儿子。
(6)给定N个节点,能构成h(N)种不同的二叉树。
h(N)为卡特兰数的第N项。h(n)=C(2*n,n)/(n+1)。
(7)设有i个枝点,I为所有枝点的道路长度总和,J为叶的道路长度总和J=I+2i
=================================以上摘自百度百科
初始化二叉树
添加节点
查找节点
获取左右子树
判断是否是空树
计算二叉树的深度
清空二叉树与显示节点数据
二叉树的三种遍历方式是,先序遍历,中序遍历,后序遍历
测试:
结果展示
=================================以上摘自百度百科
4:相关代码
创建一个树节点类型static final int MAXLen = 20 ; //定义最大长度 class CBType{ String data; //节点值 CBType left; //左孩子引用 CBType right; //右孩子引用 }
初始化二叉树
/* * 初始化二叉树 */ CBType initTree() { CBType node; if( (node = new CBType())!=null ) //如果内存分配成功 { System.out.println("请先输入一个根节点数据:"); node.data = input.next(); //初始化节点的各部分值 node.left = null; node.right = null; if(node!=null) return node; else return null; } return null; }
添加节点
/* * 添加节点 */ void addTreeNode(CBType treeNode) { CBType pnode,parent; String data; int menusel; if( ( pnode = new CBType())!=null ) { System.out.println("请输入二叉树的节点数据:"); pnode.data = input.next(); pnode.left = null; pnode.right = null; System.out.println("输入该节点的父结点的数据:"); data = input.next(); parent = TreeFindNode(treeNode,data); //查找指定数据的节点 if(parent == null) { System.out.println("未找到该父结点!"); pnode = null; //如果未找到,释放该节点 return; } //如果找到的话进行以下操作 System.out.println("1:添加该节点到左子树\n2:添加该节点到右子树"); do{ menusel = input.nextInt(); //输入1或者2 if(menusel==1 || menusel==2) { if(parent==null) { System.out.println("不存在父结点,请先设置父结点"); } else { switch(menusel) { case 1: //添加到左子树 if(parent.left != null) { System.out.println("左子树节点不能为空"); } else { parent.left=pnode; } break; case 2: if(parent.right != null ) { System.out.println("右子树节点不能为空"); } else { parent.right=pnode; } break; default: System.out.println("无效的参数!"); } } } }while(menusel != 1 && menusel != 2); } }
查找节点
/* * 查找节点,分别递归查找左子树和右子树。逐个进行比较,若找到目标数据,则返回该数据所在的节点的引用 */ CBType TreeFindNode(CBType treeNode, String data) { CBType ptr; if(treeNode==null){ return null; } else { if(treeNode.data.equals(data)) { return treeNode; } else { if( (ptr=TreeFindNode(treeNode.left, data)) != null ) //递归查找左子树 { return ptr; } else if( (ptr = TreeFindNode(treeNode.right, data))!= null ) //递归查找右子树 { return ptr; } else //如果在左右子树中均没有找到,则返回null { return null; } } } }
获取左右子树
/* * 获取左子树 */ CBType TreeLeftNode(CBType treeNode) { if(treeNode!=null) return treeNode.left; else return null; } /* * 获取右子树 */ CBType TreeRightNode(CBType treeNode) { if(treeNode != null) return treeNode.right; else return null; }
判断是否是空树
/* * 判断空树,就是判断一个二叉树的结构是否为空,如果为空,则表示该二叉树结构中没有数据 */ int TreeIsEmpty(CBType treeNode) { if(treeNode!=null) return 0; return 1; }
计算二叉树的深度
/* * 计算二叉树的深度 */ int TreeDepth(CBType treeNode) { int depthLeft, depthRight; if(treeNode==null) { return 0; //对于空树,深度为0 } else { depthLeft = TreeDepth(treeNode.left); //左子树递归 depthRight = TreeDepth(treeNode.right); //右子树递归 if(depthLeft>depthRight) return depthLeft+1; return depthRight+1; } }
清空二叉树与显示节点数据
/* * 清空二叉树 */ void ClearTree(CBType treeNode) { if(treeNode != null) { ClearTree(treeNode.left); //清空左子树 ClearTree(treeNode.right); //清空右子树 treeNode = null; } } /* * 显示节点数据 */ void TreeNodeData(CBType p) { System.out.print(p.data + "\t"); }
二叉树的三种遍历方式是,先序遍历,中序遍历,后序遍历
//先序遍历 void DLRTree(CBType treeNode) { if(treeNode!=null) { TreeNodeData(treeNode); //显示节点数据 DLRTree(treeNode.left); DLRTree(treeNode.right); } } //中序遍历 void LDRTree(CBType treeNode) { if(treeNode != null) { LDRTree(treeNode.left); //中序遍历左子树 TreeNodeData(treeNode); //显示节点数据 LDRTree(treeNode.right); //中序遍历左子树 } } //后序遍历 void LRDTree(CBType treeNode) { if(treeNode!= null) { LRDTree(treeNode.left); //中序遍历左子树 LRDTree(treeNode.right); //中序遍历左子树 TreeNodeData(treeNode); //显示节点数据 } }
测试:
CBType root = null; Scanner in = new Scanner(System.in); int menusel; //决定添加到左子树还是右子树 tree t= new tree(); root = t.initTree(); //添加节点 do{ System.out.println("请选择菜单添加二叉树的节点:"); System.out.print("0:退出" + "\t"); //显示菜单 System.out.println("1:添加二叉树的节点"); menusel = in.nextInt(); switch(menusel) { case 1: t.addTreeNode(root); //添加节点 break; case 0: break; default: ; } }while(menusel!=0); //遍历 do{ System.out.println("请选择菜单遍历二叉树,输入0 表示退出"); System.out.print("1:先序遍历DLR \t"); System.out.print("2:中序遍历LDR \t"); System.out.println("3:后序遍历LRD"); menusel = in.nextInt(); switch(menusel) { case 0: break; case 1: System.out.println("先序遍历DLR的结果:"); t.DLRTree(root); System.out.println(); break; case 2: System.out.println("中序遍历的结果:"); t.LDRTree(root); System.out.println(); break; case 3: System.out.println("后序遍历的结果:"); t.LRDTree(root); System.out.println(); break; default: ; } }while(menusel != 0); //树的深度 System.out.println("\n二叉树的深度为:" + t.TreeDepth(root)); //清空二叉树 t.ClearTree(root); root = null;
结果展示