# Notes on learning data structure -- [binary tree learning]

Station B learning portal – > Shang Silicon Valley Java data structure and Java algorithm (Java data structure and algorithm)

## 1. Learn binary tree

Notice that you start at the base of the binary tree

Binary tree; Based on the root node;

• The node on the left of the root node is generally called the left subtree;
• The node on the right of the root node is generally called the right subtree;
• Each part taken out separately can be regarded as a binary tree

Full binary tree: all root nodes are hung with left and right subtrees

## 2. Preliminarily realize the pre order, middle order and post order traversal of binary tree

This time, manually create a binary tree; It mainly studies the traversal thought of pre order, middle order and post order of binary tree

### graphic

First, analyze the previous figure;

Preorder traversal:

Get output order: root node (middle node) - > left subtree - > right subtree

For example, if the binary tree just created is traversed in the previous order;
You have to output 13 -- > 11 -- > 8 -- > 12 -- > 75 -- > 14 -- > 100

Middle order traversal:
Obtain the output sequence; Left subtree - > central node - > right subtree
For example, the binary tree just now is traversed in middle order;
8 --> 11 --> 12 --> 13 --> 14 --> 75 --> 100

Post order traversal;
Output order: left subtree - > right subtree - > center node

The output order of the binary tree is;

8 --> 12 --> 11 --> 14 --> 100 --> 75 --> 13

### Simple implementation of pre middle post order traversal

```/**
* @author by CSDN@Xiaozhi RE0
* @date 2021-11-10 18:10
*/
public class DemoTree {
public static void main(String[] args) {

//Manually create binary tree;
BinarTree  btree = new BinarTree();
//Create a node first;
Node root  = new Node(13);
Node node1 = new Node(11);
Node node2 = new Node(75);
Node node3 = new Node(8);
Node node4 = new Node(12);
Node node5 = new Node(14);
Node node6 = new Node(100);

//Manually attach child nodes;
root.setLeft(node1);
root.setRight(node2);
node1.setLeft(node3);
node1.setRight(node4);
node2.setLeft(node5);
node2.setRight(node6);
btree.setRoot(root);

System.out.println("Simple preorder traversal---");
btree.prefixList();
System.out.println("Simple middle order traversal---");
btree.infixList();
System.out.println("Simple post order traversal---");
btree.suffixList();
}
}

//Binary tree;
class BinarTree {
//Root node;
public Node root;

//Set the root node;
public void setRoot(Node root) {
this.root = root;
}

//Preorder traversal;
public void prefixList() {
if (root == null) {
System.out.println("Empty tree,Not traversal");
} else {
this.root.prefixList();
}
}

//Middle order traversal;
public void infixList() {
if (root == null) {
System.out.println("Empty tree,Not traversal");
} else {
this.root.infixList();
}
}

//Post order traversal;
public void suffixList() {
if (root == null) {
System.out.println("Empty tree,Not traversal");
} else {
this.root.suffixList();
}
}
}

//Node;
class Node {
//The value of the node;
private int val;
//Left subtree, right subtree;
private Node left;
private Node right;

public Node(int val) {
this.val = val;
}

public int getVal() {
return val;
}

public void setVal(int val) {
this.val = val;
}

public Node getLeft() {
return left;
}

public void setLeft(Node left) {
this.left = left;
}

public Node getRight() {
return right;
}

public void setRight(Node right) {
this.right = right;
}

@Override
public String toString() {
return "Node{" + "val=" + val + '}';
}

//Preorder traversal; Middle -- > left -- > right;
public void prefixList() {
//The central node outputs first;
System.out.println(this);

if (this.left != null) {
//To the left subtree;
this.left.prefixList();
}

if (this.right != null) {
//To right subtree;
this.right.prefixList();
}
}

//Middle order traversal; Left -- > Middle -- > right;
public void infixList() {
//First go to the left subtree;
if (this.left != null) {
this.left.infixList();
}
//Central node;
System.out.println(this);
//In the right subtree;
if (this.right != null) {
this.right.infixList();
}
}

//Post order traversal; Left -- > right -- > middle;
public void suffixList() {
//Left subtree;
if (this.left != null) {
this.left.suffixList();
}
//Right subtree;
if (this.right != null) {
this.right.suffixList();
}
//Center point output
System.out.println(this);
}

}
```

