Why do we need to cue the binary tree
Let's look at a question first
Construct the sequence {1, 3, 6, 8, 10, 14} into a binary tree. n+1=7
problem analysis:
1. When we traverse the above binary tree in order, the number 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 back nodes?
4. Solution-clue binary tree
Basic introduction to threaded binary tree
1. A binary linked list of n nodes contains n+1 [formula 2n-(n-1)=n+1] null pointer fields. Use the null pointer field in the binary linked list to store pointers to the predecessor and successor nodes of the node in a certain traversal order (this kind of additional pointers are called "clues")
2. This binary linked list with clues is called a thread linked list, and the corresponding binary tree is called a threaded binary tree. According to the nature of the clues, the clue binary tree can be divided into three types: preorder clue binary tree, middle order clue binary tree and postorder clue binary tree.
3. The previous node of a node is called the predecessor node and the next node of a node is called the successor node.
Create node
class HeroNode {
private int no;
private String name;
private HeroNode left;
private HeroNode right;
private HeroNode parent;
//true 表示是线索化节点
//false 表示不是线索化节点
private boolean ThreadedLeft = false;
private boolean ThreadedRight = false;
public HeroNode(int no, String name) {
this.no = no;
this.name = name;
}
public int getNo() {
return no;
}
public void setNo(int no) {
this.no = no;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public HeroNode getLeft() {
return left;
}
public void setLeft(HeroNode left) {
this.left = left;
}
public HeroNode getRight() {
return right;
}
public void setRight(HeroNode right) {
this.right = right;
}
public HeroNode getParent() {
return parent;
}
public void setParent(HeroNode parent) {
this.parent = parent;
}
public boolean isThreadedLeft() {
return ThreadedLeft;
}
public void setThreadedLeft(boolean threadedLeft) {
ThreadedLeft = threadedLeft;
}
public boolean isThreadedRight() {
return ThreadedRight;
}
public void setThreadedRight(boolean threadedRight) {
ThreadedRight = threadedRight;
}
@Override
public String toString() {
return "HeroNode{" +
"no=" + no +
", name='" + name + '\'' +
'}';
}
}
In-order threaded binary tree
Application case description: Take the following binary tree into an in-order clue binary tree. The sequence of middle order traversal is {8, 3, 10, 1, 14, 6}
Explanation: When the binary tree is threaded, the left and right attributes of the Node node are as follows:
1. Left refers to the left subtree, or the predecessor node that it points to. For example, ① the left subtree pointed to by the node left, and the left of the ⑩ node points to the predecessor node.
2. Right points to the right subtree, or it may point to the successor node. For example, ① The node right points to the right subtree, and the right of the ⑩ node points to the successor node.
The process of in-order threading
1. In the order of the middle order traversal, the first node to be traversed is 8, and the left pointer of the 8 node is null, so let the left pointer of the 8 node point to its predecessor node, which is null
pre and node move backward
2. Continue to traverse to 3 nodes in the middle order, and its left pointer is not null
pre is 8 nodes, and its right pointer is empty, so let his right pointer point to its successor node, which is 3.
pre and node move backward
3. Continue to traverse to 10 nodes, its left pointer is empty, so it points to its predecessor node
pre is 3 nodes and its right pointer is not empty
pre and node move backward
4. Continue to traverse to node 1, and its left pointer is not empty
The pre node is 10 nodes, and its right pointer is empty, so it points to the successor node 1.
pre and node move backward
5. Continue to traverse to node 14, because its left pointer is not empty, so it points to its predecessor node 1
The pre node is 1 node, and its right pointer is not empty
pre and node move backward
6. Continue to traverse to 6 nodes, and its left pointer is empty
The pre node is 14 nodes, because its right pointer is empty, so it points to its successor node 6
pre and node move backward
The above is a process of in-order threading nodes, please see the code implementation below
private void infixThreadedNode(HeroNode node) {
if (node == null) {
return;
}
//线索化左节点
infixThreadedNode(node.getLeft());
//线索化当前节点
if (node.getLeft() == null) {
node.setLeft(pre);
node.setThreadedLeft(true);
}
if (pre != null && pre.getRight() == null) {
pre.setRight(node);
pre.setThreadedRight(true);
}
pre = node;
//线索化右节点
infixThreadedNode(node.getRight());
}
In-order threaded traversal
public void infixThreadedList() {
HeroNode node = root;
while (node != null) {
while (!node.isThreadedLeft()) {
node = node.getLeft();
}
System.out.println(node);
while (node.isThreadedRight()) {
node = node.getRight();
System.out.println(node);
}
node = node.getRight();
}
}
Preorder threaded binary tree
Code
private void preThreadedNode(HeroNode node) {
//线索化当前节点
if (node == null)
return;
if (node.getLeft() == null) {
node.setLeft(pre);
node.setThreadedLeft(true);
}
if (pre != null && pre.getRight() == null) {
pre.setRight(node);
pre.setThreadedRight(true);
}
pre = node;
//线索化左节点
if (!node.isThreadedLeft()) {
preThreadedNode(node.getLeft());
}
//线索化右节点
if (!node.isThreadedRight()) {
preThreadedNode(node.getRight());
}
}
Pre-threaded traversal
public void preThreadedList() {
HeroNode node = root;
while (node != null) {
if (!node.isThreadedLeft()) {
System.out.println(node);
node = node.getLeft();
}
System.out.println(node);
node = node.getRight();
}
}
Post-cline binary tree
Code
private void postThreadedNode(HeroNode node) {
if (node == null)
return;
postThreadedNode(node.getLeft());
postThreadedNode(node.getRight());
if (node.getLeft() == null) {
node.setLeft(pre);
node.setThreadedLeft(true);
}
if (pre != null && pre.getRight() == null) {
pre.setRight(node);
pre.setThreadedRight(true);
}
pre = node;
}
Post-cline traversal
public void postThreadedList() {
HeroNode node = root;
while (node != null && !node.isThreadedLeft()) {
node = node.getLeft();
}
pre = null;
while (node != null) {
if (node.isThreadedRight()) {
System.out.println(node);
pre = node;
node = node.getRight();
} else {
if (node.getRight() == pre) {
System.out.println(node);
if (node == root)
return;
pre = node;
node = node.getParent();
} else {
node = node.getRight();
while (node != null && !node.isThreadedLeft()) {
node = node.getLeft();
}
}
}
}
}