树递归建立和二叉搜索树BST

1. 对于大量数据输入时候,链表方式进行数据查找耗费时间太长,因此引入 简单的数据结构树,树的操作耗费的平均时间 log(N), 

 树定义:由一个或者多个结点组成集合,但是结点之间串联不形成环--叫做树,树根据 儿子的多小分为 二叉树和 B树,现在最重点研究的是二叉树(每一个树中结点最多有量个儿子结点)。

2. 二叉树:度不超过2的树---(对于树数据结构 最主要目标:利用这种特性数据结构如何快速定位所需要查找的数据)查找二叉树、平衡二叉树和红黑树 

                   有如下特性:相比于度>2
1). 第 I 层最多 有2^(I-1)个结点
2). 深度K的二叉树 总结点数不超过 2^(K)-1 
3). 叶子结点数 N0,度为2 的结点数N2,度为1 结点数N1: 根据总的 边数相同情况下 0*N0+2*N2+1*N1=总的结点数-1=N0+N1+N2-1
  N0=N2+1;

3. 二叉树建立--树的定义 一种最自然方式采用递归方式建立二叉树,对树遍历 4中方式 前中后、层次遍历,对于数据输入 递归方式建立二叉树。 对于普通的二叉树,对于二叉搜索树等还有更加简便方式; 接下来 采用层次遍历和先序遍历方式 递归建立二叉树:

普通类型的二叉树 建立 使用递归的方式建立二叉树:
package com.offerr;



/** 
 * 利用层次遍历二叉树 */
public class CreatBinaryTree {

	public  static BinaryTree root;
	
	public CreatBinaryTree(int array[],int Key)
	{
	     if(Key>=1)
		{  // 采用层次遍历 递归建立二叉树
		   root=Tree(array,0);
		}
	     else 
	     {
			root=PreOrderTree(array);
			System.out.println(Kindex);
		}
	}

	/**
	 * 先序遍历的特性,必须 需要 成员变量 控制索引
	 * */
	private int Kindex=0;
	private BinaryTree PreOrderTree(int[] array) {
		
		int val=array[Kindex++];// Kindex 代表数组索引,不管是否-1 ,不得不向前加1
		
		if(  val==-1)
			return null;
		
			BinaryTree Node=new BinaryTree(val);
			Node.Left=PreOrderTree(array);
			Node.Right=PreOrderTree(array);
			return Node;
		
	}
	
	/**
	 * 层次遍历方式建立二叉树*/
	public BinaryTree Tree(int[] array,int index) {
		if(index>=array.length || array[index]<0)
			return null;
		BinaryTree Node=new BinaryTree(array[index]);
		Node.Left=Tree(array, 2*index+1);
		Node.Right=Tree(array, 2*index+2);
		
		return Node;
	}
	
	  public void preShow(BinaryTree node) { // 先序遍历  
          if (node != null) {  
              System.out.print(node.val + " ");  
              preShow(node.Left);  
              preShow(node.Right);  
          }  
      }  
	  
	  public static void main(String[] args) {  
	         int array[]={1,2,-1,5,-1,-1,3,-1,4,-1,-1};  
	         CreatBinaryTree Tree=new CreatBinaryTree(array,0); 
	         
	         Tree.preShow(root);  
	     }  
}

class BinaryTree
{
	public BinaryTree Left;
	public BinaryTree Right;
	
	public int val=0;
	public BinaryTree()
	{
		this(0);
	}
	public BinaryTree(int val) {
		this.Left=null;
		this.Right=null;
		this.val=val;
	}

}

4. BST 二叉查找树:

           1.树一个最重要的应用在于 树的查找时间复杂度o(logN),

      二叉查找树相比于普通二叉树 树的结点有一定的规律:任何结点X,它的左子树中所有项比X小,右子树中所有的值比X大,因此 在二叉树Insert 方法建立二叉树,不能够简单的递归的方式建立BST树 ,建立BST 主要 Insert,Remove,findMin,findMax等几个常用方法,

对于insert ,findMin,findMax等方法 确实没有多大的疑问,
但是 对于树这种逻辑结构,删除操作 有点困难,删除必须虑三种情况 
1.叶子节点 
2. 只有一个儿子节点
3.有俩个儿子 这里有两种策越:① 删除点的右子树的最小数据,因为此结点没有孩子结点,代替此结点
寻找删除结点的左子树的最大数据代替此结点。
注意如果要删除结点是根结点 ,代替根结点值 只能是右子树的最小值代替,删除右子树。

由于在remove操作时候 特别某一个结点有 两个孩子,采取寻找删除结点的右子树的最小值点,同时删除此最小值结点在树中原先的位置
/* 找到最小值点,同时在树中删除此最小值结点*/
private BinaryNode<AnyType> findMinR(BinaryNode<AnyType> t) {
	BinaryNode<AnyType> min=t.right;
	BinaryNode<AnyType> parent=null;// 两种情况 直线斜树 和 不是斜树
	
	while(min.left!=null)
	{
		parent=min;// 记录 min 父结点
		min=min.left;
	}
	
	if(parent==null)
	{// 表示 直线斜树
		t.right=min.right;//直接删除min结点
	}	
	else
	{		
			parent.left=min.right;
	}
	return min;
}
BST 树整体代码:


package com.offerr;

public class BinarySearchTree<AnyType extends Comparable<? super AnyType>>  {
	
	private BinaryNode<AnyType> root;
	
	public BinarySearchTree()
	{
		root=null;
	}
	
