Algorithm self-study notes: binary search tree search operation

Posted by magie on Fri, 04 Feb 2022 08:56:12 +0100

In this paper, we continue to build a binary tree, and the rest of the methods

API:

size() returns the total number of nodes
select(int k) returns the key ranked K in the tree, that is, K keys are less than it
Rank (key) returns the ranking of a given key, that is, the number less than the key in the tree

To implement these methods, we first need to count each node and find out the number of child nodes of each node (including itself).
We add count as a counter in the Node construction method and update the count of each Node in the put method

	private class Node {
		private Key key;
		private Value value;
		private Node left;
		private Node right;
		private int count;
		private Node(Key key, Value value, int count) {
			this.key = key;
			this.value = value;
			this.count = count;
		}
	}
	// 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;
	}

The size method used in put is shown below

1 size
The size: count called by the user stores the number of all child nodes of the node, so the total node tree is the count value of the root node. Note that if the root node is null, additional judgment is required

public int size() {
		return size(root);
	}
	
	private int size(Node x) {
		if (x == null) {
			return 0;
		} else {
			return x.count;
		}
	}

The private size method is used in put to update the count of each node. The number of nodes in the left subtree + the number of nodes in the right subtree + 1 (self) is the total number of nodes in the subtree whose node is the root

2 select

// return the kth smallest key
	public Key select(int k) {
		Node x = select(k, root);
		if (x == null) {
			return null;
		}
		return x.key;
	}
	
	private Node select(int k, Node x) {
		if (x == null) {
			return null;
		}
		int rank = size(x.left);
		if (rank == k) {	// find the correct index
			return x;
		} else if (rank > k) { // move to the left
			return select(k, x.left);
		} else {	// move to the right
			return select(k - rank - 1, x.right);
		}
	}

Here, we should note that the count of each node represents the number of all its child nodes, including the left node and the right node. To find the ranking of this node in the tree, you should check the ranking of its left child node. (the leftmost node, i.e. the minimum value, ranks 0)

Baseline condition: 1. If it reaches the bottom of the tree (x is null), it means that the number of keys in the whole binary tree is less than k, and the search is out of bounds
2 if the corresponding index is equal to k, the key is found

State transition equation: rank is the ranking of left child nodes. If rank is greater than the target value, move left and continue to search. If rank is less than the target value, the right recursive search should be (- rank-1), which means subtracting the root node, the left node and the root node itself.

3 rank

// find the rank of a given key
	public int rank(Key key) {
		return rank(key, root);
	}
	
	private int rank(Key key, Node x) {
		if (x == null) {
			return 0;
		}
		int cmp = key.compareTo(x.key);
		if (cmp == 0) {	// find the key
			return size(x.left);
		} else if (cmp > 0) {	// smaller, move to the right
			return size(x.left) + 1 + rank(key, x.right);
		} else {	// larger, move to the left
			return rank(key, x.left);
		}
	}

Baseline conditions:
If x is null, the corresponding key has not been found at the bottom of the tree, and 0 is returned
If the corresponding key is found, the number of left child nodes will be returned

State transition equation:
If the current node key is greater than the target key, find the left subtree
If the current node key is less than the target key, find the right subtree and add size(x.left) + 1 to represent the parent node and its left node less than the right subtree key

Still note that size(x) returns the keys of all child nodes of X, including left and right. To find the ranking of X in the tree, return the number of left child tree nodes

Topics: Java Algorithm data structure Binary tree recursion