[PHP data structure] traversal and logical operation of binary tree

Time:2021-10-14

In the last article, we talked about a lot of theoretical knowledge. Although it is very boring, those are the premise of our study today. When you look at the code later, you will find how important these theoretical knowledge is. First of all, we still want to explain that the main content of our study is binary tree, because binary tree is the most typical application of tree. It is a must know and must learn content whether it is an exam or an interview.

First of all, before learning the tree operation, we must understand that the core of the tree operation is “traversal”. Why do you say that? Different from stack and queue, tree structure is not one-dimensional. It has branches and different angles. More importantly, it has the concept of hierarchy. One dimensional space is our common “line”. It has only length and no height, and this length is its only dimension. Stack and queue are obviously one-dimensional. The tree is different. Because of the concept of hierarchy, it has a “height”, that is, it is upgraded to a two-dimensional concept. Just like the pile of nouns introduced in the previous article, there is the concept of “height (depth) of tree”.

After traversing a tree, we can add, delete and change the nodes of the tree on the basis of traversal. These basic logical operations are all based on traversal. Think about the stack and queue carefully. In fact, these logical operations also start from traversal? Whether out of the stack, in the stack or out of the queue, we are based on a fixed traversal rule (Filo, FIFO).

For two-dimensional things, how to traverse it is a key content. We only need to traverse the one-dimensional data structure in order, while the two-dimensional data results can not be simply traversed one by one in order. Because there is a hierarchical relationship between nodes, we should consider the current node. What should we do if there are no child nodes?

https://imgs.developpaper.com/imgs/1575433-20210726085514425-476763969.png

Fortunately, we stand on the shoulders of giants to learn this knowledge. Many predecessors have summarized some very simple tree traversal methods for us. How simple is it? Let’s see how to build a tree, that is, the binary tree we showed in the last article.

https://imgs.developpaper.com/imgs/1575433-20210726085514663-65753765.png

Chain storage structure of binary tree

Using chained storage binary tree is very simple and vivid. Let’s put away our doubts about sequential storage binary tree first, because in the next article, we will explain how to use sequential storage.

class BiTree
{
    public $data;
    public $lChild;
    public $rChild;
}

In fact, in chain storage, we use nodes to save the tree. Each binary tree node has a data field, that is, the data attribute. The other two attributes can be regarded as two forked pointers, which are the left child node lchild and the right child node rchild of this node. Compared with stack and queue, we just replace the next node with the left and right child nodes. In fact, it is not much different from stack and queue. To put it bluntly, from the perspective of data structure, we still use one-dimensional storage to represent the two-dimensional concept, and the transformation of this concept is from the perspective of concept understanding.

Binary tree construction

//Establish binary tree
function CreateBiTree($arr, $i)
{
    if (!isset($arr[$i])) {
        return null;
    }
    $t = new BiTree();
    $t->data = $arr[$i];
    $t->lChild = CreateBiTree($arr, $i * 2);
    $t->rChild = CreateBiTree($arr, $i * 2 + 1);
    return $t;
}

With such a simple method, we can complete the establishment of a chain binary tree. Guys, please watch carefully. This simple operation actually contains many mysteries:

  • We use an array to represent each node of the tree in turn, for example, enter a, B, C, D, e… (we will see their shadow again in the sequential storage of the tree)

  • The content of the assignment is the data of the current $I subscript. Note that we performed a recursive operation when assigning values to the left and right children

  • When learning stack, we learned that “recursion” is a stack operation. Therefore, in this code, we build trees in the form of stack

  • Notice every I * 2 and I * 2 + 1? Please review the of binary treeNature 5

Finally, we test whether this method can successfully establish a chain tree structure.