	private static class BinaryNode<AnyType>{
		
		AnyType Element;
		BinaryNode<AnyType> left;
		BinaryNode<AnyType> right;
		public BinaryNode(AnyType Element) {
			
			this(Element,null,null);
		}

		public BinaryNode(AnyType element, BinaryNode<AnyType> object, BinaryNode<AnyType> object2) {
			this.Element=element;
			this.left=object;
			this.right=object2;
		}
	}


	public void insert(AnyType x)
	{
		root=insert(x,root);
	}
	
	public boolean contains(AnyType x)
	{
		return conatins(root,x);
	}
	
	public void remove(AnyType x)
	{
		remove(root,x);
	}
	

	public AnyType findMin() throws Exception
	{
		if (isEmpty())
			throw new Exception("树是空树");
		return findMin(root).Element;
	}

	public void makeEmpty()
	{
		root=null;
	}
	public boolean isEmpty()
	{
		return root==null;
	}
	
	/**
	 * Insert
	 * */
	private BinaryNode<AnyType>insert(AnyType x, BinaryNode<AnyType> t) {
		if(t==null)
			return new BinaryNode<AnyType>(x);
		
		int ComparableResult=x.compareTo(t.Element);
		
		if(ComparableResult<0)
		{
			t.left=insert(x, t.left);
		}else if(ComparableResult>0)
		{
			 t.right=insert(x, t.right);
		}
		else {
			   ;// 插入点 与树中某个结点值相同,不进行任何操作
		}
		return t;
		
	}
	
	/**
	 * BST 的 最小值 最小值 一定最左边的叶子结点
	 * @throws Exception 
	 * */
	
	private BinaryNode<AnyType> findMin(BinaryNode<AnyType> t) {
		while(t.left!=null)
			t=t.left;
		return t;
	}
	private BinaryNode<AnyType> findMax(BinaryNode<AnyType> t) {
		while(t.right!=null)
			t=t.right;
		
		return t;
	}
	/**
	 * BST 包含 某一个结点 ,循环
	 * */
  private boolean conatins(BinaryNode<AnyType> t, AnyType x) {
		if(t==null)
			return false;
		
		// 使用循环
		while(t!=null)
		{
			int CompareResult=x.compareTo(t.Element);
			if(CompareResult==0)// match
				return true;
			else if(CompareResult<0)
				t=t.left;
			else {
				t=t.right;
			}
		}
		return false;
	}
  /**
   * 提供效率 不使用递归
   *  判定被删除点是不是 根结点*/
  private void remove(BinaryNode<AnyType> t, AnyType x) {
		if(t==null)
			return  ;
		// 定位到被删除的结点
		BinaryNode<AnyType> p=null;
		while(t!=null)
		{
			if(x.compareTo(t.Element)<0)
			{
				p=t;
				t=t.left;
			}
			else if(x.compareTo(t.Element)>0)
			{
				p=t;
				t=t.right;
				
			}
			else // 定位到被删除的结点
			{
				// 判断 被删除结点 是否是根结点 如果是根结点话,两个孩子
				if(t.left==null && t.right==null)
				{
					if(p==null)
					{
						// 被删除结点 是根结点 并且 无孩子,说明此树只有一个结点
						t=null;
					}
					else 
					{
						if(p.left==t) // 待删除结点是父结点的 左孩子
							p.left=t.left;
						else 
							p.right=t.right;
					}
					
				}
				else if(t.left==null || t.right==null )//有一个孩子
				{
						if(p==null) //判断删除结点 是否根结点
						{
							if(t.left!=null)
							     t=t.left;
							if(t.right!=null)
								t=t.right;
						}
						else // 被删除的点 不是 其根结点
						{
							if(t.left!=null) // 有左孩子
							{
								if(p.left==t)
									p.left=t.left;
								else
								    p.right=t.left;
							}
							if(t.right!=null)
							{
								if(p.left==t)
									p.left=t.right;
								else
								    p.right=t.right;
							}
						}
				}
				else // 有两个孩子
				{
					//  找到最小值点,同时删除最小值点在树中位置
				      BinaryNode<AnyType> min=findMinR(t); // 
					  t.Element=min.Element;
					  					  
				}
			}
		}
	}
/**
 * 找到最小值点,同时在树中删除此最小值结点*/
private BinaryNode<AnyType> findMinR(BinaryNode<AnyType> t) {
	BinaryNode<AnyType> min=t.right;
	BinaryNode<AnyType> parent=null;// 两种情况 直线斜树 和 不是斜树
	
	while(min.left!=null)
	{
		parent=min;// 记录 min 父结点
		min=min.left;
	}
	
	if(parent==null)
	{// 表示 直线斜树
		t.right=min.right;//直接删除min结点
	}	
	else
	{		
			parent.left=min.right;
	}
	return min;
}

public void preShow(BinaryNode<Integer> node) { // 先序遍历  
    if (node != null) {  
        System.out.print(node.Element + " ");  
        preShow(node.left);  
        preShow(node.right);  
    }  
}  
public static void main(String [] args)
{
	int array[]={6,5,9,4,7,10};
	BinarySearchTree<Integer> bst=new BinarySearchTree<>();
	
	for(int i=0;i<array.length;i++)
		bst.insert(array[i]);
	bst.preShow(bst.root);
	BinaryNode<Integer> re=bst.root;
	bst.remove(6);
	System.out.println();
	bst.preShow(bst.root);
}

}



    

    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值