# Look and think for 15 minutes. Take the clue and store the binary tree

## preface

If you think the article is helpful, please leave some praise and collection. Pay attention to xiaoleng and read more dry goods learning articles

★ this is Xiao Leng's blog ‡ see the column for good articles on high-quality technology The official account of the individual, sharing some technical articles, and the pit encountered. Current series: data structure series Source code git warehouse Data structure code address Code Git warehouse address

## Cued binary tree

The cue binary tree is introduced through a problem

The sequence {1,3,6,8,10,14} is constructed into a binary tree n+1=7

Problem analysis:

1. When we traverse the above binary tree in middle order, the sequence is {8, 3, 10, 1, 6, 14}
2. However, the left and right pointers of nodes 6, 8, 10 and 14 are not fully utilized
3. What if we want to make full use of the left and right pointers of each node so that each node can point to its own front and rear nodes?
4. Solution - clue binary tree

#### Basic introduction of clue binary tree

1. The binary linked list of N nodes contains n+1 [Formula 2n-(n-1)=n+1] empty finger needle fields. The null pointer field in the binary linked list is used to store pointers to the precursor and successor nodes of the node in a certain traversal order (this additional pointer is called "clue")
2. This binary linked list with clues is called clue linked list, and the corresponding binary tree is called threaded binary tree. According to the different properties of clues, clue binary trees can be divided into three types: pre order clue binary trees, middle order clue binary trees and post order clue binary trees
3. The previous node of a node is called the precursor node
4. The next node of a node is called the successor node

#### Application case of clue binary tree

Put the following binary tree into the middle order clue binary tree. The number sequence traversed in the middle order is {8, 3, 10, 1, 14, 6}

Note: after cueing the binary tree, the attributes left and right of the Node are as follows:

1. Left refers to the left subtree or the precursor node For example, ① node left points to the left subtree, while ⑩ node left points to the left subtree Is the precursor node
2. Right refers to the right subtree or the successor node. For example, ① node right refers to the right subtree, while ⑩ node right refers to the successor node

#### code implementation

