[Java data structure] will not be a binary tree? A complete binary tree

Binary tree is one of our common data structures. Before learning binary tree, we need to know what is a tree and what is a binary tree. This article mainly describes the binary tree and the traversal of binary tree.

What knowledge can you get?

1. Introduction to the tree
2. Introduction to the binary tree
3. Four methods for traversing the binary tree
4. Niu Ke Topic: Reverse Binary Tree

1. Knowledge preparation

1. Tree

Tree (Tree) is a finite set of n (n> = 0) nodes.

The tree in the data structure can be seen as an inverted tree, with his 'root' above and his 'leaf' below.

graph TD 4-->2 4-->7 2-->1 2-->3 7-->6 7-->9

2. Introduction of tree related terms

  • 1. The node of the tree (node): contains a data element and several branches pointing to the subtree;
  • 2. Child node: The root of the node's subtree is called the child of that node. For node 4, node 2 and node 7 are the child nodes of node 4;
  • 3. Parent node: Node B is the child of node A, then node A is the parent of node B;
  • 4. Brother node: the child node of the same parent; cousin node: the node on the same layer;
  • 5. Ancestor nodes: all nodes on the branch from the root to the node
  • 6. The descendant node: any node in the subtree rooted at a node is called the descendant of the node
  • 7. Node layer: The layer of the root node is defined as 1; the child of the root is the node of the second layer, and so on;
  • 8. The depth of the tree: the largest node layer in the tree, the depth of the tree is three, because he has only three layers.
  • 9. The degree of the node: the number of node subtrees
  • 10. The degree of the tree: the largest node degree in the tree.
  • 11. Leaf nodes: also called terminal nodes, which are nodes with degree 0, for example, nodes 1, 2, 6, 9 are all leaf nodes;
  • 12. Branch node: a node whose degree is not 0;
  • 13. Ordered tree: an ordered tree of subtrees, such as a family tree;
  • 14. Unordered tree: Does not consider the order of subtrees;

1. Binary tree

Binary Tree (Binary Tree) each node has at most two sub-trees tree structure. So the binary tree is also a special kind of tree.

Usually we call the subtrees of the binary tree "left subtree" (left subtree) and "right subtree" (right subtree).

Binary trees are often used to implement binary search trees and binary heaps.

It can be seen from this that in a binary tree, each node has at most two nodes, that is, the degree of the node is less than or equal to two, that is, 0, 1, 2.

2. Binary tree type

  1. Full binary tree: Every node except the leaf nodes has left and right cotyledons and the leaf nodes are at the bottom of the binary tree.

  2. Complete binary tree: If the height of the binary tree is h, the number of nodes in all layers (1 ~ h-1) except the h-th layer reaches the maximum number, and the h-th layer has leaf nodes, and the leaf nodes are all Arranged in order from left to right, this is a complete binary tree.
    To put it simply: if the last layer of nodes in the binary tree is a full binary tree, and the nodes of the last layer are distributed from left to right, this binary tree is called a complete binary tree.

  3. Balanced binary tree: Balanced binary tree is also called AVL tree (different from AVL algorithm), it is a binary sorting tree, and has the following properties: it is an empty tree or the absolute difference in height between its left and right subtrees The value does not exceed 1, and the two left and right subtrees are a balanced binary tree.

Second, the binary tree practice (I did not swear)

1. Define the nodes of the binary tree

Define the structure of each node of the binary tree, he has left and right cotyledons, and has a value of val itself, define a constructor, a combination of multiple nodes is a binary tree.

    /**
     * Definition for binary tree
     */
    public static class TreeNode {
      //定义该结点值
      int val;
      //定义左结点
      TreeNode left;
      //定义右结点
      TreeNode right;

	  //定义一个构造函数
      TreeNode(int x) { val = x; }
    }

Illustration: The following illustration will be used to explain

graph TD 4-->2 4-->7 2-->1 2-->3 7-->6 7-->9

2. Traverse the binary tree (four methods)

There are four main methods for traversing a binary tree: ①: preorder traversal ②: midorder traversal ③: postorder traversal ④: sequence traversal

The first three traversals need to be explained in advance, that is, the access order of the root node is different, but the order of accessing the left and right nodes is still to visit the left node first and then the right node.

①: Preorder traversal

1. Access the root node;
2. Access the left subtree of the current node;
3. Access the right subtree of the current node;
that is, start from the root node, first visit the root node, and then access the left subtree of the root node. If there is a left subtree on the root node of the left subtree, the left subtree is accessed; otherwise, the right subtree is accessed, and so on.

