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;
- If it is not found, an empty node is returned
/** * @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 found, return in advance; 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 found, return in advance; if (resultNode != null) { return resultNode; } //Right subtree recursion; if (this.right != null) { resultNode = this.right.suffixSearch(val); } //If found, return in advance; 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}