今天来分享一下二叉搜索树--java实现

优点:
二叉树在搜索上的优势

数组的搜索比较方便,可以直接使用下标,
但删除或者插入就比较麻烦了,而链表与之相反,删除和插入都比较简单,但是查找很慢,
这自然也与这两种数据结构的存储方式有关,数组是取一段相连的空间,
而链表是每创建一个节点便取一个节点所需的空间,只是使用指针进行连接,空间上并不是连续的。
而二叉树就既有链表的好处,又有数组的优点。

1.Node节点
属性
父亲节点
左右孩子节点
要存储的数据
代码

package two;

public class Node {
    private Node lift;//左孩子
    private Node right;//右孩子
    private Node parent;//父亲节点
    private int item; //数据
    public Node(Node parent,Node lift,Node right,int item)
    {
    	this.parent = parent;
    	this.lift = lift;
    	this.right = right;
    	this.item = item;
    }
	public Node getLift() {
		return lift;
	}
	public void setLift(Node lift) {
		this.lift = lift;
	}
	public Node getRight() {
		return right;
	}
	public void setRight(Node right) {
		this.right = right;
	}
	public int getItem() {
		return item;
	}
	public void setItem(int item) {
		this.item = item;
	}
	public Node getParent() {
		return parent;
	}
	public void setParent(Node parent) {
		this.parent = parent;
	}
    
}

2.tree封装方法
增 add()
删 delect()
查 find()
层次打印 从上到下 利用一个队列进行bfs arrangement()
先序打印 根左右 preorderprint()
顺序打印(中序) 左根右 orderprint()
后续打印 左右根 postorderprint()
有效元素个数 getsize()

增:
1.new一个新的节点
2.判断该树的根节点是否为空 为空就 root = newnode
3.不为空就进入递归Adds(Node node,Node newnode)
4传入root节点和newnode节点Adds(root,newnode)
5.每次递归判断 (大的放右孩子 小的放左孩子)
如果newnode节点的值小于node节点
如果node节点的左孩子为空 就直接让newnode节点填补到这个空节点上、
不为空的话 再次递归 传入Adds(node.getLift(),newnode)
如果newnode节点的值大于node节点
跟左节点差不多一样的操作
查:
递归 大于根的值往右孩子找
小于根的值往左孩子找
等于的话 就找到了
删:
二叉查找树的删除分三种情况
1.p为叶子节点 没有左右孩子 直接删除 让父亲节点的下一个为空
2.p为单支节点 有左孩子 或者右孩子 的其中一个
3.p的左子树和右子树均不为空 那就找到他的右孩子的最左的一个孩子

在这里插入图片描述
代码可能有点多

package two;

import java.util.concurrent.ArrayBlockingQueue;

/*
 * 构建二叉搜索树
 */
public class Tree {
    private Node root; //根节点
    private int size=0; //有效元素个数
    private ArrayBlockingQueue<Node> queue;  //定义一个队列
    private void Adds(Node node,Node newnode)//递归建树
    {
    	   if(newnode.getItem()<node.getItem())  //如果newnode节点的值小于node节点
    		{
    			if(node.getLift()!=null)   //并且左孩子不为空
    			{
    				Adds(node.getLift(),newnode);
    			}
    			else  //否则  把新节点添加到空节点上
    			{
    				size++;  //元素个数加1
    				newnode.setParent(node);  //newnode节点的父亲是 node节点
    				node.setLift(newnode);  //node节点的左孩子 是newnode节点
    				System.out.println(newnode.getItem()+"添加成功 父亲节点是"+newnode.getParent().getItem());
    				
    			}
    		}
    		if(newnode.getItem()>node.getItem())  //如果newnode节点的值大于node节点
    		{
    			if(node.getRight()!=null)   //并且右孩子不为空
    			{
    				Adds(node.getRight(),newnode);
    			}
    			else  //否则  把newnode节点添加到空节点上
    			{
    				size++;  //元素个数加1
    				newnode.setParent(node);  //newnode节点的父亲是 node节点
    				node.setRight(newnode);  //node节点的右孩子 是newnode节点
    				System.out.println(newnode.getItem()+"添加成功 父亲节点是"+newnode.getParent().getItem());
    			}
    		}
    }
    private Node search(Node node,int item)  //递归查找
    {
    		if(item < node.getItem())  //小于node节点的值
    		{
    			if(node.getLift()==null)
    			{
    				return null;
    			}
    			return search(node.getLift(),item);   //往左孩子这边找
    			
    		}
    		else if(item > node.getItem()) //大于node节点的值
    		{
    			 if(node.getRight()==null)
    			{
    				return null;
    			}
    			return search(node.getRight(),item);   //往右孩子这边找
    		}
    		else
    		{
    			return node;  //返回该node节点
    		}
			
    }
    private void ordercount(Node node)   //递归顺序打印 左根右
    {
    	if(node!=null)
    	{
    		ordercount(node.getLift());
    	    System.out.print(node.getItem()+" ");
    	    ordercount(node.getRight());
    	}
    }
    private void preordercount(Node node)   //递归先序打印 根左右
    {
    		if(node!=null)
        	{
    			System.out.print(node.getItem()+" ");
    			preordercount(node.getLift());
    			preordercount(node.getRight());
        	    
        	}
    	    
    	
    }
    private void postordercount(Node node)   //递归后序打印 左右根
    {
    	if(node!=null)
    	{
    		postordercount(node.getLift());
    		postordercount(node.getRight());
    	    System.out.print(node.getItem()+" ");
    	}
    }
    private void yezijiedian(Node parent,int item)  //叶子节点的删除
    {
    	//看是父亲节点的左孩子等于该值 还是右孩子等于该值
   	 if(parent.getLift()!=null)   //左孩子不等于null
   	 {
   		
   		 if(parent.getLift().getItem()==item) //左孩子等于item
   		 {
   			 parent.getLift().setParent(null); //先让该节点的父亲为空
   		     parent.setLift(null);   //让父亲节点的左孩子为空
   		     
   		 }
   	 }
   	 else //右孩子等于
   	 {
   		
   		 parent.getRight().setParent(null); 
   		 parent.setRight(null);
   	 }
   	 
    }
    private void danzhijieidan(Node parent,Node node)  //单枝节点的删除
    {
    	if(parent.getLift()!=null && parent.getLift().getItem()==node.getItem())   //左孩子等于
      	 {
    		if(node.getLift()==null)  //如果左孩子为空  右节点不为空
      	     {
      		    parent.setLift(node.getRight());  //让父亲节点的左孩子直接连 node的右节点
      		    node.setParent(null); //让node节点的父亲节点为空
      		    node.getRight().setParent(parent);//
      		    node.setRight(null);
      	     }
      	    else  //右孩子为空
      	     {
      	    	parent.setLift(node.getLift());  //让父亲节点的左孩子直接连 node的左节点
       		    node.setParent(null); //让node节点的父亲节点为空
       		    node.getLift().setParent(parent);
       		    node.setLift(null);
      	     }
      	 }
      	 else //右孩子等于
      	 {
      		if(node.getLift()==null)  //如果左孩子为空  右节点不为空
     	     {
     		    parent.setRight(node.getRight());  //让父亲节点的右孩子直接连 node的右节点
     		    node.setParent(null); //让node节点的父亲节点为空
     		    node.getRight().setParent(parent);
     		    node.setRight(null);
     	     }
     	    else  //右孩子为空
     	     {
     	    	parent.setRight(node.getLift());  //让父亲节点的右孩子直接连 node的左节点
      		    node.setParent(null); //让node节点的父亲节点为空
      		    node.getLift().setParent(parent);
      		    node.setLift(null);
     	     }
      	 }
    	
    }
    private Node zuizuozisun(Node node)   //找到node的最左子孙
    {
    	if(node.getLift()==null)  //如果他左孩子为空
    	{
    		return node;  //说明他就是最左子树
    	}
    	else //否则
    	{
    		return zuizuozisun(node.getLift());  //继续递归  再传入他的左孩子
    	}
    }
  
