Java实现排序二叉树的操作

在写博客之前,一定要明确一个问题,就是Java方法传值的问题,如果是基本类型和String类型,调用了某个方法,在方法内部对其值进行了更改,但是方法调用完了其值保持不变,这是因为Java在传值的时候对这些类型的变量copy了一个副本。对于对象的引用也是如此,比喻a=new A();方法中更改a指向:a=new B();方法执行完毕a仍然指向A类型对象。

    排序二叉树:

二叉排序树或者是一棵空树,或者是具有下列性质的 二叉树
(1)若左子树不空,则左子树上所有结点的值均小于它的 根结点的值;
(2)若右子树不空,则右子树上所有结点的值均大于或 等于它的根结点的值;
(3)左、右子树也分别为二叉排序树;
(4)没有键值相等的节点。
插入和创建过程比较简单,我就不说了,这里讨论下删除操作:
在二叉排序树删去一个结点,分三种情况讨论:
  1. 若*p结点为叶子结点,即PL(左子树)和PR(右子树)均为空树。由于删去叶子结点不破坏整棵树的结构,则可以直接删除此子结点。
  2. 若*p结点只有左子树PL或右子树PR,此时只要令PL或PR直接成为其双亲结点*f的左子树(当*p是左子树)或右子树(当*p是右子树)即可,作此修改也不破坏二叉排序树的特性。
  3. 若*p结点的左子树和右子树均不空。在删去*p之后,为保持其它元素之间的相对位置不变,可按中序遍历保持有序进行调整,可以有两种做法:
    其一是令*p的左子树为*f的左/右(依*p是*f的左子树还是右子树而定)子树,*s为*p左子树的最右下的结点,而*p的右子树为*s的右子树;
    其二是令*p的直接前驱(或直接后继)替代*p,然后再从二叉排序树中删去它的直接前驱(或直接后继)-即让*f的左子树(如果有的话)成为*p左子树的最左下结点(如果有的话),再让*f成为*p的左右结点的父结点。
这里对于情况3代码使用做法2:

   下面是Java操作排序二叉树,注意传值问题:

package data_structure;

public class BinarySortTree {

	private BST root;
	static class BST{
		int data;
		BST lchild;
		BST rchild;
		
		public BST(){}
		
		public BST(int data,BST lchild,BST rchild) {
			this.data=data;
			this.lchild=lchild;
			this.rchild=rchild;
		}
	}
	
	public void createBST(int []d){
		for(int i:d)
			insertBST(i);
	}
	
	public  void insertBST(int d){
		BST p=this.root,parent=this.root;
		if(p==null){
			this.root=new BST(d,null,null);
		    return;
		}
		while(p!=null){
			parent=p;
			if(d<p.data){
				p=p.lchild;
			}
			else if(d>p.data){
				p=p.rchild;
			}
		}
		if(d<parent.data){
			parent.lchild=new BST(d,null,null);
		}
		else{
			parent.rchild=new BST(d,null,null);
		}
		System.out.println("insert "+d+"  over");
	}
	
	public boolean searchBST(int key){
		BST p=root;
		if(p==null)
			return false;
		while(p!=null){
			if(key==p.data)
				return true;
			else if(key<p.data)
				p=p.lchild;
			else if(key>p.data)
				p=p.rchild;
		}
		return false;
	}
	
	@SuppressWarnings("unused")
	public void deleteBST(int key){
		BST p=this.root,parent=null;
		if(p!=null){
			//开始的时候想着调用方法findKey(key,p,parent)寻找p和parent的值,但是由于传值问题,方法调用完毕P和parent值不变,舍弃调用方法
			//parent = findKey(key,p,parent);
			//寻找待删除的节点和其父节点
			while(p!=null&&p.data!=key){
				parent=p;
				if(p.data>key){
					p=p.lchild;
				}
				else{
					p=p.rchild;
				}
			}
			//p==null 表示没有找到
			if(p==null){
				System.out.println("不存在待删除节点");
				return;
			}
			//System.out.println("P:"+p.data+"  parent:"+parent.data);
			//下面对树做删除操作,分成三种情况
			//没有左孩子和右孩子
			if(p.lchild==null&&p.rchild==null){
				if(parent==null){
					root=null;
				}
				else{
					if(parent.data>p.data)
						parent.lchild=null;
					if(parent.data<p.data)
						parent.rchild=null;
				}
			}
			//有左孩子没有右孩子
			if(p.lchild!=null&&p.rchild==null){
				if(p==root){
					root=p.lchild;
				}
				else if(parent.data>p.data){
					parent.lchild=p.lchild;
				}
				else if(parent.data<p.data){
					parent.rchild=p.lchild;
				}
			}
			//没有左孩子只有右孩子
			if(p.lchild==null&&p.rchild!=null){
				if(p==root){
					root=p.rchild;
				}
				else if(parent.data>p.data){
					parent.lchild=p.rchild;
				}
				else if(parent.data<p.data){
					parent.rchild=p.rchild;
				}
			}
			//既有左孩子又有右孩子
			if(p.lchild!=null&&p.rchild!=null){
				BST pre=p,s=p.rchild;
				while(s.lchild!=null){
					pre=s;
					s=s.lchild;
				}
				p.data=s.data;
				if(pre==p){
					p.rchild=s.rchild;
				}
				else{
					pre.lchild=s.rchild;
				}
			}
		}
	}
	
	public BST findKey(int key,BST p,BST parent){
		while(p!=null&&p.data!=key){
			parent=p;
			if(p.data>key){
				p=p.lchild;
			}
			else{
				p=p.rchild;
			}
		}
		System.out.println("P:"+p.data+"  parent:"+parent.data);
		return parent;
	}
	
	public void printBST(BST p){
		if(p==null)
			return ;
		printBST(p.lchild);
		System.out.print(p.data+"  ");
		printBST(p.rchild);
	}
	
	public static void main(String []args){
		BinarySortTree bTree=new BinarySortTree();
		int []d={2,6,8,4,12,45,25,14,28};
		bTree.createBST(d);
		bTree.printBST(bTree.root);
		if(bTree.searchBST(45))
			System.out.println("\nfind it!~~~");
		bTree.deleteBST(2);
		bTree.printBST(bTree.root);
	}
	
	
	
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值