【问题标题】:Binary Search Tree post-order Iterator二叉搜索树后序迭代器
【发布时间】:2012-08-03 18:45:08
【问题描述】:

我正在用 PHP 实现 AVL 树(一种自平衡二叉搜索树),并且一切正常。我有按顺序、预顺序和级别顺序 迭代器 工作,但我不知道如何为 BST 执行后序迭代器。 Google 搜索显示了如何进行迭代后序遍历,而不是迭代器。

到目前为止,我唯一的成功是使用后序遍历来构建一个数组,然后返回一个数组迭代器。这很糟糕,因为它会迭代树两次并增加更多空间复杂度。

构建后序迭代器的一般算法是什么?

标签出现在这里的唯一原因是 PHP 中的迭代器与 Java 或 C++ 中的迭代器不同。这可能会影响您的建议。

另外,如果 PHP 有生成器,这将是一件轻而易举的事,因为后序遍历可以简单地产生值,将其变成一个迭代器。 . .

编辑:这里是按顺序迭代器的实现。也许它可以帮助您了解我对后序迭代器的要求:

class InOrderIterator implements Iterator {

    /**
     * @var ArrayStack
     */
    protected $stack;

    /**
     * @var BinaryNode
     */
    protected $root;

    /**
     * @var BinaryNode
     */
    protected $value;

    public function __construct(BinaryNode $root) {
        $this->stack = new ArrayStack;
        $this->root = $root;
    }

    /**
     * @link http://php.net/manual/en/iterator.current.php
     * @return mixed
     */
    public function current() {
        return $this->value->getValue();
    }

    /**
     * @link http://php.net/manual/en/iterator.next.php
     * @return void
     */
    public function next() {
        /**
         * @var BinaryNode $node
         */
        $node = $this->stack->pop();

        $right = $node->getRight();
        if ($right !== NULL) {
            // left-most branch of the right side
            for ($left = $right; $left !== NULL; $left = $left->getLeft()) {
                $this->stack->push($left);
            }
        }

        if ($this->stack->isEmpty()) {
            $this->value = NULL;
            return;
        }
        $this->value = $this->stack->peek();

    }

    /**
     * @link http://php.net/manual/en/iterator.key.php
     * @return NULL
     */
    public function key() {
        return NULL; //no keys in a tree . . .
    }

    /**
     * @link http://php.net/manual/en/iterator.valid.php
     * @return boolean
     */
    public function valid() {
        return $this->value !== NULL;
    }

    /**
     * @link http://php.net/manual/en/iterator.rewind.php
     * @return void
     */
    public function rewind() {
        $this->stack->clear();

        for ($current = $this->root; $current !== NULL; $current = $current->getLeft()) {
            $this->stack->push($current);
        }

        $this->value = $this->stack->peek();
    }
}

【问题讨论】:

  • 听起来很奇怪,因为如果您可以实现预购和有序,那么运行后购有什么问题?这只是对孩子的递归调用顺序的改变。后序是:遍历右孩子及其孩子,然后遍历左孩子及其孩子,最后打印“self”
  • @alfasin 我不做递归。请重新阅读问题。我正在制作一个迭代器,而不是遍历树。
  • 我想如果你给我们看一些代码会更清楚
  • @alfasin 我添加了按顺序遍历的例子,也许它会帮助你理解我所追求的。
  • 不错!你能告诉我们预购和使用示例吗?

标签: php php algorithm iterator binary-search-tree


【解决方案1】:

我几乎可以将 C++ 中的迭代遍历示例转换为迭代器。 Latest on github。还需要弄清楚几个案例。

class PostOrderIterator implements Iterator {

    /**
     * @var ArrayStack
     */
    protected $stack;

    /**
     * @var BinaryNode
     */
    protected $root;

    /**
     * @var BinaryNode
     */
    protected $value;

    protected $current;

    public function __construct(BinaryNode $root) {
        $this->stack = new ArrayStack;
        $this->root = $root;
    }

    /**
     * @link http://php.net/manual/en/iterator.current.php
     * @return mixed
     */
    public function current() {
        return $this->current->getValue();
    }

    /**
     * @link http://php.net/manual/en/iterator.next.php
     * @return void
     */
    public function next() {
        /**
         * @var BinaryNode $node
         */
        if ($this->value !== NULL) {
            $right = $this->value->getRight();
            if ($right !== NULL) {
                $this->stack->push($right);
            }
            $this->stack->push($this->value);
            $this->value = $this->value->getLeft();
            $this->next();
            return;
        }

        if ($this->stack->isEmpty()) {
            $this->current = $this->value;
            $this->value = NULL;
            return;
        }

        $this->value = $this->stack->pop();

        $right = $this->value->getRight();
        if ($right !== NULL && !$this->stack->isEmpty() && ($right === $this->stack->peek())) {
            $this->stack->pop();
            $this->stack->push($this->value);
            $this->value = $this->value->getRight();
            $this->current = $this->value;
        } else {

            if ($this->current === $this->value) {
                $this->value = NULL;
                $this->next();
            } else {
                $this->current = $this->value;
                $this->value = NULL;
            }
        }

    }

    /**
     * @link http://php.net/manual/en/iterator.key.php
     * @return NULL
     */
    public function key() {
        return NULL; //no keys in a tree . . .
    }

    /**
     * @link http://php.net/manual/en/iterator.valid.php
     * @return boolean
     */
    public function valid() {
        return $this->current !== NULL;
    }

    /**
     * @link http://php.net/manual/en/iterator.rewind.php
     * @return void
     */
    public function rewind() {
        $this->stack->clear();

        $this->value = $this->root;
        $this->next();
    }
}

我无法描述该算法或证明它在做什么,但希望随着时间的推移它会变得有意义。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-11-06
    • 1970-01-01
    • 1970-01-01
    • 2015-01-18
    • 2017-05-09
    • 2011-06-02
    • 1970-01-01
    相关资源
    最近更新 更多