Preorder Tree Traversal | Iterative & Recursive

来源:互联网 发布:淘宝鞋子女款冬天穿的 编辑:程序博客网 时间:2024/06/04 20:02

树前序遍历|迭代和递归

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

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

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

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

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

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

这里写图片描述

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

C ++实现 -

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

迭代实现 -

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

iterativePreorder(node)  if (node = null)    return  s -> empty stack  s.push(node)  while (not s.isEmpty())    node -> s.pop()    visit(node)    if (node.right -> null)       s.push(node.right)    if (node.left -> null)       s.push(node.left)C ++实现 - //执行树的前序遍历的迭代函数void preorderIterative(Node *root){     //如果树为空,则返回    if (root == nullptr)       return;    //创建一个空堆栈并推根节点    stack<Node*> stack;    stack.push(root); //运行到堆栈不是空的    while (!stack.empty())    {        //从堆栈中弹出一个节点并打印它        Node *curr = stack.top();        stack.pop();        cout << curr->data << " ";         //将弹出节点的右侧小孩推送到堆栈        if (curr->right)            stack.push(curr->right);         //将弹出节点的左边小孩推到堆栈        if (curr->left)            stack.push(curr->left);          //重要的注意事项 - 右边的孩子被推开,让左边的孩子        //先处理(FIFO顺序)    }}

以上解决方案可以通过仅将正确的孩子推到堆栈进一步优化。

C ++实现 -

 //执行树的前序遍历的迭代函数void preorderIterative(Node *root){  //如果树为空,则返回    if (root == nullptr)       return;    //创建一个空堆栈并推根节点    stack<Node*> stack;    stack.push(root);    //从根节点开始(将当前节点设置为根节点)    Node* curr = root;    //运行到堆栈不是空的    while (!stack.empty())    {        //如果当前节点不为空,则打印并推送其右边的子节点        //到堆栈并移动到它的左边的孩子        if (curr != nullptr)        {            cout << curr->data << " ";            if (curr->right)                stack.push(curr->right);            curr = curr->left;        }        // else如果当前节点为空,我们从堆栈中弹出一个节点        //将当前节点设置为弹出的节点        else        {            curr = stack.top();            stack.pop();        }    }}

上述解决方案的时间复杂度为O(n),程序的空间复杂度为O(n)作为空间要求

原创粉丝点击