《树》——二叉树(Java)

简介: 完整代码下载地址: 点击下载 1:二叉树的分类 (1)空二叉树——如图(a); (2)只有一个根结点的二叉树——如图(b); (3)只有左子树——如图(c); (4)只有右子树——如图(d); (5)完全二叉树——如图(e)。

完整代码下载地址: 点击下载


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;

结果展示




相关文章
|
1月前
|
Java
【用Java学习数据结构系列】震惊,二叉树原来是要这么学习的(二)
【用Java学习数据结构系列】震惊,二叉树原来是要这么学习的(二)
26 1
|
1月前
|
算法 Java C语言
【用Java学习数据结构系列】震惊,二叉树原来是要这么学习的(一)
【用Java学习数据结构系列】震惊,二叉树原来是要这么学习的(一)
23 1
|
19天前
|
算法 Java
JAVA 二叉树面试题
JAVA 二叉树面试题
14 0
|
3月前
|
存储 Java
|
3月前
|
存储 Java
|
3月前
|
存储 算法 Java
LeetCode经典算法题:二叉树遍历(递归遍历+迭代遍历+层序遍历)以及线索二叉树java详解
LeetCode经典算法题:二叉树遍历(递归遍历+迭代遍历+层序遍历)以及线索二叉树java详解
79 0
|
5月前
|
Java
赫夫曼树(java)
赫夫曼树(java)
|
5月前
|
Java
二叉树简单遍历、查找、删除(java)
二叉树简单遍历、查找、删除(java)
|
5月前
|
存储 Java
顺序存储二叉树(java)
顺序存储二叉树(java)
树的遍历:迭代 & 递归|Java 刷题打卡
树的遍历:迭代 & 递归|Java 刷题打卡