Test results;

```Simple preorder traversal---
Node{val=13}
Node{val=11}
Node{val=8}
Node{val=12}
Node{val=75}
Node{val=14}
Node{val=100}
Simple middle order traversal---
Node{val=8}
Node{val=11}
Node{val=12}
Node{val=13}
Node{val=14}
Node{val=75}
Node{val=100}
Simple post order traversal---
Node{val=8}
Node{val=12}
Node{val=11}
Node{val=14}
Node{val=100}
Node{val=75}
Node{val=13}
```

## 3. Preliminarily realize the pre order search and middle order search of binary tree; Post order search;

Then, when the pre order search, the middle order search and the post order search are performed, the order of the traversal must be the same; Search step by step;

Preorder search

• First, judge whether the current node meets the requirements;
• If the current node does not match, first judge whether the left subtree is empty; If it is not empty, recursion is performed downward in the left subtree;
• If the node to be searched is found after the left subtree recursion; Just go straight back,
• If it is not found under the left subtree, judge whether the right subtree is empty. If it is not empty, search recursively;
• Finally, if it is not found, an empty node is returned

Middle order search

• First, judge whether the left subtree of the current node is empty; Recursion if it is not empty;
• If it is found recursively in the left subtree, it will be returned directly;
• Judge whether the current node meets the requirements;
• Then judge whether the right subtree of the current node is empty. If not, recursion will be carried out;
• If it is not found in the end, an empty node is returned;

Sequential search

• First, judge whether the left subtree of the current node is empty, and recurse if it is not empty;
• If it is found recursively in the left subtree, it will be returned directly;
• Then judge whether the right subtree of the current node is empty; Recursion if it is not empty;
• If it is found recursively in the right subtree, it will be returned directly;
• Judge whether the current node meets the requirements;
```/**
* @author by CSDN@Xiaozhi RE0
*/
public class DemoTree {
public static void main(String[] args) {
//Manually create binary tree;
BinarTree btree = new BinarTree();
//Create a node first;
Node root = new Node(13);
Node node1 = new Node(11);
Node node2 = new Node(75);
Node node3 = new Node(8);
Node node4 = new Node(12);
Node node5 = new Node(14);
Node node6 = new Node(100);

//Manually attach child nodes;
root.setLeft(node1);
root.setRight(node2);
node1.setLeft(node3);
node1.setRight(node4);
node2.setLeft(node5);
node2.setRight(node6);
btree.setRoot(root);

System.out.println("Preamble search test--->");
btree.prefixSearch(14);
System.out.println("Middle order search test--->");
btree.infixSearch(14);
System.out.println("Post order search test--->");
btree.suffixSearch(14);
}
}

//Binary tree;
class BinarTree {
//Root node;
public Node root;

//Set the root node;
public void setRoot(Node root) {
this.root = root;
}

//Preorder search;
public void prefixSearch(int val) {
if (root == null) {
System.out.println("Empty tree,No search");
} else {
Node node = this.root.prefixSearch(val);
if (node == null) {
System.out.println("Can't find");
} else {
System.out.println("Node found" + node.getVal());
}
}
}

//Middle order search;
public void infixSearch(int val) {
if (root == null) {
System.out.println("Empty tree,No search");
} else {
Node node = this.root.infixSearch(val);
if (node == null) {
System.out.println("Can't find");
} else {
System.out.println("Node found" + node.getVal());
}
}
}

//Post order search;
public void suffixSearch(int val) {
if (root == null) {
System.out.println("Empty tree,No search");
} else {
Node node = this.root.suffixSearch(val);
if (node == null) {
System.out.println("Can't find");
} else {
System.out.println("Node found" + node.getVal());
}
}
}
}

//Node;
class Node {
//The value of the node;
private int val;
//Left subtree, right subtree;
private Node left;
private Node right;

public Node(int val) {
this.val = val;
}

public int getVal() {
return val;
}

public void setVal(int val) {
this.val = val;
}

public Node getLeft() {
return left;
}

public void setLeft(Node left) {
this.left = left;
}

public Node getRight() {
return right;
}

public void setRight(Node right) {
this.right = right;
}

@Override
public String toString() {
return "Node{" + "val=" + val + '}';
}

//Pre order search steps;
public Node prefixSearch(int val) {
//During preorder traversal, the middle -- > left -- > right;
System.out.println("Searching in preamble------>");
//1. First judge whether the current node is empty;
if (this.val == val) {
return this;
}
Node resultNode = null;
//If not, first check whether the left subtree is null; If it is not empty, it will recurse all the way to the left;
if (this.left != null) {
resultNode = this.left.prefixSearch(val);
}
//If it is found in the left subtree, it will return in advance;
if (resultNode != null) {
return resultNode;
}
//If the left subtree is not found, it will be found recursively in the right subtree;
//Check whether the right subtree is empty;
if (this.right != null) {
resultNode = this.right.prefixSearch(val);
}
//Finally, return the node of the query; If it is null, it is not found;
return resultNode;
}

//Middle order search steps;
public Node infixSearch(int val) {
//Middle order traversal; Left -- > Middle -- > right;
Node resultNode = null;
//First judge whether the left subtree is empty; If it is not empty, search again;
if (this.left != null) {
resultNode = this.left.infixSearch(val);
}
if (resultNode != null) {
return resultNode;
}
System.out.println("Searching in order------>");
//Judge whether the current node meets the requirements;
if (this.val == val) {
return this;
}
//Judge whether the right subtree is empty, and then search recursively;
if (this.right != null) {
resultNode = this.right.infixSearch(val);
}
//The final returned result node; If it is null, it is not found;
return resultNode;
}

//Subsequent search steps;
public Node suffixSearch(int val) {
//During post order traversal, left -- > right -- > middle;
Node resultNode = null;
//Similarly, first judge whether the left subtree is empty;
if (this.left != null) {
resultNode = this.left.suffixSearch(val);
}
if (resultNode != null) {
return resultNode;
}
//Right subtree recursion;
if (this.right != null) {
resultNode = this.right.suffixSearch(val);
}
if (resultNode != null) {
return resultNode;
}
System.out.println("Searching in post order------>");
//Judge whether the current node meets the requirements;
if (this.val == val) {
return this;
}
//Finally, the result node is returned. If it is null, it is not found;
return resultNode;
}

}
```

