算法自学笔记:二分查找树插入和比较操作实现(1)

本文包括二分查找树基本插入和查找操作
API:

put(Key key, Value value) 插入一个键-值对
get(Key key) 根据一个键返回对应值,如不存在返回null
min() 返回最小键
max() 返回最大键
ceiling(Key k) 返回大于k的最小键
floor(Key k) 返回小于k的最大键

二分查找树作为递归数据结构。尽管也可以使用循环进行查找,最好使用递归方法进行查找。在这里我们使用递归函数两个基本构成:基线条件,状态转移方程,进行说明

1 put

// put a key-value pair into the tree
	public void put (Key key, Value value) {
		root = insert(key, value, root);
	}
	
	private Node insert(Key key, Value value, Node x) {
		if (x == null) {
			return new Node(key, value, 1);
		}
		if (x.key.compareTo(key) > 0) {	// smaller, move to the left
			x.left =  insert(key, value, x.left);
		} else if (x.key.compareTo(key) < 0) {	// larger, move to the right
			x.right =  insert(key, value, x.right);
		} else {
			x.value = value;	// key existed, replace it
		}
		x.count = size(x.left) + size(x.right) + 1;
		return x;
	}
	

基线条件:x == null, 该索引处没有对象,因而到达了树底端,插入新元素
状态转移方程:如果要插入的键小于当前位置键,插到当前键左子树里,如果大于当前键插到右子树。如果相等则替换值

注:count值用于遍历操作,目前先不涉及,在后续会讲到

2 get

	// find a certain value according to its key
	public Value get(Key key) {
		Node result = get(key, root);
		if (result == null) {
			return null;
		}
		return result.value;
	}
	
	private Node get(Key key, Node x) {
		if (x == null) {	// no this key
			return null;
		}
		
		if (x.key.compareTo(key) > 0) {	// smaller, move to the left
			return get(key, x.left);
		} else if (x.key.compareTo(key) < 0) {	// larger, move to the right
			return get(key, x.right);
		} else {
			return x;	// find it
		}
	}

基线条件:如果找到对应键,返回该节点。如果该节点为null,说明搜索到树底端还未找到,返回null
状态转移方程:如果当前键大于目标键,搜索该节点左子树,如果当前键小于目标键,搜索该节点右子树

3 min max

// find the smallest key
	public Key min() {
		return min(root).key;
	}
	
	private Node min(Node x) {
		if (x.left == null) {
			return x;
		} else {
			return min(x.left);
		}
	}
	
	
	// find the largest key
	public Key max() {
		return max(root).key;
	}
	
	private Node max(Node x) {
		if (x.right == null) {
			return x;
		} else {
			return max(x.right);
		}
	}

min:
基线条件:如果该节点左子节点为null,说明该节点处于最左端,对应最小值。返回该节点
状态转移方程:如果左子节点存在,移到左子节点

max和min原理相同,只是把左移改为右移

4 floor/ceiling

// find the largest key less or equals k
	public Key floor (Key k) {
		Node x = floor(root, k);
		if (x == null) {
			return null;
		} else {
			return x.key;
		}
	}
	
	private Node floor(Node x, Key k) {
		if (x == null) {
			return null;
		} 
		int cmp = k.compareTo(x.key);
		if (cmp == 0) {	// the same key, return it
			return x;
		} else if (cmp < 0) {
			return floor(x.left, k);	// smaller, move to the left
		} else {	// larger, attempt to move to the right
			Node t = floor(x.right, k);
			if (t != null) {
				return t;
			} else {
				return x;
			}
		}
	}
	
	
	// find the smallest key larger or equals k
	public Key ceiling (Key k) {
		Node x = ceiling(root, k);
		if (x == null ) {
			return null;
		}
		return x.key;
	}
	
		
	private Node ceiling(Node x, Key k) {
		if (x == null) {
			return null;
		}
		int cmp = k.compareTo(x.key);
		if (cmp == 0) {	// the exact value
			return x;
		} else if (cmp > 0) {
			return ceiling(x.right, k);	// larger, move to the left
		} else {	// smaller, attempt to move to the right
			Node t = ceiling(x.left, k);
			if (t != null) {
				return t;
			} else {
				return x;
			}
		}
	}

floor:
基线条件:
如果该节点为null,代表达到树底,返回null。
状态转移方程:
如果该节点键大于k,直接左移
如果该节点键小于k,此节点可能为最大值,但也有可能树上存在该键和k之间一个值。此时对右子节点调用floor,如果可以找到符合条件的值返回该值,如果找不到(返回null),返回当前节点

ceiling与floor同理

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值