Programmer, your heart is no point tree it?

Tell me, do not be angry, I did not call you do not despise you mean, today is simply to want everyone to share the knowledge of the tree, but I have to say as a programmer, his heart there is no point tree? You can not count it? Closer to home, the tree is one of our common data structure, there are many types of binary tree, binary search tree, balanced binary tree, red-black tree, B tree, B + tree, etc., we have to talk about tree-related binary tree today.

What is a tree?

First of all we need to know what is the tree? We usually are up in the tree branches while they have long does not form a closed loop, the data structure of the tree with us we usually see similar trees, precisely, is similar with the roots grow, I drew a picture map, give you a better understanding of the tree.

FIG 1, FIG 2 is a tree, the tree in FIG. 3 not. Each red circle we call the elements are also called nodes, with lines connecting two nodes, the two nodes to form a parent-child relationship, a parent with a child node becomes the sibling nodes, like our family relations , one father called brothers and sisters in the family of which the largest is called I, which is the same tree, but I do not call, called nodes with no child node is called a leaf node. Do we take the example of FIG. 1, A is the root node, B, C of sibling nodes, E, F is a leaf node.

Tree will be involved in three concepts 高度, , 深度, let's take a look at the definition of these three terms:

Height : node to the leaf node of the longest path, starting from zero count

Depth : with the number of edges subjected to the node to node, starts counting from 0

Layer : the root node from a distance, start counting from 1

Once you know the concept of three terms, we use a diagram to represent the image of more of these three concepts.

These are the basic concepts of tree species of the tree lot, we mainly learn binary tree.

Binary Tree

Binary tree as its name suggests, each element has at most two nodes, the nodes are called left and right node. Of course, not every element needs to have two nodes, and some may be left node, and some may be in the right node. Like countries to open a second child, like, not everyone needs to have two children. Let us look at a typical binary tree.

Based on different storage modes of the tree, in order to make better use of storage space, a complete binary tree and binary tree is divided into non-complete binary tree, we take a look at what is a complete binary tree, a non-complete binary tree?

Complete binary tree defined : leaf node in the bottom two layers, the last layer of the left leaf node are arranged, and except for the last one, the number of layers of other nodes must be maximized

Maybe look definitions do not understand, we look at a few pictures, you will be able to fully understand what is binary, non-complete binary tree.

1, complete Nimata 树

Full Nimata 树

2, non-full Nimata 树

We said above the tree based on different storage mode, and is divided into non-complete binary tree complete binary tree, that we are going to look at storage mode tree.

Binary Tree's storage mode

There are two modes of storing binary tree, one is based on a pointer or reference binary linked storage method , one is based on an array of sequential storage method

Chain store binary method

Chain storage method is relatively simple, it is also very easy to be understood, each node has three fields, a field stores a value of the node, the other two left and right reference fields stored in the node. We along with byte can easily string together the entire tree structure of the storage method of the chain probably be so long.

Method sequential storage

Sequential storage method is based on the realization of an array, the array is an orderly period of memory space, if we coordinate with the positioning node i= 1, the left node is 2 * i= 2, the right node * 2 i+ 1 = 3, and so on, each node so considered, then it will be converted into an array of trees, and in turn, we are able to follow this rule array transformed into a tree. See here I think you must have seen a number of drawbacks, if this is an unbalanced binary tree is not it will cause a lot of wasted space it? Yes, this is why you need points and non-complete binary tree complete binary tree. Look at each of these two trees based storage array.

Method sequential storage complete binary tree

Method of non-sequential storage complete binary tree

After transformation into an array in the tree can be seen from the FIG., A complete binary array to store only an index for the waste storage 0, the two non-complete binary tree waste a lot of space. If the tree is a complete binary tree, with the storage array than the chain storage space saving, because the information about the storage array of storage node need not

We understand that the above definition of binary tree, type, storage methods, let's look together to traverse the binary tree, binary tree traversal problem is often encountered in the interview.

Traversing Binary Tree

To understand the binary tree traversal, we first need to instantiate out of a binary tree, we use the chain store way to define the tree, the tree needs to be instantiated node information tree, used to store information of the node, because we are using a chain store, so our node information below.

/**
 * 定义一棵树
 */
public class TreeNode {
    // 存储值
    public int data;
    // 存储左节点
    public TreeNode left;
    // 存储右节点
    public TreeNode right;

    public TreeNode(int data) {
        this.data = data;
    }
}

复制代码

After defining the node information, we can initialize a tree friends, here is a process of initializing the tree:

