树——二叉树的概念及构造(Java实现)

先普及一下树的概念

  • 树的定义
    • 树是由n(n>=0)个结点点组成的有限集合。若n=0,称为空树;若n>0,则
      • (1)有一个特定的称为根(root)的结点,他只有后继,没有前驱;
      • (2)除根结点以外的其他结点可以划分为m(m>=0)个互不相关的集合T0、T1、...Tm-1,每个集合Ti又是一颗树,称为根的子树,
      • 每颗子树的结点有且只有直接前驱,但可以有一个或多个后继。
  • 树的基本术语
    • (1)结点
      • 指树中的一个数据元素,一般用一个字母表示。
    • (2)度
      • 一个结点包含树的数目,称为该结点的度
    • (3)树叶(叶子)
      • 度为0的结点,称为叶子结点或树叶,也叫终端结点
    • (4)孩子结点
      • 若结点X有子树,则紫薯的根结点为X的孩子结点,也称为孩子。
    • (5)双亲结点
      • 若结点X有子女Y,则X为Y的双亲结点
    • (6)祖先结点
      • 从根结点到该结点所经过分枝上的所有结点为该结点的祖先
    • (7)子孙结点
      • 某一结点的子女及子女的子女都为该结点子孙。
    • (8)兄弟结点
      • 具有同一个双亲的结点,称为兄弟结点
    • (9)树的度——唯一性
      • 树中结点度的最大值称为最大值称为树的度
    • (10)树的层数
      • 根结点的层数为1,其他结点的层数为从根结点到该结点所经过分支数目再加1。
    • (11)树的高度 (深度)
      • 树中结点所处的最大层数称为树的高度
    • (12)有序树与无序树
      • 若一棵树中所有子树从左到右的排序是有顺序的,不能颠倒次序,称该树为有序树,反之为无序树。
    • (13)森林(树林)
      • 若干颗数称为森林,一棵树也是一个特殊的森林。

树可以转换为二叉树,二叉树还原为树。所以我们在解决树的问题时,可以通过实现二叉树来实现目的。

二叉树

二叉树的性质

  • (1)若二叉树的层次从1开始,则二叉树的第i层最多有2^(i-1)个结点。(i>=1)
  • (2)深度为k的二叉树最多有2^k-1个结点。(k>=1)       推导公式:1+2+...+2^(k-1)
  • (3)对于任一棵非空二叉树,若其叶结点数为n0,度为2的非叶结点数为n2,则n0 = n2 +1。
  • (4) 具有n个结点的完全二叉树的深度为int_UP(log(2,n+1))。
  • (5).如果将一棵有n个结点的完全二叉树自顶向下,同一层自左向右连续给结点编号1,2,3,......,n,然后按此结点编号将树中各结点顺序的存放于一个一维数组,并简称编号为i的结点为结点i( i>=1 && i<=n),则有以下关系:
    • (1)若 i= 1,则结点i为根,无父结点;若 i> 1,则结点 i 的父结点为结点int_DOWN(i / 2);
    • (2)若 2*i <= n,则结点 i 的左子女为结点 2*i;
    • (3)若2*i<=n,则结点i的右子女为结点2*i+1;
    • (4)若结点编号i为奇数,且i!=1,它处于右兄弟位置,则它的左兄弟为结点i-1;
    • (5)若结点编号i为偶数,且i!=n,它处于左兄弟位置,则它的右兄弟为结点i+1;
    • (6)结点i所在的层次为 int_DOWN(log(2,i))+1。

存储方式

 (1)顺序存储——数组存储(占用空间大,适合存完全二叉树(只要层数达到,并且除最后一层外全满))

  (2)链式存储——二叉链表

实现方式

感觉用数组实现树的真的特别少,所以这里我们通过二叉链表实现二叉树。

package cn.datastruct.tree;
/**
 * 二叉树
 * @author hydra
 *
 */
public class BinaryTree {
	
	private Node root;//根结点

	class Node{		//内部类模仿树结构
		
		private int val;
		private  Node lchild;//左孩子
		private Node rchild;//右孩子
		
		
		public Node(int val) {
			this.val = val;
		}		
	}
	
	public void setRoot(int val) {
		this.root.val= val;
	}
	public Node getRoot() {
		return root;
	}
	public BinaryTree(int val) {
		Node node = new Node(val);
		this.root = node;
	}
	
	public BinaryTree() {	
		this.root = null;
	}
	
	/**
	 * 添加节点
	 * @param val
	 */
	public boolean add(int val){
		//创建新节点对象
		Node node = new Node(val);
		if(root==null) {//根结点不存在
			root = node;
			return true;
		}else {
			Node cur = root;
			while(true) {
				if(val < cur.val) {
					if(cur.lchild == null) {
						Node newNode = new Node(val);
						cur.lchild = newNode;
						return true;
					}
					cur = cur.lchild;
				}else if(val > cur.val){
					if(val > cur.val) {
						if(cur.rchild == null) {
							Node newNode = new Node(val);
							cur.rchild = newNode;
							return true;
						}
						cur = cur.rchild;
					}
				}else {				
					return false;//不允许重复
				}
				
			}
		}
	}
	
	/**
	 * 查找树中是否含有某值
	 * @param val
	 * @return
	 */
	public Object find(int val) {		
		Node cur = root;//记录当前结点的对象
		while(true) {
			if(cur.val == val)
			{	
				return cur.val;
			}else if(cur.val > val){				
				cur = cur.lchild;
				if(cur==null) {
					return null;
				}
			}else if(cur.val < val){
				cur = cur.rchild;
				if(cur==null) {
					return null;
				}
			}
			
		}
	}
	
	/**
	 * 先序遍历
	 * @param node
	 */
	public static void preOrder(Node node) {
		if(node == null) {
			return ;
		}
		System.out.println(node.val);
		preOrder(node.lchild);		
		preOrder(node.rchild);
	}
	/**
	 * 中序遍历
	 * @param node
	 */
	public void inOrder(Node node) {
		if(node == null) {
			return ;
		}
		
		inOrder(node.lchild);	
		System.out.println(node.val);
		inOrder(node.rchild);
	}
	/**
	 * 后序遍历
	 * @param node
	 */
	public void froOrder(Node node) {
		if(node == null) {
			return ;
		}
		froOrder(node.lchild);		
		froOrder(node.rchild);
		System.out.println(node.val);

	}
	public static void main(String[] args) {
		BinaryTree tree = new BinaryTree();
		int[] a = new int[] {3,1,0,2,7,5,8,9};
		for (int i : a) {
			tree.add(i);
		}
//		tree.setRoot(3);
		System.out.println("前序遍历");
		tree.preOrder(tree.getRoot());
		System.out.println("中序遍历");
		tree.inOrder(tree.getRoot());
		System.out.println("后序遍历");
		tree.froOrder(tree.getRoot());

	}
}



其中中序输出是有序。

*************************************************************如有错误,欢迎指正**********************************************************

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值