Postorder Tree Traversal | Iterative & Recursive

来源:互联网 发布:狗狗长跳蚤怎么办 知乎 编辑:程序博客网 时间:2024/05/21 14:01

后序树遍历|迭代和递归

给定一个二叉树,使用后序遍历编写迭代和递归解决方案来遍历树。

不同于链表,一维数组和其他以线性顺序遍历的线性数据结构,树可以以多种方式以深度顺序(后序,预订和后序)或宽度优先遍历订单(级别遍历)。除了这些基本遍历之外,各种更复杂或混合的方案是可能的,例如深度限制搜索,如迭代深化深度优先搜索。

遍历树包括以某种方式遍历所有节点。由于树不是线性数据结构,所以从给定的节点可能会有多个可能的下一个节点,因此一些节点必须被延迟,以某种方式存储以备后续访问。遍历可以迭代地进行,其中延迟节点存储在堆栈中,或者可以通过递归完成延迟节点隐式存储在调用堆栈中。

对于以顺序方式遍历(非空)二进制树,我们必须对从树的根节点开始的每个节点N做这三件事:

(L)递归地遍历其左子树。当这个步骤完成后,我们再次返回N。
(R)递归地遍历其右子树。当这个步骤完成后,我们再次返回N。
(N)过程N本身

在正常的后序遍历中,我们在右子树之前访问了左子树。如果我们在访问左子树之前访问右子树,则被称为反向后续遍历。

后序遍历

在处理任何节点之前,我们可以看到,左子树被先处理,后跟右子树,最后处理节点。可以为每个节点递归地定义这些操作。递归实现被称为深度优先搜索(DFS),因为搜索树在进入下一个兄弟之前尽可能地加深每个孩子的深度。

C ++实现 -

 递归函数执行树的后续遍历void postorder(Node *root){      //如果当前节点为空    if (root == nullptr)        return;     //遍历左子树    postorder(root->left);     //遍历正确的子树    postorder(root->right);     //显示根(或当前节点)的数据部分    cout << root->data << " ";}

迭代实现 -

要将上述递归过程转换为迭代过程,我们需要一个显式堆栈。下面是一个简单的基于堆栈的迭代算法进行后续遍历。

iterativePostorder(node)  s -> empty stack  t -> output stack  while (not s.isEmpty())     node -> s.pop()     t.push(node)     if (node.left <> null)        s.push(node.left)     if (node.right <> null)        s.push(node.right)  while (not t.isEmpty())     node -> t.pop()     visit(node)

C ++实现 -

//执行树的后续遍历的迭代函数void postorderIterative(Node* root){      //创建一个空堆栈并推根节点    stack<Node*> stk;    stk.push(root);      //创建另一个堆栈来存储后续遍历    stack<int> out;     //运行到堆栈不是空的    while (!stk.empty())    {        //我们从堆栈中弹出一个节点,并将数据推送到输出堆栈        Node *curr = stk.top();        stk.pop();        out.push(curr->data);        // push left and right child of popped node to the stack        if (curr->left)            stk.push(curr->left);        if (curr->right)            stk.push(curr->right);    }    //将弹出节点的左右孩子推送到堆栈    while (!out.empty())    {        cout << out.top() << " ";        out.pop();    }}

上述解决方案的时间复杂度为O(n),并且程序的空间复杂度为O(n),因为所需的空间与树的高度成比例,在最差情况下可能与树的节点数相等。 。

原创粉丝点击