```package com.hyc.DataStructure.tree.ThreadedBinaryTree;

/**
* @projectName: DataStructure
* @author: Cold Huanyuan doorwatcher
* @description: TODO
* @date: 2022/2/5 16:38
* @version: 1.0
*/
public static void main(String[] args) {
//Test the function of a medium order clue binary tree
heroNode root = new heroNode(1, "tom");
heroNode node2 = new heroNode(3, "jack");
heroNode node3 = new heroNode(6, "smith");
heroNode node4 = new heroNode(8, "mary");
heroNode node5 = new heroNode(10, "king");
heroNode node6 = new heroNode(14, "dim");

//The binary tree will be created recursively later. Now it is easy to create it manually
root.setLeftNode(node2);
root.setRightNode(node3);
node2.setLeftNode(node4);
node2.setRightNode(node5);
node3.setLeftNode(node6);

//Sequential cueing in testing

//Test: test with node 10
heroNode leftNode = node5.getLeftNode();
heroNode rightNode = node5.getRightNode();
System.out.println("10 The precursor node of node is =" + leftNode); //3
System.out.println("10 The successor node of node is=" + rightNode); //1

//When the binary tree is threaded, the original traversal method can be used
System.out.println("Traversing the cued binary tree in a cued way");

}

}

//Determine root node
//During recursion, the variables used to store the previous node are used to traverse the cued tree and cued nodes
private heroNode pre;

}

//Cued traversal
//    Here we need a variable to store the current node
while (tempNode != null) {
/* Start loop traversal
* Loop to find the node with lefttype 1, so the first one to find is the node with node value of 8
* Later, it will change with traversal. When lefttype ==1 is found, it indicates that the tree has been cued
* After that, you only need to deal with the effective nodes after cueing
* */
while (tempNode.getLefttype() == 0) {
tempNode = tempNode.getLeftNode();
}
//    Because it is a medium order traversal, the order is: left, middle and right. Here, we are from the left lefttype==1, that is, it is the first node at the beginning of the left, so we can output it directly
System.out.println(tempNode);
/* If the right pointer of the current node points to the subsequent node, it will be output all the time
* */
while (tempNode.getRighttype() == 1) {
tempNode = tempNode.getRightNode();
System.out.println(tempNode);
}
// Replace this traversal node
tempNode = tempNode.getRightNode();
}
}

//    Here we need a variable to store the current node
while (tempNode != null) {
/* Start loop traversal
* Loop to find the node with lefttype 1, so the first one to find is the node with node value of 8
* Later, it will change with traversal. When lefttype ==1 is found, it indicates that the tree has been cued
* After that, you only need to deal with the effective nodes after cueing
* */
while (tempNode.getLefttype() == 0) {
System.out.println(tempNode);
tempNode = tempNode.getLeftNode();
}
//    Because it is a medium order traversal, the order is: left, middle and right. Here, we are from the left lefttype==1, that is, it is the first node at the beginning of the left, so we can output it directly
System.out.println(tempNode);
// Traversal of this node
tempNode = tempNode.getRightNode();
}

}

//Cued node
//       Non null judgment
if (node == null) {
return;
}
//    Cued left subtree
//    Cued node
//It's not easy to understand. Here's 8 an example
// 8's left ==null, then 8's lefttype = 1 means that it is a precursor node
if (node.getLeftNode() == null) {
//If the left pointer of the current node is null, then point her left pointer to the pre preceding node
//Taking 8 as an example, when the method pre is empty for the first time, so 8 has no front node, it is the front node itself, so the left pointer state is 1
node.setLeftNode(pre);
//    After pointing, change the type to 1
node.setLefttype(1);
}
//Processing successor nodes
//The leading node judged here is not empty, and the leading node has no successor node
if (pre != null && pre.getRightNode() == null) {
//Here, take the latter node of 8 as an example. When the pointer points to 3, the front node pre = 8, which means that the rightnode of 8 is 3
pre.setRightNode(node);
//At this time, the post node is not a subtree, and when the right pointer of the pre node points to the node, changing the right state to 1 indicates that it is the successor node
pre.setRighttype(1);
}

//Every time a node is processed, we need to store it in pre, that is, the front node
//Otherwise, it will cause dead recursion
pre = node;
//    Cued right subtree

}

//Cued node
//       Non null judgment
if (node == null) {
return;
}

//    Cued node
//It's not easy to understand. Here's 8 an example
// 8's left ==null, then 8's lefttype = 1 means that it is a precursor node
if (node.getLeftNode() == null) {
//If the left pointer of the current node is null, then point her left pointer to the pre preceding node
//Taking 8 as an example, when the method pre is empty for the first time, so 8 has no front node, it is the front node itself, so the left pointer state is 1
node.setLeftNode(pre);
//    After pointing, change the type to 1
node.setLefttype(1);
}
//Processing successor nodes
//The leading node judged here is not empty, and the leading node has no successor node
if (pre != null && pre.getRightNode() == null) {
//Here, take the latter node of 8 as an example. When the pointer points to 3, the front node pre = 8, which means that the rightnode of 8 is 3
pre.setRightNode(node);
//At this time, the post node is not a subtree, and when the right pointer of the pre node points to the node, changing the right state to 1 indicates that it is the successor node
pre.setRighttype(1);
}

//Every time a node is processed, we need to store it in pre, that is, the front node
//Otherwise, it will cause dead recursion
pre = node;
if (node.getLefttype() == 0) {
//    Cued left subtree
}
if (node.getRighttype() == 0) {
//    Cued right subtree
}
}

//Cued node
//       Non null judgment
if (node == null) {
return;
}
//    Cued left subtree
//    Cued right subtree
//    Cued node
//It's not easy to understand. Here's 8 an example
// 8's left ==null, then 8's lefttype = 1 means that it is a precursor node
if (node.getLeftNode() == null) {
//If the left pointer of the current node is null, then point her left pointer to the pre preceding node
//Taking 8 as an example, when the method pre is empty for the first time, so 8 has no front node, it is the front node itself, so the left pointer state is 1
node.setLeftNode(pre);
//    After pointing, change the type to 1
node.setLefttype(1);
}
//Processing successor nodes
//The leading node judged here is not empty, and the leading node has no successor node
if (pre != null && pre.getRightNode() == null) {
//Here, take the latter node of 8 as an example. When the pointer points to 3, the front node pre = 8, which means that the rightnode of 8 is 3
pre.setRightNode(node);
//At this time, the post node is not a subtree, and when the right pointer of the pre node points to the node, changing the right state to 1 indicates that it is the successor node
pre.setRighttype(1);
}

//Every time a node is processed, we need to store it in pre, that is, the front node
//Otherwise, it will cause dead recursion
pre = node;

}

//   Preorder traversal
public void preOrder() {
} else {
System.out.println("Binary tree has no root node and cannot be traversed");
}
}

//Middle order traversal
public void InfixOrder() {
} else {
System.out.println("Binary tree has no root node and cannot be traversed");
}
}

//Subsequent traversal
public void PostOrder() {
} else {
System.out.println("Binary tree has no root node and cannot be traversed");
}
}

//Preorder search
public heroNode preOrderSearch(int no) {
} else {
return null;
}
}

//Medium order search
public heroNode infixOrderSearch(int no) {
} else {
return null;
}
}

//Sequential search
public heroNode postOrderSearch(int no) {
} else {
return null;
}
}

//    Delete node
public void deleteNode(int no) {
return;
} else {
}
} else {
System.out.println("Empty tree,Cannot delete");
}
}
}

class heroNode {
private int id;
private String name;
private heroNode leftNode;
private heroNode rightNode;
//If the type is 0, it means that there is a subtree. If the type is 1, it means that it is a precursor node / post node
private int lefttype;
private int righttype;

public int getLefttype() {
return lefttype;
}

public void setLefttype(int lefttype) {
this.lefttype = lefttype;
}

public int getRighttype() {
return righttype;
}

public void setRighttype(int righttype) {
this.righttype = righttype;
}

public heroNode getLeftNode() {
return leftNode;
}

public void setLeftNode(heroNode leftNode) {
this.leftNode = leftNode;
}

public heroNode getRightNode() {
return rightNode;
}

public void setRightNode(heroNode rightNode) {
this.rightNode = rightNode;
}

public heroNode(int id, String name) {
this.id = id;
this.name = name;
}

public int getId() {
return id;
}

public void setId(int id) {
this.id = id;
}

public String getName() {
return name;
}

@Override
public String toString() {
return "heroNode{" +
"id=" + id +
", name='" + name + '\'' +
'}';
}

public void setName(String name) {
this.name = name;

}

//    Preorder traversal
public void PreOrder() {
System.out.println(this);
if (this.getLeftNode() != null) {
this.leftNode.PreOrder();
}
if (this.getRightNode() != null) {
this.rightNode.PreOrder();
}
}

//    Middle order traversal
public void infixOrder() {
if (this.leftNode != null) {
this.leftNode.infixOrder();
}
System.out.println(this);
if (this.rightNode != null) {
this.rightNode.infixOrder();
}
}

//   Postorder traversal
public void postOrder() {
if (this.leftNode != null) {
this.leftNode.postOrder();
}
if (this.rightNode != null) {
this.rightNode.postOrder();
}
System.out.println(this);
}

//   Preorder search
public heroNode PreOrderSearch(int no) {
System.out.println("Preorder search");
//Compare whether the no of the current node is what we want to search
if (this.id == no) {
return this;
}
//Node to return
heroNode resNode = null;
//  Judge whether the node on the left is empty. If it is not empty, recursive preamble search is performed
//    If found, return the found node
if (this.leftNode != null) {
resNode = this.leftNode.PreOrderSearch(no);
}
//If it is not null, it means that if it is found on the left, it can be returned directly
if (resNode != null) {
return resNode;
}
//  Judge whether the node on the right is empty. If it is not empty, recursive preamble search is performed
//    If found, return the found node
if (this.rightNode != null) {
resNode = this.rightNode.PreOrderSearch(no);
}
return resNode;
}

//   Medium order search
public heroNode infixOrderSearch(int no) {

//Node to return
heroNode resNode = null;
//  Judge whether the left node is empty. If it is not empty, search in recursive order
//    If found, return the found node
if (this.leftNode != null) {
resNode = this.leftNode.infixOrderSearch(no);
}
//If it is not null, it means that if it is found on the left, it can be returned directly
if (resNode != null) {
return resNode;
}
//Compare whether the no of the current node is what we want to search
System.out.println("Medium order search");
if (this.id == no) {
return this;
}
//  Judge whether the node on the right is empty. If it is not empty, search in recursive order
//    If found, return the found node
if (this.rightNode != null) {
resNode = this.rightNode.infixOrderSearch(no);
}
return resNode;
}

//   Sequential search
public heroNode postOrderSearch(int no) {

//Node to return
heroNode resNode = null;
//  Judge whether the node on the left is empty. If it is not empty, it will be searched recursively
//    If found, return the found node
if (this.leftNode != null) {
resNode = this.leftNode.postOrderSearch(no);
}
//If it is not null, it means that if it is found on the left, it can be returned directly
if (resNode != null) {
return resNode;
}
//  Judge whether the node on the right is empty. If it is not empty, it will be searched recursively
//    If found, return the found node
if (this.rightNode != null) {
resNode = this.rightNode.postOrderSearch(no);
}
//If it is not null, it means that if it is found on the right, it can be returned directly
if (resNode != null) {
return resNode;
}
System.out.println("Sequential search");
//If the left and right subtrees are not found, then compare whether the no of the current node is what we want to search
if (this.id == no) {
return this;
}
return resNode;
}

//    delete
public void deleteNode(int no) {
//    Traverse to the left. If the left subtree is a little, set the left subtree empty. If not, traverse the right
if (this.leftNode != null && this.leftNode.id == no) {
this.leftNode = null;
return;
}
//    Traverse to the right. If the right subtree is a little, set the left subtree empty. If there is no ready left or right, it should be deleted recursively
if (this.rightNode != null && this.rightNode.id == no) {
this.rightNode = null;
return;
}
//    If the above two steps are unsuccessful, let's delete recursively to the left first
if (this.leftNode != null) {
this.leftNode.deleteNode(no);
}

//    If the recursive deletion of the left subtree is not successful, the right subtree will be deleted recursively
if (this.rightNode != null) {
this.rightNode.deleteNode(no);
}
}
}```

#### Traversal cued binary tree

1. Description: traverse the binary tree of middle order cueing in front
2. Analysis: because the direction of each node changes after cueing, the original traversal method cannot be used. At this time, a new traversal method needs to be used Cued binary tree, each node can be traversed by linear way, so there is no need to use recursive way, which also improves the efficiency of traversal. The order of traversal should be consistent with that of middle order traversal.
```    public void preThreaddeList() {
//    Here we need a variable to store the current node
while (tempNode != null) {
/* Start loop traversal
* Loop to find the node with lefttype 1, so the first one to find is the node with node value of 8
* Later, it will change with traversal. When lefttype ==1 is found, it indicates that the tree has been cued
* After that, you only need to deal with the effective nodes after cueing
* */
while (tempNode.getLefttype() == 0) {
System.out.println(tempNode);
tempNode = tempNode.getLeftNode();
}
//    Because it is a medium order traversal, the order is: left, middle and right. Here, we are from the left lefttype==1, that is, it is the first node at the beginning of the left, so we can output it directly
System.out.println(tempNode);
// Traversal of this node
tempNode = tempNode.getRightNode();
}

}```

Added by Salkcin on Tue, 01 Mar 2022 06:43:06 +0200