基于二叉查找树的符号表

1.数据表示

我们嵌套定义一个私有Node类来表示二叉查找树上的一个结点。每个结点都含有一个键,一个值,一条左链接,一条右链接。左链接指向一棵由小于该结点的所有键组成的二叉查找树,右链接指向一棵由大于该结点的所有键组成的二叉查找树。变量N给出以该结点为根的子树的结点总数。这样有

size(x) = size(x.left) + size(x.right) + 1


2.查找

在符号表中查找一个键有两种结果:命中和未命中。在二叉查找树中查找一个键:

-- 如果树为空,查找未命中

--如果查找的键与根节点的键相等,返回根节点的值

--如果查找的键比根节点的键大,则查找根节点的右子树

--否则,查找根节点的左子树

	//根据键找对应的值,如果找不到返回Null
	public Value get(Key key) {
		return get(root,key);
	}
	private Value get(Node x, Key key) {
		while (x != null) {
			int cmp = key.compareTo(x.key);
			if (cmp > 0) x = x.right;
			else if (cmp < 0) x = x.left;
			else return x.val;
		}
		return null;
	}

3.插入

插入的逻辑:

    --如果树为空,创建对于键值对的新结点

--如果插入的键小于根结点的键,继续向左子树中插入该键

--否则在右子树中插入该键

//向树中插入结点
	public void put(Key key, Value val) {
		root = put(root, key, val);
	}
	private Node put(Node x, Key key, Value val) {
		if (x == null) return new Node(key, val, 1);
		int cmp = key.compareTo(x.key);
		if (cmp > 0) x.right = put(x.right, key, val);
		else if (cmp < 0) x.left = put(x.left, key, val);
		else x.val = val;
		x.N = size(x.right) + size(x.left) + 1;
		return x;
	}


4.有序性相关

最小键

--如果根结点左子树为空,那么根结点为最小键

--如果左链接非空,那么最小键为左子树的最小键

	//找到最小的键
	public Key min() {
		return min(root);
	}
	private Key min(Node x) {
		if (x == null)return null;
		while (x.left != null) {
			x = x.left;
		}
		return x.key;
	}

 最大键与最小键类似,不再赘述。


5.删除操作

二叉查找树中对较难实现的方法就是delete()方法。我们先考虑deleteMin()方法。对于deleteMin(),我们要不断深入根结点的左子树 

直至遇到一个空连接,然后将指向该结点的链接指向该结点的右子树。

                                               


public void deleteMin() {
		root = deleteMin(root);
	}
	private Node deleteMin(Node x) {
		if (x == null) return null;
		if (x.left == null) return x.right;
		x.left = deleteMin(x.left);
		x.N = size(x.left) + size(x.right) + 1;
		return x;
	}

deleteMax()与此类似,不再赘述


接下来我们考虑delete()方法,我们用四个步骤完成将x替换为它的后继结点。

--将指向即将被删除的结点的链接保存为t

--将x指向他的后继结点min(t.right)

--将x的右链接指向deleteMin(t.right),也就是在删除后所有结点都大于x.key的子二叉查找树

--将x的左链接设为t.left


	public void delete(Key key) {
		root = delete(root,key);
	}
	private Node delete(Node x, Key key) {
		if (x == null) return null;
		int cmp = key.compareTo(x.key);
		if (cmp < 0) x.left = delete(x.left, key);
		else if (cmp > 0) x.right = delete(x.right, key);
		else {
			if (x.right == null) return x.left;
			if (x.left == null) return x.right;
			Node t = x;
			x = min(t.right);
			x.right = deleteMin(t.right);
			x.left = t.left;
		}
		x.N = size(x.left) + size(x.right) + 1;
		return x;
	}

最后附上完整代码:

package com.tong.Test;

public class BST<Key extends Comparable<Key> , Value> {
	private Node root;
	private class Node {
		private Key key;
		private Value val;
		private Node left, right;
		private int N;
		public Node(Key key, Value val, int n) {
			this.key = key; this.val = val; this.N = n;
		}
	}
	//返回二叉搜索树的结点数
	public int size() {
		return size(root);
	}
	private int size(Node x) {
		if (x == null) return 0;
		return x.N;
	}
	//根据键找对应的值,如果找不到返回Null
	public Value get(Key key) {
		return get(root,key);
	}
	private Value get(Node x, Key key) {
		while (x != null) {
			int cmp = key.compareTo(x.key);
			if (cmp > 0) x = x.right;
			else if (cmp < 0) x = x.left;
			else return x.val;
		}
		return null;
	}
	//向树中插入结点
	public void put(Key key, Value val) {
		root = put(root, key, val);
	}
	private Node put(Node x, Key key, Value val) {
		if (x == null) return new Node(key, val, 1);
		int cmp = key.compareTo(x.key);
		if (cmp > 0) x.right = put(x.right, key, val);
		else if (cmp < 0) x.left = put(x.left, key, val);
		else x.val = val;
		x.N = size(x.right) + size(x.left) + 1;
		return x;
	}
	//找到最小的键
	public Key min() {
		return min(root).key;
	}
	private Node min(Node x) {
		if (x == null)return null;
		while (x.left != null) {
			x = x.left;
		}
		return x;
	}

	public void deleteMin() {
		root = deleteMin(root);
	}
	private Node deleteMin(Node x) {
		if (x == null) return null;
		if (x.left == null) return x.right;
		x.left = deleteMin(x.left);
		x.N = size(x.left) + size(x.right) + 1;
		return x;
	}
	
	public void delete(Key key) {
		root = delete(root,key);
	}
	private Node delete(Node x, Key key) {
		if (x == null) return null;
		int cmp = key.compareTo(x.key);
		if (cmp < 0) x.left = delete(x.left, key);
		else if (cmp > 0) x.right = delete(x.right, key);
		else {
			if (x.right == null) return x.left;
			if (x.left == null) return x.right;
			Node t = x;
			x = min(t.right);
			x.right = deleteMin(t.right);
			x.left = t.left;
		}
		x.N = size(x.left) + size(x.right) + 1;
		return x;
	}
	public static void main(String[] args) {
		BST<Integer, String> table = new BST<>();
		table.put(3, "三");
		table.put(2, "二");
		table.put(1, "一");
		table.put(4, "四");
		table.put(6, "五");
		System.out.println(table.get(5));
		System.out.println(table.min());
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值