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