树的遍历包含先序遍历、中序遍历、后序遍历、层序遍历。

先解释一下前三种的先中后是什么意思,这个先中后指的是访问根节点的顺序。先序就是首先根节点,然后左子树,最后右子树;中序就是先左子树、然后根节点,最后右子树;后序遍历就是先左子树,然后右子树,最后根节点。注意这里默认左子树的顺序永远在右子树之前。

他们对应的实现代码如下:

static function preOrderTraversal($tree,$fn){
    if(!($tree instanceof Node_tree)){
        return false;
    }
    if(is_callable($fn,true)){
        $fn($tree->data);
    }
    self::preOrderTraversal($tree->leftNode,$fn);
    self::preOrderTraversal($tree->rightNode,$fn);
}

static function inOrderTraversal($tree,$fn){
    if(!($tree instanceof Node_tree)){
        return false;
    }

    self::inOrderTraversal($tree->leftNode,$fn);
    if(is_callable($fn,true)){
        $fn($tree->data);
    }
    self::inOrderTraversal($tree->rightNode,$fn);
}


static function postOrderTraversal($tree,$fn){
    if(!($tree instanceof Node_tree)){
        return false;
    }

    self::postOrderTraversal($tree->leftNode,$fn);
    self::postOrderTraversal($tree->rightNode,$fn);
    if(is_callable($fn,true)){
        $fn($tree->data);
    }
}

可以很容易看出来,这里利用的递归的思想。

层序遍历和前三种遍历不太一致,前三种遍历都可以通过栈来进行模拟,而层序遍历需要依赖队。层序遍历是按照一层一层的顺序从上到下从左到右访问每个节点。

static function levelOrderTraversal($tree,$fn){
    if(!($tree instanceof Node_tree)){
        return false;
    }
    $queue = [];
    array_push($queue,$tree);
    while(!empty($queue)){
        $node = array_shift($queue);
        if(is_callable($fn,true)){
            $fn($node->data);
        }
        if($node->leftNode){
            array_push($queue,$node->leftNode);
        }
        if($node->rightNode){
            array_push($queue,$node->rightNode);
        }
    }
    return true;
}

这里没有使用之前实现的队,而是利用PHP的array模拟了一个队,本身思想是一致的。

遍历二叉树有哪些应用呢,我给出如下几个例子:

// 树的深度
static function depth($tree){
    $leftDepth = 0;
    $rightDepth = 0;
    if($tree->leftNode){
        $leftDepth = self::depth($tree->leftNode);
    }
    if($tree->rightNode){
        $rightDepth = self::depth($tree->rightNode);
    }
    return max($leftDepth,$rightDepth) + 1;
}

// 节点数量
static function length($tree){
    $leftTreeLength = 0;
    $rightTreeLength = 0;
    if($tree->leftNode){
        $leftTreeLength = self::length($tree->leftNode);
    }
    if($tree->rightNode){
        $rightTreeLength = self::length($tree->rightNode);
    }
    return $leftTreeLength + $rightTreeLength + 1;
}

我们可以求得树的深度(不知道这个概念的自己看书),我们也可以实现线性结构中的求节点数量操作。

results matching ""

    No results matching ""