二叉树的java实现

最近在复习数据结构,整理了一下,用java语言来实现一下。其实,思想是不变的,只是每种语言的特性略有不同。

本篇博客包括二叉树的:

(1)插入

(2)删除

(3)查找

(4)遍历

详细注释已经嵌入到代码当中了。

1.节点类型:

//树的节点类
class Node{
	//没有用private修饰,方便修改
	int data;   // 数据域
	Node leftChild;  // 左孩子
	Node rightChild;  // 右孩子
	
	public Node(int data) {
		this.data=data;
		leftChild=null;
		rightChild=null;
	}
}

 

2.插入操作:

//插入一个节点
	public boolean insert(int data) {
		Node newNode =new Node(data);
		//如果是空树,则新的节点就是根节点
		if(root==null) {
			root=newNode;
			return true;
		}
		
		Node current=root; //当前节点
		Node parent=null;  //记录当前节点的父节点
		while(current!=null) {
			parent=current;
			//如果data大于当前节点值,则在右子树插入
			if(data>current.data) {
				current=current.rightChild;
				//如果当前节点的右节点为空,则插入到右节点
				if(current==null) {
					parent.rightChild=newNode;
					return true;
				}
			}
			//如果data小于当前节点值,则在左子树插入
			else if(data<current.data){
				current=current.leftChild;
				//如果当前节点的左节点为空,则插入到左节点
				if(current==null) {
					parent.leftChild=newNode;
					return true;
				}
			}
			//data==current.data,重复的值不能插入
			else {
				return false;
			}
		}
		return false;
	}

 

3.删除操作,比较复杂,分三种情况:

(1)删除的是叶子节点

(2)删除的节点只有一个孩子

(3)有两个孩子的节点

首先是要找到要删除的节点及其父节点:

//删除分三种情况:1.删除的是叶子节点 2.删除的节点只有一个孩子 3.有两个孩子的节点
	public boolean delete(int key) {
		Node delNode=root;          //要删除的节点
		boolean isLeftChild=false;  //要删除的节点是否在左子树上
		Node parent=null;           //要删除节点的父节点
		//找到要删除的节点
		while(delNode!=null) {
			//如果key大于当前节点值,则到右子树查找
			if(key>delNode.data) {
				parent=delNode;
				delNode=delNode.rightChild;
				isLeftChild=false;
			}
			//如果key小于当前节点值,则到左子树查找
			else if(key<delNode.data) {
				parent=delNode;
				delNode=delNode.leftChild;
				isLeftChild=true;
			}
			//key==current.data,找到了就停止搜索
			else {
				break;
			}
		}
		//要删除的节点不存在
		if(delNode==null) {
			return false;
		}
		System.out.println("删除的节点"+delNode.data+"父节点"+parent.data);
		//如果是叶子节点
	    if(delNode.leftChild==null&&delNode.rightChild==null) {
			//如果这棵树只有一个根节点
	    	if(delNode==root) {
	    		root=null;
	    	}else {
	    		if(isLeftChild) {
	    			parent.leftChild=null;
	    		}else {
	    			parent.rightChild=null;
	    		}
	    	}
	    	return true;
		}
		//如果删除的节点只有左孩子
		else if(delNode.leftChild!=null&&delNode.rightChild==null) {
			//删除的根节点
			if(delNode==root) {
				root=delNode.leftChild;
			}else {
				if(isLeftChild) {
					parent.leftChild=delNode.leftChild;
				}else {
					parent.rightChild=delNode.leftChild;
				}
			}
			return true;
		}
		//如果删除的节点只有右孩子
		else if(delNode.leftChild==null&&delNode.rightChild!=null) {
			//删除的根节点
			if(delNode==root) {
				root=delNode.rightChild;
			}else {
				if(isLeftChild) {
					parent.leftChild=delNode.rightChild;
				}else {
					parent.rightChild=delNode.rightChild;
				}
			}
			return true;
		}
	    //有两个节点delNode.leftChild!=null&&delNode.rightChild!=null
		else {
			//找删除节点的替换节点有两种选择:
			//1.该删除节点左子树的最大值 ,它一定没有右孩子
			//2.该删除节点右子树的最小值,它一定没有左孩子
			//这样,就把问题转化只有一个孩子的节点的删除了
			//这里使用第二种方法
			Node rightMin=delNode.rightChild;
			parent=delNode;
			while(rightMin.leftChild!=null) {
				parent=rightMin;
				rightMin=rightMin.leftChild;
			}
			delNode.data=rightMin.data;
			//如果右孩子就是要删除节点的最小值
			//这里的意思是要删除的节点右边只有一个节点
			if(parent==delNode) {
				parent.rightChild=null;
			}
			//如果替换节点存在右孩子
			if(rightMin.rightChild!=null) {
				parent.leftChild=rightMin.rightChild;
			}
			return true;
		}
	}

 

4.查找:根据关键字查找

//根据关键字查找
	public Node find(int key) {
		Node current=root;  //记录当前节点
		while(current!=null) {
			//如果key大于当前节点值,则到右子树查找
			if(key>current.data) {
				current=current.rightChild;
			}
			//如果key小于当前节点值,则到左子树查找
			else if(key<current.data) {
				current=current.leftChild;
			}
			//key==current.data,找到了就停止搜索
			else {
				break;
			}
		}
		//如果返回的是null表示没有找到,不然就是找到了
		return current;
	}

 

5.根据给定的根节点,查找最小值:二叉树的最小值,最小值就是最左边的,并且没有左孩子的

	//查找以Root为根的二叉树的最小值,最小值就是最左边的,并且没有左孩子的
	public Node findMin(Node Root) {
		Node current=Root;
		while(current.leftChild!=null) {
			current=current.leftChild;
		}
		return current;
	}

 

6. 根据给定的根节点,查找最大值:二叉树的最大值,最大值就是最右边的,并且没有右孩子的

	//查找以Root为根的二叉树的最大值,最大值就是最右边的,并且没有右孩子的
	public Node findMax(Node Root) {
		Node current=Root;
		while(current.rightChild!=null) {
			current=current.rightChild;
		}
		return current;
	}

 

7.遍历二叉树:

(1)递归遍历,包括先序遍历、中序遍历和后序遍历

//先序遍历
	public void preOrder(Node Root) {
		//如果不是空树
		if(Root!=null) {
			//先访问根节点
			System.out.print(Root.data+" ");
			//递归中序遍历左子树
			preOrder(Root.leftChild);
		    //递归中序遍历右子树
			preOrder(Root.rightChild);
		}
	}
	
	//中序遍历
	public void midOrder(Node Root) {
		//如果不是空树
		if(Root!=null) {
			//递归中序遍历左子树
			midOrder(Root.leftChild);
			//再访问根节点
			System.out.print(Root.data+" ");
		    //递归中序遍历右子树
			midOrder(Root.rightChild);
		}
	}
	
	//后序遍历
	public void postOrder(Node Root) {
		//如果不是空树
		if(Root!=null) {
			//递归中序遍历左子树
			postOrder(Root.leftChild);
		    //递归中序遍历右子树
			postOrder(Root.rightChild);
			//最后访问根节点
			System.out.print(Root.data+" ");
		}
	}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值