Binary tree (1): depth-first traversal and breadth-first traversal

Preface: Binary tree is a very efficient data structure. The tree structure can efficiently search and search semantics. For example, the tree is kused in the nearest neighbor algorithm kdto store training data, which greatly improves kthe efficiency of the nearest neighbor search. Another example is the file manager of the computer. , all adopt a tree structure, and searching through the tree will become very fast. In short, the binary tree data structure is widely used and can greatly improve the search efficiency. This article will comprehensively explain the binary tree structure and the related algorithms of the binary tree. I believe it will be of great help to everyone's learning of data structures and algorithms.

Table of contents

1. Basic concept of binary tree

2. Preorder, inorder and postorder traversal of binary tree

2.1 Recursive order

2.1.1 Preorder traversal

2.1.2 Inorder traversal

2.1.3 Post-order traversal

2.2 Non-recursive order

2.2.1 Preorder traversal

2.2.2 Inorder traversal

2.2.3 Post-order traversal

3. Depth-first traversal and breadth-first traversal of binary tree

3.1 Depth-first traversal

3.2 Breadth-first traversal


1. Basic concept of binary tree

       A binary tree is a special tree structure. The degree of each node is up to 2, and there are left child nodes and right child nodes. The order of the subtrees cannot be reversed, so the binary tree is an ordered tree. Each node in the binary tree contains three basic information: the data value stored by itself, the left child node left, and the right child node right. The child nodes also have such an information structure, and the continuous extension like this forms a binary tree structure, as shown in the figure 1, ①-⑩ represent 10 nodes respectively.

 figure 1

In addition, for convenience, you can write a class to represent the nodes in the tree, the code is as follows:

class Node {
    int value;        //存放的数据
    Node left;        //左子节点
    Node right;       //右子节点

    public Node() {        //无参构造函数
    }

    public Node(int value) {        //有参构造函数
        this.value = value;
    }
}

2. Preorder, inorder and postorder traversal of binary tree

        There are many traversal methods for binary trees. Here are three traversal methods of pre-order, in-order and post-order. These three traversal methods can be implemented in code using recursive and non-recursive ideas. The amount of code using recursive thinking Very little, but it may not be easy to understand, and the amount of code using non-recursive thinking is very large, but it is very easy to understand.

2.1 Recursive order

        Before explaining, let me help you sort out the process of binary tree recursion. Give an example: print the data stored in each node of the binary tree in Figure 2.

figure 2

When recursive, the sequence is: 1-2-4-4-4-2-5-5-5-2-1-3-6-6-6-3-7-7-7-3-1, The so-called pre-order traversal printing is to print the data stored in each node when each node appears for the first time in the recursive order; in-order traversal printing is to print the data stored in each node when each node appears for the second time in the recursive order; Post-order traversal printing is to print the data stored in each node when each node appears for the third time in the recursive order.

2.1.1 Preorder traversal

       According to the above introduction, the printing order of each node in preorder traversal is: 1-2-4-5-3-6-7. It is not difficult to find that pre-order traversal traverses all subtrees in the order of head node = "left child node = "right child node . The recursive code for pre-order traversal is as follows:

    //1.先序遍历打印
    public void preOrderRecur(Node head) {
        if (head == null) {
            return;
        }
        System.out.print(head.value + " ");
        preOrderRecur(head.left);
        preOrderRecur(head.right);
    }

2.1.2 Inorder traversal

        The printing order of each node in the in-order traversal is: 4-2-5-1-6-3-7. It is not difficult to find that in-order traversal traverses all subtrees in the order of left child node = "head node = "right child node, and the recursive code for in-order traversal is as follows:

//2.中序遍历打印
    public void inOrderRecur(Node head) {
        if (head == null) {
            return;
        }
        inOrderRecur(head.left);
        System.out.print(head.value + " ");
        inOrderRecur(head.right);
    }

2.1.3 Post-order traversal

        The printing order of each node in postorder traversal is: 4-5-2-6-7-3-1. It is not difficult to find that post-order traversal traverses all subtrees in the order of left child = "right child = "head node, and the recursive code for post-order traversal is as follows:

 //3.后序遍历打印
    public void behindOrderRecur(Node head) {
        if (head == null) {
            return;
        }
        behindOrderRecur(head.left);
        behindOrderRecur(head.right);
        System.out.print(head.value + " ");
    }

2.2 Non-recursive order

2.2.1 Preorder traversal

        Preorder traversal: head node = "left child node = "right child node

The specific implementation process of the algorithm is as follows (open up a stack space):

① Push the head node into the stack first;

②while (square non-empty):

                         1) Pop a node cur from the stack

                         2) Printing or other operations process cur

                         3) First push the right child of cur onto the stack, and then push the left child of cur onto the stack (provided that cur has left and right children)

Note: The stack is characterized by last-in-first-out .