Test results:

```Preamble search test--->
Searching in preamble------>
Searching in preamble------>
Searching in preamble------>
Searching in preamble------>
Searching in preamble------>
Searching in preamble------>
Node 14 found
Middle order search test--->
Searching in order------>
Searching in order------>
Searching in order------>
Searching in order------>
Searching in order------>
Node 14 found
Post order search test--->
Searching in post order------>
Searching in post order------>
Searching in post order------>
Searching in post order------>
Node 14 found
```

## 4. Preliminarily realize the deletion of binary tree

• For specific implementation, first search on the left side of the current node; If it matches, it will be deleted, and then find it on the right of the current node. If it matches, it will be deleted;
• Then, if it is not found, it recurses downward from the left subtree of the current node until it recurses to the leaf node;
• Recursion down from the right subtree of the current node to the leaf node;
• In fact, the current node when operating here is not a fixed node; Is a node that changes all the time; It recurses to the left or right;

Specific implementation process

```package day09binarysearchtree.demo01_starttree;

/**
* @author by CSDN@Xiaozhi RE0
* @date 2021-11-10 18:10
*/
public class DemoTree {
public static void main(String[] args) {

//Manually create binary tree;
BinarTree btree = new BinarTree();
//Create a node first;
Node root = new Node(13);
Node node1 = new Node(11);
Node node2 = new Node(75);
Node node3 = new Node(8);
Node node4 = new Node(12);
Node node5 = new Node(14);
Node node6 = new Node(100);

//Manually attach child nodes;
root.setLeft(node1);
root.setRight(node2);
node1.setLeft(node3);
node1.setRight(node4);
node2.setLeft(node5);
node2.setRight(node6);
btree.setRoot(root);
System.out.println("Simple preorder traversal---");
btree.prefixList();
//Delete the specified node;
btree.deleteNode(8);
System.out.println("Simple preorder traversal after deleting nodes---");
btree.prefixList();
}
}

//Binary tree;
class BinarTree {
//Root node;
public Node root;
//Set the root node;
public void setRoot(Node root) {
this.root = root;
}

//Call to delete the specified element;
public void deleteNode(int val){
//First, empty trees are excluded;
if(root!=null){
//Judge whether the nodes of the tree meet the requirements;
if(root.getVal()==val){
root =null;
}else {
root.deleteNode(val);
}
}else {
System.out.println("Empty tree,Cannot delete");
}
}

//Preorder traversal;
public void prefixList() {
if (root == null) {
System.out.println("Empty tree,Not traversal");
} else {
this.root.prefixList();
}
}
}

//Node;
class Node {
//The value of the node;
private int val;
//Left subtree, right subtree;
private Node left;
private Node right;

public Node(int val) {
this.val = val;
}

public int getVal() {
return val;
}

public void setVal(int val) {
this.val = val;
}

public Node getLeft() {
return left;
}

public void setLeft(Node left) {
this.left = left;
}

public Node getRight() {
return right;
}

public void setRight(Node right) {
this.right = right;
}

@Override
public String toString() {
return "Node{" + "val=" + val + '}';
}

//Delete the node in the binary tree;
public void deleteNode(int val){
//First, check whether the left subtree is empty. If it is empty and meets the requirements, delete it;
if(this.left!=null && this.left.val==val){
this.left = null;
return;
}
//Then check whether the right subtree is empty. If it is empty and meets the requirements, delete it;
if(this.right!=null && this.right.val==val){
this.right = null;
return;
}

//Then, recursion is performed to see whether the left subtree is empty;
if (this.left!=null){
this.left.deleteNode(val);
}

//Right recursion;
if (this.right!=null){
this.right.deleteNode(val);
}
}

//Preorder traversal; Middle -- > left -- > right;
public void prefixList() {
//The central node outputs first;
System.out.println(this);

if (this.left != null) {
//To the left subtree;
this.left.prefixList();
}

if (this.right != null) {
//To right subtree;
this.right.prefixList();
}
}
}
```