Take the above picture as an example,

  1. Find the root node first, read 4,
  2. The node also has a left subtree, visit the root node of its left subtree, read 2,
  3. Node 2, and the left subtree, read 1,
  4. Node 1 has neither a left subtree nor a right subtree. Go back to the previous level, visit the right subtree of node 2, and read 3.
  5. At this time, the left and right subtrees of 3 should be visited, but no, return to the previous layer. At this time, the left and right subtrees of node 2 have been read. Return to the previous layer and read the right subtree of node 4. 7,
  6. Access the left subtree of node 7, read 6,
  7. Node 6 has no left and right subtrees, go back to the previous level, visit the right subtree of node 7, read 9,
  8. Node 9 has no left or right subtrees, and the binary tree has been traversed at this time.

So the order of access is:4 2 1 3 7 6 9

②: Mid-order traversal

1. Access the left subtree of the current node;
2. Access the root node;
3. Access the right subtree of the current node; the
traversal idea is similar to the previous sequence, except that the read root node is placed after the left node of the read, right Before the node

③: Post-order traversal

1. Access the left subtree of the current node;
2. Access the right subtree of the current node;
3. Access the root node; the
traversal idea is similar to the previous sequence, except that the read root node is placed after the left node of the read, right After the node

④: Sequence traversal

According to the hierarchical structure of the binary tree, the nodes are traversed from left to right. The
algorithm is to define a queue, starting from the root node of the tree, and enqueue its left and right children in sequence. Then every time a node in the queue leaves the team, its left and right children are enqueued until all the nodes in the tree are dequeued. The order of the nodes in the queue is the final result of the hierarchy traversal.

  1. The root node 4 enters the team,
  2. The root node 4 leaves the team, visits the left and right nodes (2, 7) of node 4, and enters the team in turn,
  3. Node 2 leaves the team, visits the left and right nodes (1, 3) of node 2, and enters the team in turn,
  4. Node 1 leaves the team, no child nodes, no need to enter the team,
  5. Node 3 leaves the team, no child nodes, no need to enter the team,
  6. Node 6 leaves the team, no child nodes, no need to enter the team,
  7. Node 9 leaves the team, no child nodes, no need to enter the team,
  8. The queue is empty and the traversal is complete.

The final access sequence is:4 2 7 1 3 6 9

Code:

    /**
     * 先序遍历(递归)
     * @param node
     */
    public void previous(TreeNode node) {
        if (node == null) {
            return;
        }
        System.out.print(node.val+"\t");
        this.previous(node.left);
        this.previous(node.right);
    }
    /**
     * 中序遍历(递归)
     * @param node
     */
    public void middle(TreeNode node) {
        if (node == null) {
            return;
        }
        this.middle(node.left);
        System.out.print(node.val+"\t");
        this.middle(node.right);
    }
    /**
     * 后序遍历(递归)
     * @param node
     */
    public void next(TreeNode node) {
        if (node == null) {
            return;
        }
        this.next(node.left);
        this.next(node.right);
        System.out.print(node.val+"\t");
    }
	    
	 /**
     * 遍历二叉树
     * 层序遍历(非递归)
     * @param node
     */
    public void bfs(TreeNode node){
        if (node == null) {
            return;
        }
        Queue<TreeNode> queue = new LinkedList<>();
        queue.add(node);
        while (!queue.isEmpty()){
            TreeNode current = queue.poll();
            System.out.print(current.val + "\t");
            //如果当前节点的左节点不为空入队
            if(current.left != null)
            {
                queue.offer(current.left);
            }
            //如果当前节点的右节点不为空,把右节点入队
            if(current.right != null)
            {
                queue.offer(current.right);
            }
        }
    }
遍历结果:
1、前序遍历:4	2	1	3	7	6	9	
2、中序遍历:1	2	3	4	6	7	9	
3、后序遍历:1	3	2	6	9	7	4	
4、层序遍历:4	2	7	1	3	6	9	