The non-recursive code for preorder traversal is as follows:

 //1.先序打印
    public void perOrderUnrecur(Node head) {
        System.out.println("pre-order: ");
        if (head != null) {
            Stack<Node> stack = new Stack<>();
            Node cur;
            stack.add(head);
            while (!stack.isEmpty()) {
                cur = stack.pop();
                System.out.print(cur.value + " ");
                if (cur.right != null) {
                    stack.push(cur.right);
                }
                if (cur.left != null) {
                    stack.push(cur.left);
                }
            }
        }
        System.out.println();
    }

2.2.2 Inorder traversal

        In-order traversal: left child node = "head node = "right child node

The specific implementation process of the algorithm is as follows (open up a stack space):

① Push the left children of all subtrees of the root node head of the binary tree onto the stack, starting from the head, and then the left child of the head, the left child of the left child of the head...

②while(non-empty):

                 1) Pop a node cur from the stack

                 2) Printing or other operations process cur

                 3) Push the left children of all subtrees of the right subtree of cur onto the stack, starting from the right child of cur, then cur the left child of the right child, then cur the left child of the left child of the right child, ... (if not, then not press in)

The non-recursive code for inorder traversal is as follows:

 //2.中序打印
    public void inOrderUnrecur(Node head) {
        System.out.println("in-order: ");
        if (head != null) {
            Node temp1 = head;
            Stack<Node> stack = new Stack<>();
            while (temp1 != null) {
                stack.push(temp1);
                temp1 = temp1.left;
            }
            Node cur;
            Node temp2;
            while (!stack.isEmpty()) {
                cur = stack.pop();
                System.out.print(cur.value + " ");
                temp2 = cur.right;
                while (temp2 != null) {
                    stack.push(temp2);
                    temp2 = temp2.left;
                }
            }
        }
        System.out.println();
    }

2.2.3 Post-order traversal

        Post-order traversal: left child node = "right child node =" head node

The specific implementation process of the algorithm is as follows (open up two stack spaces, stack 1: tool, stack 2: collection):

① Push the head node into the stack 1

②while (stack 1 is not empty):

                 1) Pop a node cur from stack 1

                 2) Push cur onto stack 2

                 3) First push the left child of cur into stack 1, then push the right child of cur into stack 1 (the condition is that cur has left and right children) ③while (stack 2 is not empty):

                 1) Pop a node node from stack 2

                 2) Printing or other operations processing node

The non-recursive code for postorder traversal is as follows:

//3.后序打印
    public void behindOrderUnrecur(Node head) {
        System.out.println("behind-order: ");
        if (head != null) {
            Stack<Node> stack1 = new Stack<>();
            Stack<Node> stack2 = new Stack<>();
            Node cur;
            stack1.add(head);
            while (!stack1.isEmpty()) {
                cur = stack1.pop();
                stack2.push(cur);
                if (cur.left != null) {
                    stack1.push(cur.left);
                }
                if (cur.right != null) {
                    stack1.push(cur.right);
                }
            }
            Node node;
            while (!stack2.isEmpty()) {
                node = stack2.pop();
                System.out.print(node.value + " ");
            }
        }
        System.out.println();
    }

3. Depth-first traversal and breadth-first traversal of binary tree

        The non-recursive general method of binary tree depth-first traversal is to use stack (last in first out) , and the non-recursive general method of breadth-first traversal is to use queue (first in first out) .

3.1 Depth-first traversal

        Depth-first traversal means to go deep into every possible branch path until it cannot go deeper, and each node can only be visited once. The depth-first traversal of a binary tree is special, and can be subdivided into pre-order traversal, in-order traversal, and post-order traversal. These traversal methods have been mentioned earlier, so I won’t go into details here.

3.2 Breadth-first traversal

        Breadth-first traversal is also called breadth-first traversal and hierarchical traversal. It refers to visiting each layer sequentially from top to bottom, visiting nodes from left to right in each layer, and entering the next layer after visiting, until there are no nodes to visit. . The algorithm idea of ​​breadth-first traversal is as follows:

① Put the head node head into the queue;

②while (the queue is not empty):

                 1) Pop a node cur from the queue;

                 2) Printing or other operations process cur;

                 3) First put the left child of cur (if any) into the queue, and then put the right child of cur (if any) into the queue.

The code for breadth-first traversal is as follows:

//二叉树的广度优先遍历如下:
    public void widthOrder(Node head) {
        if (head == null) {
            return;
        }
        Queue<Node> queue = new LinkedList<>();//java中LinkedList(原理是用双向链表实现队列)就是队列
        queue.add(head);
        Node cur;
        while (!queue.isEmpty()) {
            cur = queue.poll();
            System.out.print(cur.value + " ");
            if (cur.left != null) {
                queue.add(cur.left);
            }
            if (cur.right != null) {
                queue.add(cur.right);
            }
        }
    }

Guess you like

Origin blog.csdn.net/Mike_honor/article/details/125828311