public static TreeNode buildTree() {
    // 创建测试用的二叉树
    TreeNode t1 = new TreeNode(1);
    TreeNode t2 = new TreeNode(2);
    TreeNode t3 = new TreeNode(3);
    TreeNode t4 = new TreeNode(4);
    TreeNode t5 = new TreeNode(5);
    TreeNode t6 = new TreeNode(6);
    TreeNode t7 = new TreeNode(7);
    TreeNode t8 = new TreeNode(8);

    t1.left = t2;
    t1.right = t3;
    t2.left = t4;
    t4.right = t7;
    t3.left = t5;
    t3.right = t6;
    t6.left = t8;

    return t1;
}
复制代码

After the above steps, we will grow into a tree shape shown in the figure, the digital values ​​representative of the node.

After With tree, we can traverse the tree it, there are three ways the binary tree traversal, a preorder traversal, in order traversal, three kinds subsequent traversal of traversal, there are three kinds of relationship sequential output node traversal. Let's look at each of these three traversal.

Preorder traversal

Preorder traversal : for any node in the tree, the first printing of this node, and then print it left subtree, and finally print its right subtree.

In order to facilitate the understanding, based on my binary tree above our definition, the implementation process of the three traversal methods have created a dynamic map, want to help your reading, we take a look preorder traversal of dynamic execution flow chart .

Understand the concept before and after traversing dynamic execution flow chart before reading order traversal, mind you definitely want to know, how to how to achieve a preorder traversal of the tree in your code? Binary tree traversal is very simple, are generally used recursively traverse, let's look at the code preorder traversal of:

// 先序遍历,递归实现 先打印本身,再打印左节点,在打印右节点
public static void preOrder(TreeNode root) {

    if (root == null) {
        return;
    }
    // 输出本身
    System.out.print(root.data + " ");
    // 遍历左节点
    preOrder(root.left);
    // 遍历右节点
    preOrder(root.right);
}
复制代码

Preorder

Preorder : for any node in the tree, the first print its left subtree, and then print it themselves, and finally print its right subtree.

As front-order traversal, we look fancy traversing dynamic execution flow chart.

Inorder traversal code:

// 中序遍历 先打印左节点,再输出本身,最后输出右节点
public static void inOrder(TreeNode root) {
    if (root == null) {
        return;
    }
    inOrder(root.left);
    System.out.print(root.data + " ");
    inOrder(root.right);
}
复制代码

Postorder

Postorder : for any node in the tree, the first print its left subtree, and then print it right subtree, and finally print the node itself.

In front of two kinds of traversing the same, after understanding the concept, we first look at the figures.

Postorder implementation code:

// 后序遍历 先打印左节点,再输出右节点,最后才输出本身
public static void postOrder(TreeNode root) {
    if (root == null) {
        return;
    }
    postOrder(root.left);
    postOrder(root.right);
    System.out.print(root.data + " ");
}
复制代码

Binary tree traversal is very simple, although there are three ways to traverse, but all the same, but the order of the output just not the same, after so many of the above study, I believe you must have a lot of knowledge of the binary tree, then Let's understand a common and relatively unique binary: binary search tree

Binary search tree

Binary search tree, also known as binary search trees, from the name we can know that this tree must have in terms of look extraordinary advantages, is indeed the case, binary search tree is indeed a tree to look born, but it supports not only quickly find the data, but also support to quickly insert, delete data. How does it do this it? We start with the concept of a binary search tree begin to understand.

Binary search tree : any node in the tree, each node of the value of its left subtree of this node must be less than the value, the value of the right subtree of this node is greater than the value of the node.

Difficult to understand? Remember? It does not matter, here I define a binary search tree, we are facing the tree to slowly understand.

According to the definition of a binary search tree, the value of each tree node is left which is smaller than the parent node, the node is greater than the value of the right parent node. 62 nodes all left node values should be less than 62, all the right node values should be greater than 62. For each node of the tree Fengyun must meet this condition, we take our tree to another node 35, the node value of its right sub-tree maximum can not exceed 47, because 35 is the left subtree 47 according to the rules of binary search tree, the value of the left subtree is less than the value of the node.

Since the binary search tree to find the name with the word, then we will find a binary search tree from a binary search tree to start learning it.

Find operate a binary search tree

Because of the characteristics of a binary search tree, we need to find a data comparison should talk with the node, if the node is equal with the root node is returned, if less than the root node in the left subtree is inevitable here, as long as the left child recursive search tree on the line, if more than this in the right sub-tree here, recursively to the right subtree. This can be achieved quickly find, because every time to find the data are cut in half, with half of look somewhat similar, quickly insert, delete all living in this feature implemented.

Here we use a dynamic map to enhance the understanding of the process to find a binary search tree, we need to find a value equal to 37 nodes in the above Fengyun binary search tree, we take a look at is how to achieve a flow chart .

