# Data structure -- binary lookup tree

Posted by lucy on Mon, 07 Feb 2022 09:49:33 +0100

## 1, Perfect binary tree

It is also called full binary tree, that is, except for the leaf node of the last level, each node has two child nodes

## 2, Complete binary tree

Two conditions need to be met:
(1) Except for the last layer, the number of nodes in other layers reaches the maximum
(2) The nodes of the last layer are concentrated on the left, and the nodes are continuous. Only the right part can be missing nodes

## 3, Storage of binary tree

When using binary tree to store data, we have two options: array storage and linked list storage.

### (1) Array storage

When using arrays for storage, in order to distinguish the relationship between various nodes, we will complete the tree into a full binary tree, but it will cause a waste of space.

Each node is packaged as an object and points to its left child node and right child node respectively through left and right, which avoids the waste of space and has clear regulations.

## 4, What is a binary lookup tree

Also known as binary sort tree and binary search tree. When the binary lookup tree is not empty, the following three conditions must be met:
(1) The key of the node of the non empty left subtree is less than the key of its root node
(2) The key of the node of the non empty right subtree is greater than the key of its root node
(3) The left subtree and the right subtree are also binary search trees

## 5, Traversal of tree

### (1) Preorder traversal

Access root node = > access left subtree = > access right subtree. When accessing the left or right subtree, continue to access according to this rule.

### (2) Middle order traversal

Access left subtree = > access root node = > access right subtree. When accessing the left or right subtree, continue to access according to this rule.

### (3) Subsequent traversal

Access left subtree = > access right subtree = > access root node. When accessing the left or right subtree, continue to access according to this rule.

## 6, API design

### 6.1 node class

Class nameNode<Key,Value>
Construction methodNode (key, value, node left, node right): creates a node object
Member variable1.public Node left: records the left child node
2.public Node right: record the right child node
3. Public key: storage key
4. Public value: store value

### 6.2 binary lookup tree class

Class nameBinaryTree<Key key,Value value>
Construction methodBinaryTree(): creates a BinaryTree object
Member variable1.private Node root: records the root node
2.private int N: number of elements in the record tree
Member method1. Public void put (key, value): insert a key value pair into the tree
2. Public value get (key): find the corresponding value from the tree according to the key
3. Public void delete (key): delete the corresponding key value pair in the tree according to the key
4.public int size(): get the number of elements in the tree

### 6.3 method and realization idea

1. If there is no node in the current tree, the new node is directly used as the root node
2. If the current tree is not empty, start from the root node:
2.1 if the key of the new node is less than the key of the current node, continue to find the left child node of the current node.
2.2 if the key of the new node is greater than the key of the current node, continue to find the right child node of the current node.
2.3 if the key of the new node is equal to the key of the current node, such a node already exists in the tree. Replace the value value of the node.

#### 6.3.2 check

Starting from the root node:
1. If the key to be queried is less than the key of the current node, continue to find the left child node of the current node;
2. If the key to be queried is greater than the key of the current node, continue to find the right child node of the current node;
3. If the key to be queried is equal to the key of the current node, the book returns the value of the current node.

#### 6.3.3 deletion (the new order after deletion needs to be considered)

1. Find the deleted node;
2. Find the smallest node minNode in the right subtree of the deleted node
3. Delete the smallest node in the right subtree
4. Let the left subtree of the deleted node be called the left subtree of the minimum node minNode, and let the right subtree of the deleted node be called the right subtree of the minimum node minNode
5. Make the parent node of the deleted node point to the smallest node minNode

## 7, Code implementation

### 7.1 implementation of binary search tree

/**
* Binary lookup tree -- implementation of linked list
* @date 2021/5/20 14:26
*/
public class BinaryTree<Key extends Comparable<Key>, Value> {
// Root node
private Node root;
// Number of elements in the tree
private int N;

// constructor
public BinaryTree() {}

// increase
public void put(Key key, Value value){
// Start at the root node
root = put(root, key, value);
}
// Add key value to the specified tree x and return the new tree after adding elements
private Node put(Node x, Key key, Value value){
if(x == null){
N++;
return new Node(key, value, null, null);
}
int cmp = key.compareTo((Key) x.key);
if(cmp > 0){
// recursion
x.right = put(x.right, key, value);
}else if(cmp < 0){
x.left = put(x.left, key, value);
}else {
x.value = value;
}
return x;
}

// check
public Value get(Key key){
return get(root, key);
}
// From the specified tree x, find the value corresponding to the key
private Value get(Node x, Key key){
if(x == null){
return null;
}
int cmp = key.compareTo((Key) x.key);
if(cmp > 0){// Larger than the current node, find the right
// recursion
return get(x.right, key);
}else if(cmp < 0){
return get(x.left, key);
}else {
return (Value) x.value;
}
}

// Delete
public void delete(Key key){
root = delete(root, key);
}
// Delete the value corresponding to the key in the specified tree x and return the deleted new tree
private Node delete(Node x, Key key){
if(x == null){
return null;
}
int cmp = key.compareTo((Key) x.key);
if(cmp > 0){
x.right = delete(x.right, key);
}else if(cmp < 0){
x.left = delete(x.left, key);
}else {
if(x.right == null){
}
if (x.left == null){
return x.right;
}
Node minNode = x.right;
while (minNode.left != null){
minNode = minNode.left;
}
Node n = x.right;
while (n.left != null){
if (n.left.left == null){
n.left = null;
}else {
n = n.left;
}
}
minNode.left = x.left;
minNode.right = x.right;
x = minNode;
N--;
}
return x;
}

// Get the number of elements in the tree
public int size(){
return N;
}
}