    public void add(int item)//添加元素
    {
    	Node newnode = new Node(null,null,null,item);//先创建一个新的节点
    	if(root==null)
    	{
    		root = newnode;
    		System.out.println(newnode.getItem()+"添加成功 根节点");
    	}
    	else
    	{
    		Adds(root,newnode);
    	}
    }
    public void find(int item)  //查找
    {
    	Node node = search(root,item);
    	if(node==null)  //如果返回值为空 说明没有找到
    	{
    		System.out.println("没找到");
    	}
    	else
    	{
    		System.out.println("找到了");
    	}
    }
    public void delect(int item) //删除节点
    {
    	Node node = search(root,item);  //通过递归先找到该值的节点 node
    	if(node==null)  //如果返回值为空 说明没有找到
    	{
    		System.out.println("此树没有存储该值,无法删除");
    	}
    	else  //找到了
    	{
    		
    		 Node parent = node.getParent();   //node节点的 父亲节点
    		//1.node为叶子节点         没有左右孩子    直接删除  让父亲节点的下一个为空
    	     if(node.getLift()==null && node.getRight()==null)
    	     {
    	    	 yezijiedian(parent,item);
    	     }
    	     //2.node的左子树和右子树均不为空  那就找到他的右孩子的最左的一个孩子
    	     else if(node.getLift()!=null && node.getRight()!=null)
    	     {
    	    	 //先到找node节点的最左子孙   
    	    	 Node zs = zuizuozisun(node.getRight()); //zs为node的最左子孙
    	    	 System.out.println(zs.getItem());
    	    	 //然后将node的值  替换为最左子孙的值
    	    	 node.setItem(zs.getItem());
    	    	 //最后再判断zs 是单枝还是叶子
    	    	 if(zs.getRight()==null)  //如果右孩子为空  说明是叶子节点
    	    	 {
    	    		 yezijiedian(zs.getParent(),zs.getItem());
    	    	 }
    	    	 else  //zs为单枝节点
    	    	 {
    	    		 danzhijieidan(zs.getParent(),zs);
    	    	 }
    	    	 //删除zs完成
    	     }
             //3.node为单支节点        有左孩子 或者右孩子 的其中一个  
    	     else
    	     {
    	    	 danzhijieidan(parent,node);
    	     }
    	}
    }
    public int getsize() //获取有效元素个数
    {
    	return this.size;
    }
    public void arrangement()  //层次遍历
    {
    	queue = new ArrayBlockingQueue<Node>(5);//给5个足够了
    	queue.offer(root);//先把根节点丢进去
    	while(queue.peek()!=null)  //如果队列不为空、
    	{
    		Node node = queue.poll();  //得到队首元素 
    		System.out.print(node.getItem()+" "); //然后打印
    		if(node.getLift()!=null)
    		{
    			 queue.offer(node.getLift());//再把它的左节点丢进去
    		}
    	    if(node.getRight()!=null)
    	    {
    	    	queue.offer(node.getRight());//再把它的右节点丢进去
    	    }
    	    
    	}
    	//直到结束  打印就完成了
    	System.out.println();
    }
    public void preorderprint()  //先序遍历  根左右
    {
    	preordercount(root);
    	System.out.println();
    }
    public void orderprint()//按顺序打印
    {
    	ordercount(root);
    	System.out.println();
    }
    public void postorderprint() //后序遍历
    {
    	postordercount(root);
    	System.out.println();
    }
   
}

如果有错请留言,谢谢哈

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值