Binary search tree of the search operation

  • 1, first with 37 with 62 compared to 37 <62, continue to find in the left subtree
  • 2, the left subtree node 58,37 is <58, and look in the left subtree
  • 3, left subtree node 47,37 is <47, and look in the left subtree
  • 4, left subtree is the node 35, 37> 35, looking up in the right subtree
  • 5, the right subtree of a node is 37, 37 = 37, the node returns

After looking finished concept, we take a look at the code lookup operation of a binary search tree implementation

/**
 * 根据值查找树
 * @param data&emsp;值
 * @return
 */
public TreeNode find(int data) {
    TreeNode p = tree;
    while (p != null) {
        if (data < p.data) p = p.left;
        else if (data > p.data) p = p.right;
        else return p;
    }
    return null;
}
复制代码

Binary search tree insertion

Find insert with almost as well start looking at the root, if you want to insert data than large data node and the right child node of the tree is empty, it will position the new data directly into the right child; if not empty, then recursively traverse the right subtree, find the insertion position. Similarly, if the data to be inserted is smaller than the value of the node, and the node's left subtree is empty, new data will be inserted into the position of the left child node; if not empty, it is then recursively traverse the left subtree, to find the insertion position .

Suppose we want to insert 63, we use a dynamic map to see the insertion process.

  • 1,63> 62, continue to find the right child tree.
  • 2,63 <88, in the left sub-tree continues to look for
  • 3,63 <73, because 73 is a leaf node, so 63 becomes the left subtree 73.

Let's look at the binary search tree insert implementation code

/**
 * 插入树
 * @param data
 */
public void insert(int data) {
    if (tree == null) {
        tree = new TreeNode(data);
        return;
    }

    TreeNode p = tree;

    while (p != null) {
        // 如果值大于节点的值,则新树为节点的右子树
        if (data > p.data) {
            if (p.right == null) {
                p.right = new TreeNode(data);
                return;
            }
            p = p.right;
        } else { // data < p.data
            if (p.left == null) {
                p.left = new TreeNode(data);
                return;
            }
            p = p.left;
        }
    }
}
复制代码

Binary search tree deletion

Delete logical than to find and insert more complex, delete points about three cases:

The first case : If you want to delete a node has no child nodes, we need only direct parent node, point you want to delete a node pointer is set to null. For example, deleting a node 51 in FIG.

The second case : If the node you want to remove only one child node (only the left child or the right child node), we only need to update the parent node, point you want to delete a node pointer to point to the child node to remove the node on it. For example, to delete a node 35 in the figure.

The third case : If you want to delete a node has two children, which is more complicated. We need to find the right child node of the smallest node in the tree, to replace it on the node to be deleted. And then delete the minimum node, because the minimum is certainly not left child node (if there is a left child node, it is not the smallest node), so we can apply two rules above to remove the smallest node. For example, deleting a node 88 in FIG.

The first two cases a little simpler, the third case, I created a dynamic map, hoping to help you.

Let's look at a binary search tree delete operations implementation code

public void delete(int data) {
    TreeNode p = tree; // p指向要删除的节点,初始化指向根节点
    TreeNode pp = null; // pp记录的是p的父节点
    while (p != null && p.data != data) {
        pp = p;
        if (data > p.data) p = p.right;
        else p = p.left;
    }
    if (p == null) return; // 没有找到

    // 要删除的节点有两个子节点
    if (p.left != null && p.right != null) { // 查找右子树中最小节点
        TreeNode minP = p.right;
        TreeNode minPP = p; // minPP表示minP的父节点
        while (minP.left != null) {
            minPP = minP;
            minP = minP.left;
        }
        p.data = minP.data; // 将minP的数据替换到p中
        p = minP; // 下面就变成了删除minP了
        pp = minPP;
    }

    // 删除节点是叶子节点或者仅有一个子节点
    TreeNode child; // p的子节点
    if (p.left != null) child = p.left;
    else if (p.right != null) child = p.right;
    else child = null;

    if (pp == null) tree = child; // 删除的是根节点
    else if (pp.left == p) pp.left = child;
    else pp.right = child;
}
复制代码

We understand some of the above binary search tree of knowledge, because the binary search tree in extreme cases, degenerate into a linked list, for example, each node has only one node left, this is the time complexity becomes O (n) to avoid this situation, the emergence of a new tree called balanced binary search tree related, due to the space available here a little longer, I believe you see here has been a bit tired junior partner, on balanced binary search tree I do not knowledge presented here.

If you find a bug article, you also pointed out, if you think I write well, welcome to share your article to be read in conjunction junior partner, and I also created a public number, if you are interested can follow the public number, learning exchange.

Personal Public Number

Reference material

  • US data structures and algorithms of (geeks time)

Guess you like

Origin juejin.im/post/5d42d962f265da03c502ef7a