Test results:

```Simple preorder traversal---
Node{val=13}
Node{val=11}
Node{val=8}
Node{val=12}
Node{val=75}
Node{val=14}
Node{val=100}
Simple preorder traversal after deleting nodes---
Node{val=13}
Node{val=11}
Node{val=12}
Node{val=75}
Node{val=14}
Node{val=100}
```

## 5. Store the binary tree in sequence (complete the first, middle and last sequence traversal)

From top to bottom, from left to right; Traversing a binary tree;
The array obtained by traversal can be converted to binary tree; In other words, even if the binary tree is changed into an array, the preorder / inorder / postorder traversal can be derived from this data;

• If a binary tree is stored sequentially, it is generally for a complete binary tree;
• Binary tree in sequential storage, characterized by the nth element (starting from zero); The left subtree node of is 2N+1; The right subtree node of the nth element is 2N+2;

The specific implementation of sequential storage binary tree traversal

```package day09binarysearchtree.demo02_sequentialstorageofbinarytrees;

/**
* @author by CSDN@Xiaozhi RE0
* @date 2021-11-11 18:50
* Sequential storage binary tree
*/
public class SequentialStorageOfBinaryTreeTest {
public static void main(String[] args) {
//The array to be stored;
int[] array = {1, 2, 3, 4, 5, 6, 7};
SequentialStorageOfBinaryTree storage = new SequentialStorageOfBinaryTree(array);
//Preorder traversal;
storage.prefixList();
//Middle order traversal;
storage.infixList();
//Post order traversal;
storage.suffixList();
/*
Preorder traversal -- > 1 - > 2 - > 4 - > 5 - > 3 - > 6 - > 7 - >
Middle order traversal -- > 4 - > 2 - > 5 - > 1 - > 6 - > 3 - > 7 - >
Post order traversal -- > 4 - > 5 - > 2 - > 6 - > 7 - > 3 - > 1 - >
*/
}
}

//Analog sequential storage binary tree;
class SequentialStorageOfBinaryTree {
//Using array as storage structure;
private final int[] data;

//initialization;
public SequentialStorageOfBinaryTree(int[] data) {
this.data = data;
}

//Complete preorder traversal;
public void prefixList() {
System.out.print("Preorder traversal-->");
prefixList(0);
//Print blank lines for line feed;
System.out.println();
}

/**
* Preorder traversal of sequential storage binary tree
* Middle - > left - > right
* @param i Array index
*/
private void prefixList(int i) {
//Eliminate the empty tree first;
if (data == null || data.length == 0) {
System.out.println("Empty tree,Unable to traverse");
return;
}

//When traversing, first get the current node;
System.out.printf("%d->", data[i]);

//When recursing left / right, you should pay attention to whether this exceeds the length of the array;
if ((2 * i) + 1 < data.length) {
prefixList(2 * i + 1);
}
if ((2 * i + 2) < data.length) {
prefixList(2 * i + 2);
}
}

//Complete the middle order traversal;
public void infixList() {
System.out.print("Medium order traversal-->");
infixList(0);
System.out.println();
}

/**
* Middle order traversal of sequential storage binary tree
* Left - > Middle - > right
* @param i Subscript of array
*/
private void infixList(int i) {
//Exclude empty trees first;
if (data == null || data.length == 0) {
System.out.println("Empty tree,No traversal is required");
return;
}

//Left recursion first;
if ((2 * i) + 1 < data.length) {
infixList((2 * i) + 1);
}
//Then print the current element;
System.out.printf("%d->", data[i]);
//Right recursion;
if ((2 * i + 2) < data.length) {
infixList((2 * i) + 2);
}
}

//Complete the post order traversal;
public void suffixList() {
System.out.print("Postorder traversal-->");
suffixList(0);
System.out.println();
}

/**
* Post order traversal of sequential storage binary tree
* Left - > right - > middle
* @param i Subscript of array
*/
private void suffixList(int i) {
//Exclude empty trees first;
if (data == null || data.length == 0) {
System.out.println("Empty tree,No traversal is required");
return;
}

//Recursion to the left first;
if ((2 * i) + 1 < data.length) {
suffixList((2 * i) + 1);
}
//Recursion to the right;
if ((2 * i) + 2 < data.length) {
suffixList((2 * i) + 2);
}
//Print the current array element;
System.out.printf("%d->", data[i]);
}

}
```