$treeList = ['', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O'];

$tree = CreateBiTree($treeList, 1);
print_r($tree);

// BiTree Object
// (
//     [data] => A
//     [lChild] => BiTree Object
//         (
//             [data] => B
//             [lChild] => BiTree Object
//                 (
//                     [data] => D
//                     [lChild] => BiTree Object
//                         (
//                             [data] => H
//                             [lChild] =>
//                             [rChild] =>
//                         )

//                     [rChild] => BiTree Object
//                         (
//                             [data] => I
//                             [lChild] =>
//                             [rChild] =>
//                         )

//                 )

//             [rChild] => BiTree Object
//                 (
//                     [data] => E
//                     [lChild] => BiTree Object
//                         (
//                             [data] => J
//                             [lChild] =>
//                             [rChild] =>
//                         )

//                     [rChild] => BiTree Object
//                         (
//                             [data] => K
//                             [lChild] =>
//                             [rChild] =>
//                         )

//                 )

//         )

//     [rChild] => BiTree Object
//         (
//             [data] => C
//             [lChild] => BiTree Object
//                 (
//                     [data] => F
//                     [lChild] => BiTree Object
//                         (
//                             [data] => L
//                             [lChild] =>
//                             [rChild] =>
//                         )

//                     [rChild] => BiTree Object
//                         (
//                             [data] => M
//                             [lChild] =>
//                             [rChild] =>
//                         )

//                 )

//             [rChild] => BiTree Object
//                 (
//                     [data] => G
//                     [lChild] => BiTree Object
//                         (
//                             [data] => N
//                             [lChild] =>
//                             [rChild] =>
//                         )

//                     [rChild] => BiTree Object
//                         (
//                             [data] => O
//                             [lChild] =>
//                             [rChild] =>
//                         )

//                 )

//         )

// )

The printed content should be very clear, right? Node a has left and right children, nodes B and C respectively, node B has left and right children, D and e respectively, and so on. The final structure is exactly the same as that of the binary tree graph above. Here, we also need to note that for the passed in array, we give the data of the first element, that is, the 0 subscript, empty, and start building the tree from the second element, that is, the 1 subscript element. This is also in order to use the binary tree intuitively and convenientlyNature 5To quickly build this tree.

Traversal of binary tree

After the construction of binary tree, in fact, we have come into contact with an ergodic form of binary tree. Pay attention to the code in our tree building method. We first assign a value to the data of the node, then create the left and right child nodes of the node, assign a value to them, and then continue to use the same operation to build all nodes all the way. Now, we reverse this operation. Instead of establishing nodes, we read the contents of these nodes. First read the contents of the nodes, and then read the contents of the child nodes around the node. This is “sequential traversal”.

Preorder traversal

/**
 *Preorder traversal
 */
function PreOrderTraverse(?BiTree $t)
{
    if ($t) {
        echo $t->data, ',';
        PreOrderTraverse($t->lChild);
        PreOrderTraverse($t->rChild);
    }
}

PreOrderTraverse($tree);

// A,B,D,H,I,E,J,K,C,F,L,M,G,N,O,

Isn’t it amazing? Even for tree building, we actually use the same traversal method. We can see that traversal plays an important role in the complex data structure of binary tree.

You can see the node order read by traversal. It seems that it is different from the order we input! Yes, the preorder traversal is through recursion. First go to the end in one direction. When this node has no child nodes, it pops up through the characteristics of the recursion stack.And before traversing the child node, first output the content of the current node。 Note that this sentence is very important! Therefore, our order is a, B, D and h. when h has no child nodes, we return to the parent node D and enter its right child node I. for the specific order, please refer to the following figure:

https://imgs.developpaper.com/imgs/1575433-20210726085514863-892947520.png

The node order of preorder traversal and preorder tree building in our code is completely different, which should be made clear. The tree building process is based on the binary treeNature 5It is directly assigned a data subscript. In the traversal process, it is a node by node to scan and traverse the whole tree.

Medium order traversal

As the name suggests, the middle order traversal actually outputs the content of the current node after traversing the left child node, so we only need to fine tune the code of the first order traversal.

/**
 *Medium order traversal
 */
function InOrderTraverse(?BiTree $t)
{
    if ($t) {
        InOrderTraverse($t->lChild);
        echo $t->data, ',';
        InOrderTraverse($t->rChild);
    }
}

InOrderTraverse($tree);

// H,D,I,B,J,E,K,A,L,F,M,C,N,G,O,

The step of middle order traversal is that we will directly go to the leftmost child node. When we encounter the last node, we will output the content, that is, node h in the figure, and then return to its parent node D. at this time, we will output d according to the principle of middle order, and then enter its right child node and output I. After traversing the subtree of node D and itself, it returns to the superior node B of node D, outputs B, and then enters the right child node e of node B. Enter the leftmost child node j of e again, and then complete the traversal of the whole tree with reference to the traversal form of node D. Refer to the following figure for the specific sequence:

https://imgs.developpaper.com/imgs/1575433-20210726085515207-1641053940.png

Postorder traversal

After learning the pre order and middle order, you can see from the name that the post order is to output the content of a node after traversing the left and right children of a node. Of course, the code is simply fine tuned.

/**
 *Postorder traversal
 */
function PostOrderTraverse(?BiTree $t)
{
    if ($t) {
        PostOrderTraverse($t->lChild);
        PostOrderTraverse($t->rChild);
        echo $t->data, ',';
    }
}

PostOrderTraverse($tree);

// H,I,D,J,K,E,B,L,M,F,N,O,G,C,A,

The specific principle will not be explained in detail. I believe that after learning the first order and middle order, you can immediately understand what the second order traversal means. Directly above:

https://imgs.developpaper.com/imgs/1575433-20210726085515391-1489697722.png

level traversal

Finally, we want to talk about sequence traversal. Since there is the keyword “layer”, I believe you can immediately think of whether to traverse layer by layer! Yes, sequence traversal means that. We output the corresponding node information layer by layer according to the tree hierarchy. It should be noted that we will use the queue instead of the stack here.

/**
 *Sequence traversal
 */
$q = InitLinkQueue();
function LevelOrderTraverse(?BiTree $t)
{
    global $q;
    if (!$t) {
        return;
    }

    EnLinkQueue($q, $t);
    $node = $q;
    while ($node) {
        $node = DeLinkQueue($q);
        if ($node->lChild) {
            EnLinkQueue($q, $node->lChild);
        }
        if ($node->rChild) {
            EnLinkQueue($q, $node->rChild);
        }
        echo $node->data, ',';
    }
}

LevelOrderTraverse($tree);

// A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,

Initlinkqueue(), enlinkqueue(), enlinkqueue() are the logical operation methods for queues that we wrote when learning about queues. Are you very happy? I used my previous knowledge again. The core idea of sequence traversal is to use the concept of queue. When you encounter a node, you queue the node, judge whether it has child nodes, and then queue the child nodes one after another. Every time a node is traversed, the node at the head of the queue is out of the queue, which completes the ability to traverse according to the tree level. The text description is still too abstract. We still show this process through pictures:

https://imgs.developpaper.com/imgs/1575433-20210726085515690-506783622.png

Have you found that the output of sequence traversal is exactly the same as the array order when we build the tree. It’s fun, so there’s always a lot of fun in the code world waiting for us to find out!

summary

Is there any confusion in today’s content? If you are confused, find more data and study it carefully. The first order, middle order and second order use stacks to traverse the nodes of the tree, while the sequence traversal uses queues. One by one, the previous learning contents come in handy! But this is just the beginning. When learning the graph, we will see the stack and queue again in the depth traversal and breadth traversal. They are all relatives.

These four traversal methods also often appear in examinations and interviews. Whether their principles or drawing or writing various traversal sequences according to the graphics are very common assessment contents, so we should deepen our understanding of these traversals based on the introduction of this article and master them skillfully according to some teaching materials.

Test code:

https://github.com/zhangyue0503/Data-structure-and-algorithm/blob/master/4. Traversal and logical operation of binary tree / source / 4.2.php

reference material:

Data structure, Second Edition, Yan Weimin

Data structure, Second Edition, Chen Yue

High score notes on data structure, 2020 edition, tianqin postgraduate entrance examination

Official account: hard core project manager

Add wechat / QQ friends: [xiaoyuezigonggong / 149844827] get free PHP and project management learning materials

Tiktok, official account, voice, headline search, hard core project manager.

Station B ID: 482780532