二叉查找树

具有以下特征的可以被定义为二叉查找树(Binary Search Tree)

(1)若左子树不空,则左子树上所有结点的值均小于它的根节点 的值;

(2)若右子树不空,则右子树上所有结点的值均大于或等于它的根结点的值;

(3)中序遍历可以让节点有序


二叉查找树适用于范围查找,这个才是我们使用二叉树的最终目的,既然是范围查找,我们就知道了一个”min“和”max“,其实实现起来也很简单,

第一步:我们要在树中找到min元素,当然min元素可能不存在,但是我们可以找到min的上界,耗费时间为O(logn)。

第二步:从min开始我们中序遍历寻找max的下界。耗费时间为m。m也就是匹配到的个数。


二叉查找树的插入:

1.先执行查找,找到要插入元素位置的父节点

2.判断其是父节点的左叶子/右叶子,被插入节点做为叶子节点插入

二叉查找树的删除:

1.根据给定的key值找到要被删除的节点p,判断是否是叶子节点(是则直接删除)

2.判断其是否有左孩子,如果有则找到左孩子的最右节点r,将r的(key,value)数据覆盖p的(key,value)数据,没有则直接使用右孩子覆盖p

3.判断r是否等于p的左孩子节点,是则将p的左孩子指向r的左孩子,不是则将r的父节点的右孩子指向r(左儿子的最右节点)的左孩子

下面是一个查找二叉树的实现:

package test;

import java.util.Random;

public class BinaryTreeTest {
	private static class BinaryNode implements Comparable<BinaryNode> {
		// 节点
		private String key;
		// 数量
		private int total;
		// 左子节点
		private BinaryNode leftNode;
		// 右子节点
		private BinaryNode rightNode;
		// 父节点
		private BinaryNode parentNode;

		public BinaryNode getParentNode() {
			return parentNode;
		}

		public void setParentNode(BinaryNode parentNode) {
			this.parentNode = parentNode;
		}

		public BinaryNode getLeftNode() {
			return leftNode;
		}

		public void setLeftNode(BinaryNode leftNode) {
			leftNode.setParentNode(this);
			this.leftNode = leftNode;
		}

		public BinaryNode getRightNode() {
			return rightNode;
		}

		public void setRightNode(BinaryNode rightNode) {
			rightNode.setParentNode(this);
			this.rightNode = rightNode;
		}

		public BinaryNode(String key) {
			this.key = key;
			total = 1;
		}

		public int compareTo(BinaryNode o) {
			int result = (o.getKey()).compareTo(key);
			if(result == 0){
				return 0;
			}else if(result < 0){
				return -1;
			}else if(result > 0){
				return 1;
			}
			return 0;
		}
		
		public int compareTo(String k) {
			int result = k.compareTo(key);
			if(result == 0){
				return 0;
			}else if(result > 0){
				return -1;
			}else if(result < 0){
				return 1;
			}
			return 0;
		}

		public void increament() {
			total++;
		}

		public String getKey() {
			return this.key;
		}
		
		public void setKey(String key) {
			this.key = key;
		}
	}

	public static void addChildNode(BinaryNode startNode,BinaryNode addNode){
		int compare = addNode.compareTo(startNode);
		switch (compare) {
		//相等,则当前节点数量+1
		case 0:
			startNode.increament();
			break;
		//大于则找到其右子节点,并继续执行添加过程
		case 1:
			BinaryNode rightNode = startNode.getRightNode();
			if(rightNode == null){
				startNode.setRightNode(addNode);
			}else{
				addChildNode(rightNode, addNode);
			}
			break;
		//小于则找到其左子节点继续执行添加过程
		case -1:
			BinaryNode leftNode = startNode.getLeftNode();
			if(leftNode == null){
				startNode.setLeftNode(addNode);
			}else{
				addChildNode(leftNode, addNode);
			}
			break;
		default:
			break;
		}
	}
	
	public static BinaryNode sercherChildNode(BinaryNode startNode,String sercherKey){
		int compare = startNode.compareTo(sercherKey);
		switch (compare) {
		//相等,则当前节点数量+1
		case 0:
			return startNode;
		//大于则找到其右子节点,并继续执行添加过程
		case 1:
			return sercherChildNode(startNode.getRightNode(), sercherKey);
		//小于则找到其左子节点继续执行添加过程
		case -1:
			return sercherChildNode(startNode.getLeftNode(), sercherKey);
		}
		return null;
	}
	
	/**
	 * 	1.若p有左子树,找到其左子树的最右边的结点r,用该结点r来替代p,把r的左孩子
	 *	作为r的父亲的右孩子。
	 *	2.若p没有左子树,直接用p的右孩子取代它。
	 */
	public static BinaryNode deleteChildNode(BinaryNode startNode,String key){
		BinaryNode node = sercherChildNode(startNode, key);
		if(node != null){
			BinaryNode left = node.getLeftNode();
			if(left != null){
				//查找最右的节点
				BinaryNode pre = left;
				while(pre.getRightNode()!=null){
					pre = pre.getRightNode();
				}
				node.setKey(pre.getKey());
				//如果pre是node的左子树,则把node的左子树设置成pre的左子树
				if(pre.compareTo(left) == 0){
					node.setLeftNode(pre.getLeftNode());
				}else{
					//把pre节点的父节点的右子树 设置成pre的左子树
					pre.getParentNode().setRightNode(pre.getLeftNode());
				}
			}else{
				//左子树为空,则直接设置node为右子树
				node = node.getRightNode();
			}
		}
		return null;
	}
	
	
	//随机生成一个1-10长度的字符串
	public static String genStr() {
		StringBuffer buffer = new StringBuffer("");
		Random random = new Random();
		int strLength = random.nextInt(10);
		strLength = strLength==0?1:strLength;
		for(int i =0;i<strLength;i++){
			char r = (char)(random.nextInt(82)+40);
			buffer.append(r);
		}
		return buffer.toString();
	}
}






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值