## 6. Cued binary tree

Cued binary tree; Not a specific tree,
Optimize the preorder traversal of binary tree; The preordered cued binary tree can be obtained;
Similar ordered cued binary trees; Post order cued binary tree;

For example, there is such a tree; Its middle order traversal output can be used as a sequence of 8 - > 3 - > 10 - > 1 - > 14 - > 6

But it has seven empty finger needle fields; There will be a waste of space;
Then you need to add a precursor pointer to it (pointing to the previous node); Subsequent pointer (pointing to the next node);

Then, at this time, if you want to supplement the binary tree with the predecessor node / successor node;
The approximate completion is shown in the figure below;

It can be noted that sometimes the left pointer in the tree may point to the left subtree or the precursor node;
The pointer pointing to right in the tree may point to the right subtree or subsequent nodes;
Then, in the implementation, two variables can be used to distinguish (precursor pointer / left subtree); (rear drive pointer / right subtree)

When implementing the middle order search, you can specify a variable as the precursor node to store the previous node;
Then, the successor node of the last operation node is the current operation node;

In addition, when the current binary tree is searched, due to more pointers, the original structure will be disrupted; If the previous output traversal mode is also used, the null pointer exception problem will occur;
Then you need to rearrange the corresponding traversal method;
Moreover, it should be noted that in the binary tree after preorder search, preorder traversal and output printing should be carried out accordingly;
The binary tree undergoing medium order search shall be traversed and printed accordingly;
The binary tree undergoing post order search shall be traversed and printed accordingly;