The non-recursive methods of the first three methods are attached here. Interested partners can study and research.
Attachment: non-recursive method The
main implementation is to rely on the stack to achieve

    /**
     * 先序遍历非递归
     * @param node
     */
    public void previous1(TreeNode node) {
        if (node == null) {
            return;
        }
        Stack<TreeNode> queue = new Stack<>();
        queue.add(node);
        while (!queue.isEmpty()) {
            TreeNode current = queue.pop();
            while(current!=null) {
                System.out.print(current.val + "\t");
                if (current.right!=null){
                    queue.push(current.right);
                }
                current = current.left;
            }
        }
    } 


	/**
     * 中序遍历(非递归)
     * @param node
     */
    public void middle1(TreeNode node) {
        Stack<TreeNode> stack = new Stack<>();
        while (!stack.isEmpty() || node !=null) {
            while (node != null){
                stack.push(node);
                node = node.left;
            }
            node = stack.pop();
            System.out.print(node.val + "\t");
            node = node.right;
        }
    }

	/**
     * 后序遍历(非递归)
     * @param node
     */
    public void next1(TreeNode node) {
        Stack<TreeNode> stack = new Stack<>();
        Stack<Integer> stack1 = new Stack<>();
        while (!stack.isEmpty() || node !=null) {
            while (node != null){
                stack.push(node);
                stack1.push(0);
                node = node.left;
            }
            while (!stack.isEmpty() && stack1.peek() == 1) {
                stack1.pop();
                System.out.print(stack.pop().val + "\t");
            }
            if (!stack.isEmpty()) {
                stack1.pop();
                stack1.push(1);
                node = stack.peek();
                node = node.right;
            }
        }
    }

Third, a small test cattle knife

Leetcode topic: Reverse Binary Tree

The original binary tree:

graph TD 4-->2 4-->7 2-->1 2-->3 7-->6 7-->9

After the algorithm, it needs to be converted to:

graph TD 4-->7 4-->2 2-->3 2-->1 7-->9 7-->6

Solution:
There are four methods for traversing the binary tree, so there are at least four solutions to this problem. If you understand the above traversal algorithm, then this question is a breeze.

The main idea: when traversing a node, that is, the operation of outputting the node is replaced with the position of the left and right nodes of the node.

/**
     * 反转二叉树
     * 前序反转
     * @param node
     */
    public void invertTree_previous(TreeNode node){
        if (node == null){
            return;
        }
        TreeNode node1 = node.left;
        node.left = node.right;
        node.right = node1;
        this.invertTree_previous(node.left);
        this.invertTree_previous(node.right);
    }

    /**
     * 反转二叉树
     * 中序反转
     * @param node
     */
    public void invertTree_middle(TreeNode node){
        if (node == null){
            return;
        }
        this.invertTree_middle(node.left);
        TreeNode node1 = node.left;
        node.left = node.right;
        node.right = node1;
        this.invertTree_middle(node.left);
    }

    /**
     * 反转二叉树
     * 后序序反转
     * @param node
     */
    public void invertTree_next(TreeNode node){
        if (node == null){
            return;
        }
        this.invertTree_next(node.left);
        this.invertTree_next(node.right);
        TreeNode node1 = node.left;
        node.left = node.right;
        node.right = node1;
    }


    /**
     * 反转二叉树
     * 层序反转
     * @param node
     */
    public void invertTree_bfs(TreeNode node){
        if (node == null) {
            return;
        }
        Queue<TreeNode> queue = new LinkedList<>();
        queue.add(node);
        while (!queue.isEmpty()){
            TreeNode current = queue.poll();
            TreeNode node1 = current.left;
            current.left = current.right;
            current.right = node1;
            //如果当前节点的左节点不为空入队
            if(current.left != null)
            {
                queue.offer(current.left);
            }
            //如果当前节点的右节点不为空,把右节点入队
            if(current.right != null)
            {
                queue.offer(current.right);
            }
        }
    }

answer:

1、转换前
前序遍历:4	2	1	3	7	6	9	
中序遍历:1	2	3	4	6	7	9	
后序遍历:1	3	2	6	9	7	4	
层次遍历:4	2	7	1	3	6	9	

2、转换后
前序遍历:4	7	9	6	2	3	1	
中序遍历:9	7	6	4	3	2	1	
后序遍历:9	6	7	3	1	2	4	
层次遍历:4	7	2	9	6	3	1	

Source code acquisition: Pay attention to the public number: Bo's Garden , reply: data structure binary tree

Your support is my biggest motivation

References:
1. Java data structure and algorithm (ten)-binary tree
2. Four traversal algorithms of binary tree
3. Java implements pre-order, middle-order, post-order and layer-order traversal of non-recursive tree

Guess you like

Origin www.cnblogs.com/lomtom/p/12717936.html