Current brain map:
one preface:
Summary of data structures and algorithms in the previous issue 2. The one-way linked list code is the basis of this article. One of the core ideas is very important: recursion. It can be said that if you master recursion, you have basically achieved half of the success of manually implementing these data structures;
In this issue, we begin to simulate the traversal of binary tree with manual code;
II. Basic knowledge paving:
2.1 what is a tree?
A tree is a collection of n (n ≥ 0) finite elements:
1. Empty tree when n = 0
2.n>0 When: there is only one element called root and m disjoint finite sets (m > 0). Each finite set can also be regarded as a subtree.
3. Node: in the tree, an element is also called a node
2.1.1 Why is tree structure important?
In terms of query operation and maintaining relative order, tree structure has advantages over linked list, and tree structure is a very common structure in life. Many transactions in life can be represented by tree structure. Can you think of any life examples that meet the above three characteristics?
Case 1 Family tree:
Case 2 product function partition:
Case 3 directory closely related to your study
One picture wins a hundred words! The above structures, including the first brain map, can be said to be tree structures;
With regard to the application of tree (search + maintain relative order), I have written the structure of mysql index as an example before, which involves the tree structure; After reading this article, you can challenge to read:
Learning notes -- mysql index underlying data structure_ Stefansss blog - CSDN blog
2.2 what is a binary tree?
As the name suggests, a node has a tree structure with up to two left and right nodes;
2.2.1 please point out which binary trees are in the following figure? And find their root node and leaf node;
Here 's the answer !!! No picture, say J8;
These are all binary trees, but some are complete binary trees, some are full binary trees, and some are incomplete binary trees;
Where is it What about root nodes, leaf nodes and subtrees?
As shown in the figure. (a picture is worth 100 words of official explanation of Du Niang);
2.2.2 What is a full binary tree?
First, if a binary tree node has two left and right child nodes, the left one is the left child node and the right one is the right child node: (as shown in the figure)
Full binary tree means that each non leaf node has left and right children, and all leaf nodes are at the same level;
The above figure is obviously not a full binary tree. Node 6 has no right child nodes. Can you add to make it a full binary tree? Go one
2.2.3 what is a complete binary tree?
From Du Niang: a binary tree with n nodes with a depth of k. the nodes in the tree are numbered from top to bottom and from left to right. If the node numbered i (1 ≤ i ≤ n) and the node numbered i in the full binary tree are in the same position in the binary tree, the binary tree is called a complete binary tree.
Anyway, I don't understand!
Let's take an example:
First, a full binary tree. If you want to meet the requirements of a complete binary tree, you must follow
The same level is left from right to left, and different levels are discarded in order from bottom to top, and the order cannot be skipped; If this is satisfied, it is a complete binary tree;
For example, the right tree in the figure above is a full binary tree, and the left tree is a right tree. On the third layer, remove one from right to left, So The left tree is a complete binary tree.
Another example is the full binary tree on the right of the above figure, and the tree on the left is the right tree. On the third layer, the first one is removed in order from right to left, but the second one is not removed in order, and the order is skipped; So the left tree of this graph is not a complete binary tree; By analogy, the tree that removes the nodes of the previous level in jump order is not a complete binary tree; (I think I understand this explanation. If you don't understand it, I can explain it in more detail);
three Code traversal of binary tree
3.1 there are two ways to realize the structure of binary tree:
1. Array 2. Linked list. This article adopts the linked list method; If you want to try the array, you can try it yourself;
three point two Tips for array implementation:
If the subscript of the parent node into the array is X, the subscript of the left child node into the array is 2X+1, and the subscript of the left child node into the array is 2X+2.
3.3 basic knowledge literacy realized by linked list:
3.3.1 the API of LinkedList: removeFirst();
That is, remove the first node of the linked list and return the value in the removed node;
//LinkedList source code, with some remarks public E removeFirst() { final Node<E> f = first; if (f == null) throw new NoSuchElementException(); return unlinkFirst(f); } private E unlinkFirst(Node<E> f) { // assert f == first && f != null; // Get the element of the header node final E element = f.item; //Get the next node final Node<E> next = f.next; //Delete item in header node f.item = null; //Make the next node the head node f.next = null; // help GC first = next; if (next == null) last = null; else next.prev = null; size--; modCount++; //Returns the item object in the deleted node return element; }
3.3.2 handwritten one-way linked list (remove) :
The one-way linked list deletes the element at the specified position and returns the object code of the deleted element: (related to the next interview question)
/** * Idea: the for loop calls the next node until index = the specified location i, and gets the previous node of the deleted node, because the original connection needs to be disconnected and a new connection needs to be established; * (Note: the index loop condition needs to be 1 at the beginning or index < I - 1 at the end) * Get the node before the specified deletion location, and change the next node of the previous node into the next node of the node to be deleted * Returns the item object of the deleted node */ public T remove(int i) { if (i < 0) { //You can also throw an exception throw new IndexOutOfBoundsException("length exception"); return null; } Node node = head.next; for (int index = 1; index < i; index++) { node = node.next; } Node nodeDelete = node.next; node.next = nodeDelete.next; return nodeDelete.item; }
3.3.3 binary tree traversal method:
-
Depth first traversal: pre order traversal, middle order traversal and post order traversal (preferred in this article)
-
Breadth first traversal: sequence traversal (a little troublesome, you can try if you are interested)
-
Preorder traversal: the output order is the root node, left subtree and right subtree, as shown in the figure:
PS: Digital is the order of output;
2. Middle order traversal: the output order is left subtree, root node and right subtree, as shown in the figure:
-
3. Post order traversal: the output order is left subtree, right subtree and root node, as shown in the figure:
I haven't figured out the above three concepts for the time being. I can think about the process together with the code. I didn't think about it at the beginning. I used the most stupid method, but it's also the method that I can think of 100% to understand the whole process: suppose a three-layer seven element binary tree like the one in the above figure, and start traversing the following code, Each step of the code, one element at a time, is continuously put on the stack until it recurses to the end, and then comes out of the stack in turn; This learning process takes a long time, but you can basically understand it after walking. To put it bluntly, it depends on your own time. It's no use just reading;
3.3.4 Specific code implementation:
The first step is to turn the linked list into a binary tree
/** * Convert list to binary tree * Use the removefirst API to put the elements into the binary tree one by one * The node returned by the createBinaryTree method of the recursion establishment condition is not empty * Break the recursive condition, list.size() == 0; * Finally, the root node TreeNode is returned */ public TreeNode createBinaryTree(LinkedList<T> list) { //Judge first if (list.size() == 0) { return null; } TreeNode<T> treeNode = null; T data = list.removeFirst(); //There are no more elements if (data != null) { treeNode = new TreeNode<>(data); treeNode.leftChildNode = createBinaryTree(list); treeNode.rightChildNode = createBinaryTree(list); } return treeNode; }
Step 2: start recursion (preorder traversal)
//Recursion, preorder traversal public TreeNode preTraverse(TreeNode<T> treeNode) { //check if (valid(treeNode)) { return null; } System.out.println("data: " + treeNode.data); if (treeNode.leftChildNode != null) { return preTraverse(treeNode.leftChildNode); } if (treeNode.rightChildNode != null) { return preTraverse(treeNode.rightChildNode); } return null; } /*//Preorder traversal writing method 2 simplified version public void preTraverse2(TreeNode<T> treeNode) { //check if (treeNode == null) { return; } System.out.println("data: " + treeNode.data); preTraverse(treeNode.leftChildNode); preTraverse(treeNode.rightChildNode); }*/
Step 3 Medium order traversal
//Recursion, medium order traversal public TreeNode inTraverse(TreeNode<T> treeNode) { //check if (valid(treeNode)) { return null; } if (treeNode.leftChildNode != null) { return preTraverse(treeNode.leftChildNode); } System.out.println("data: " + treeNode.data); if (treeNode.rightChildNode != null) { return preTraverse(treeNode.rightChildNode); } return null; }
Step 4 post order traversal
//Recursion, postorder traversal public TreeNode backTraverse(TreeNode<T> treeNode) { if (valid(treeNode)) { return null; } if (treeNode.leftChildNode != null) { return preTraverse(treeNode.leftChildNode); } if (treeNode.rightChildNode != null) { return preTraverse(treeNode.rightChildNode); } System.out.println("data: " + treeNode.data); return null; }
3.3.5 Complete code and test (you can directly copy the past)
package com.treelist; import java.util.Arrays; import java.util.LinkedList; /** * Simulate a binary tree. The Node of the binary tree contains three attributes leftChild rightChild data */ public class MyTreeList<T> { private TreeNode rootNode; /** * Convert list to binary tree * Use the removefirst API to put the elements into the binary tree one by one * The node returned by the createBinaryTree method of the recursion establishment condition is not empty * Break the recursive condition, list.size() == 0; * Finally, the root node TreeNode is returned */ public TreeNode createBinaryTree(LinkedList<T> list) { //Judge first if (list.size() == 0) { return null; } TreeNode<T> treeNode = null; T data = list.removeFirst(); //There are no more elements if (data != null) { treeNode = new TreeNode<>(data); treeNode.leftChildNode = createBinaryTree(list); treeNode.rightChildNode = createBinaryTree(list); } return treeNode; } //Recursion, preorder traversal public TreeNode preTraverse(TreeNode<T> treeNode) { //check if (valid(treeNode)) { return null; } System.out.println("data: " + treeNode.data); if (treeNode.leftChildNode != null) { return preTraverse(treeNode.leftChildNode); } if (treeNode.rightChildNode != null) { return preTraverse(treeNode.rightChildNode); } return null; } /*//Preorder traversal writing method 2 simplified version public void preTraverse2(TreeNode<T> treeNode) { //check if (treeNode == null) { return; } System.out.println("data: " + treeNode.data); preTraverse(treeNode.leftChildNode); preTraverse(treeNode.rightChildNode); }*/ //Recursion, medium order traversal public TreeNode inTraverse(TreeNode<T> treeNode) { //check if (valid(treeNode)) { return null; } if (treeNode.leftChildNode != null) { return preTraverse(treeNode.leftChildNode); } System.out.println("data: " + treeNode.data); if (treeNode.rightChildNode != null) { return preTraverse(treeNode.rightChildNode); } return null; } //Recursion, postorder traversal public TreeNode backTraverse(TreeNode<T> treeNode) { if (valid(treeNode)) { return null; } if (treeNode.leftChildNode != null) { return preTraverse(treeNode.leftChildNode); } if (treeNode.rightChildNode != null) { return preTraverse(treeNode.rightChildNode); } System.out.println("data: " + treeNode.data); return null; } //check public boolean valid(TreeNode<T> treeNode) { if (treeNode == null) { return true; } else { return false; } } //Create nodes public static class TreeNode<T> { private T data; private TreeNode leftChildNode; private TreeNode rightChildNode; //Construction method public TreeNode() { this.data = null; } //Parametric construction method public TreeNode(T data) { this.data = data; } } //Test traversal binary tree public static void main(String[] args) { MyTreeList<Integer> treeList = new MyTreeList<>(); Integer[] integers = {1, 3, 5, 7, 9, 0, 78, 65, 33, 123}; LinkedList<Integer> linkedList = new LinkedList<>(Arrays.asList(integers)); TreeNode treeNode = treeList.createBinaryTree(linkedList); System.out.println("Preorder traversal"); treeList.preTraverse(treeNode); System.out.println("Medium order traversal"); treeList.inTraverse(treeNode); System.out.println("Postorder traversal"); treeList.backTraverse(treeNode); } }
Today's main course, handwritten binary tree traversal code, this is the end;
IV. Tencent on-site Code algorithm interview question: how to delete the nodes of the linked list?
The one-way linked list provides the value of the head node and the node to be deleted: define a function to delete the node and return the head node of the deleted linked list;
After careful analysis, the core idea of the remove()API is the same as that of the just simulated one-way linked list. Change the soup without changing the dressing;
public T remove(T t) { //Security verification if (t == null) { throw new NullPointerException("Content is empty"); } //Define a node pointer to record the current node Node node = head.next; //The nodeLast pointer records the previous node of the current node Node nodeLast = null; //Define a variable record index subscript int index = 0; //When the item in the node is equal to the incoming t, the loop is broken while (node.item != t) { nodeLast = node; node = node.next; index++; } //If the node (header node) of index 0 is removed, special processing is required if (index == 0) { head.next = node.next; } else { nodeLast.next = node.next; } length--; return head.next.item; }
Test results:
public class LinkListTest { public static void main(String[] args) { MyLinkList<String> list = new MyLinkList<String>(); list.insert("Zhang San"); list.insert("Li Si"); list.insert("Wang Wu"); list.insert(2, "penis"); System.out.println("list.get(0) = " + list.get(0)); System.out.println("list.get(1) = " + list.get(1)); System.out.println("list.get(2) = " + list.get(2)); System.out.println("list.get(3) = " + list.get(3)); System.out.println("---------------------------"); String remove = list.remove("Zhang San"); System.out.println("Head node item: " + remove); String remove2 = list.remove("penis"); System.out.println("Head node item: " + remove2); } }
Print results:
Here is the solution of a big man. I think it is more concise. If you want to refer to it, you can see:
Tencent Interviewer: how to delete the node of the linked list?
V. summary and forecast for the next period:
I feel I have made progress 😄
When learning such abstract things as structure and algorithm, it's difficult to feel where I've made progress because it's difficult to have something to fall on the ground. However, when I happened to see a live code algorithm problem of Tencent today, I actually had ideas rather than confused. At that moment, I felt it was meaningful to stick to it and summarized my learning experience:
1. If you don't understand it at all, you can watch the video first. Many big guys can do animation, which is suitable for getting started.
2. First try to implement the API with your own code. If the code doesn't come out, imitate the boss's code, and then get rid of the dependency and code independently! Focus on the process of trying and correcting mistakes!
3. If you encounter some concepts that are very difficult to understand, skip them without affecting the overall understanding, and come back to ponder this difficulty after completing them.
4. It is strongly recommended to summarize the knowledge in modules, and try to write the process, code and code comments, at least try to explain yourself clearly, because teaching is the best learning!
Forecast for next period:
AVL tree, red black tree, B tree, B + tree concept literacy, and handwritten AVL, red black tree basic code implementation ~
I'm afraid I can't realize it 😂 Slap in the face! So in order to force yourself, speak out your heroic words first, and you have to do it for face!
Thank you again for the systematic knowledge and creative inspiration brought by the comic algorithm of little gray and the big talk data structure;
Slow bird flies, slow is fast! Do not seek to ascend the sky step by step, but to make a little progress today than yesterday;
This weekend, I wish you all a happy weekend ~ tomorrow I'm going to climb Baiyun Mountain to exercise!
Nine to six! Weekend weekend! Study after work! Mountain climbing on weekends! Beautiful, beautiful!
In addition, I will continue to update the data structure and algorithm handwritten JAVA code. I will go to to study a major course of computer science, operating system, and record it on the road of self-study. If you want to make up for the bad half, please pay attention to the official account of "slow bird" and work together to learn together.