```package day09abouttree.demo03_linearbinarytree;

/**
* @author by CSDN@Xiaozhi RE0
* @date 2021-11-11 19:25
* Use of cued binary tree
*/
public class LinearBinaryTreeTest {
//Testing;
public static void main(String[] args) {
ClueTree clueTree = new ClueTree();
Node root = new Node(1);
Node node1 = new Node(8);
Node node2 = new Node(3);
Node node3 = new Node(10);
Node node4 = new Node(14);
Node node5 = new Node(6);
//Manually hook up nodes;
root.setLeft(node2);
root.setRight(node5);
node2.setLeft(node1);
node2.setRight(node3);
node5.setLeft(node4);
clueTree.setRoot(root);

//Sequential cued binary tree in testing;
clueTree.preClueList();

//The precursor and successor nodes of the node with the test value of 8;
Node left = node1.getLeft();
Node right = node1.getRight();
System.out.println("8 The precursor node of node is->" + left);
System.out.println("8 The successor node of node is->" + right);

System.out.println("-----The searched binary tree is traversed in middle order--------");
//Middle order traversal;
clueTree.prefixList();
}
}

//Binary tree;
class ClueTree {
//Root node;
public Node root;

//Set the root node;
public void setRoot(Node root) {
this.root = root;
}

//----------------------------------------------->

//Define the precursor node;
public Node preNode = null;

public void preClueList() {
preClueList(root);
}

//Middle order cued binary tree;
private void preClueList(Node node) {
//First, empty trees are excluded;
if (node == null) {
return;
}

//Left recursion;
preClueList(node.getLeft());

//When processing the current node;
//1. The first is the precursor node;
// At this time, the precursor node can be added only when the left subtree of the current node is empty;
if (node.getLeft() == null) {
//Set the precursor node for it;
node.setLeft(preNode);
//Change the type of this pointer;
node.setPreType(1);
}

//2. Processing of subsequent nodes;
//Similarly, only when the right subtree of this node is empty can a successor node be added to it;
//One thing to understand is that the precursor node of this point is actually the node of the previous operation;
if (preNode != null && preNode.getRight() == null) {
//Set the node for it;
preNode.setRight(node);
//Change the type of pointer;
preNode.setSuffixType(1);

}
//3. At this time, you need to make the current node as the front node;
preNode = node;

//Right recursion
preClueList(node.getRight());
}

//----------------------------------------------->

//Traversing the output binary tree in middle order;
public void prefixList() {
//Save the root node as the operation node;
Node temp = root;

while (temp != null) {
//Find the precursor node first;
while (temp.getPreType() == 0) {
//Search left;
temp = temp.getLeft();
}
//Output the current node;
System.out.println(temp);

//If the successor node is found;
while (temp.getSuffixType() == 1) {
//Find right;
temp = temp.getRight();
//Output the current node;
System.out.println(temp);
}
//No, keep right
temp = temp.getRight();
}
}

}

//Node;
class Node {
//The value of the node;
private int val;
//Left subtree, right subtree;
private Node left;
private Node right;

//A marker point is required; Tag is left subtree (0) / precursor node (1)
private int preType;
//Right subtree (0) / successor node (1);
private int suffixType;

public int getPreType() {
return preType;
}

public void setPreType(int preType) {
this.preType = preType;
}

public int getSuffixType() {
return suffixType;
}

public void setSuffixType(int suffixType) {
this.suffixType = suffixType;
}

public Node(int val) {
this.val = val;
}

public int getVal() {
return val;
}

public void setVal(int val) {
this.val = val;
}

public Node getLeft() {
return left;
}

public void setLeft(Node left) {
this.left = left;
}

public Node getRight() {
return right;
}

public void setRight(Node right) {
this.right = right;
}

@Override
public String toString() {
return "Node{" + "val=" + val + '}';
}
}
```

Test implementation

```8 The precursor node of node is->null
8 The successor node of node is->Node{val=3}
-----The searched binary tree is traversed in middle order--------
Node{val=8}
Node{val=3}
Node{val=10}
Node{val=1}
Node{val=14}
Node{val=6}
```

Tags: data structure

Posted on Thu, 11 Nov 2021 13:32:14 -0500 by areid