### 7.2 other convenient methods of binary search tree

#### 7.2.1 find the smallest key

// Find minimum key
public Key min(){
return (Key) min(root).key;
}
private Node min(Node x){
if(x.left != null){
return min(x.left);
}else {
return x;
}
}

#### 7.2.2 find the largest key

// Find max key
public Key max(){
return (Key) max(root).key;
}
private Node max(Node x){
if(x.right != null){
return max(x.right);
}else {
return x;
}
}

### 7.3 basic traversal of binary tree

#### 7.3.1 preorder traversal

// Preorder traversal
// Get all the keys of the specified tree and put them into the keys queue
private void preErgodic(Node x, Queue<Key> keys){
if(x==null){
return;
}

// Root -- put the key of the x node into the keys
keys.enqueue((Key) x.key);

// Left subtree -- recursively traverses the left subtree of x node
if (x.left != null){
preErgodic(x.left, keys);
}

// Right subtree -- recursively traversing the right subtree of x node
if(x.right != null){
preErgodic(x.right, keys);
}
}

#### 7.3.2 middle order traversal

// Middle order traversal
public Queue<Key> midErgodic(){
Queue<Key> keys = new Queue<>();
midErgodic(root, keys);
return keys;
}
private void midErgodic(Node x, Queue<Key> keys){
if (x==null){
return;
}
// Left subtree -- recursively traverses the left subtree of x node
if (x.left!=null){
midErgodic(x.left, keys);
}
// Root -- put the key of the x node into the keys
keys.enqueue((Key) x.key);

// Right subtree -- recursively traversing the right subtree of x node
if (x.right != null){
midErgodic(x.right, keys);
}
}

#### 7.3.3 subsequent traversal

// Postorder traversal
public Queue<Key> afterErgodic(){
Queue<Key> keys = new Queue<>();
afterErgodic(root, keys);
return keys;
}
private void afterErgodic(Node x, Queue<Key> keys){
if (x == null){
return;
}
// Left subtree -- recursively traverses the left subtree of x node
if (x.left != null){
afterErgodic(x.left, keys);
}

// Right subtree -- recursively traversing the right subtree of x node
if (x.right != null){
afterErgodic(x.right, keys);
}

// Root -- put the key of the x node into the keys
keys.enqueue((Key) x.key);
}

### 7.4 sequence traversal of binary tree

// Sequence traversal -- from top to bottom, from left to right
public Queue<Key> layerErgodic(){
// Create queue -- key of storage node
Queue<Key> keys = new Queue<>();
Queue<Node> nodes = new Queue<>(); //Auxiliary queue
// (1) The root node enters the queue
nodes.enqueue(root);
// (2) Bounce element -- bounce first, put the key of the node into the keys, judge whether there are left and right child nodes, and if so, put them in the queue
while (!nodes.isEmpty()){
Node x = nodes.dequeue(); // Pop up node
keys.enqueue((Key) x.key); // Put the key of the pop-up element in the queue
if(x.left!=null){
nodes.enqueue(x.left);
}
if (x.right!=null){
nodes.enqueue(x.right);
}
}
return keys;
}

### 7.5 maximum depth of binary tree

// Maximum depth
public int maxDepth(){
return maxDepth(root);
}
// Calculates the maximum depth of the specified tree x
private int maxDepth(Node x){
// 1. If the root node is empty, the maximum depth is 0
if (x==null){
return 0;
}
int max = 0;
int maxL = 0;
int maxR = 0;
// 2. Calculate the maximum depth of the left subtree
if (x.left!=null){
maxL = maxDepth(x.left);
}
// 3. Calculate the maximum depth of the right subtree
if (x.right!=null){
maxR = maxDepth(x.right);
}
// 4. Maximum depth of current tree = maximum depth of left subtree + maximum depth of right subtree + 1
max = maxL > maxR ? maxL+1 : maxR+1;
return max;
}

Topics: Java data structure