【问题标题】:print boundary of binary tree二叉树的打印边界
【发布时间】:2012-06-29 23:11:30
【问题描述】:

如何打印二叉树的外框。

  1. 顺序是从上到下、从左到右、再从下到上
  2. 打印所有最左边和最右边的节点
  3. 打印所有叶节点
  4. 打印所有只有 1 个叶子的节点

             100
            /   \ 
          50     150
         / \      /
       24   57   130
      /  \    \    \
    12   30    60   132
    

例如: 输出应该是 100、50、24、12、30、57、60、130、132、150

如果我们编写三个不同的函数来打印左节点、叶节点和右节点,这很容易解决,但需要 O(n+2logn) 时间。

我也在寻找一种 O(n) 的方法,但条件是每个节点只能访问一次,不想要这个额外的 O(2logn) 部分。

【问题讨论】:

  • O(n+2logn)O(n)
  • @interjay 是对的,我们可以跳过它等于 o(n) 的常数部分
  • geeksforgeeks.org/archives/2755 检查这个。它的时间和空间复杂度等于简单的遍历算法
  • @interjay 我知道 O(n+2logn) 是 O(n),但我说的是不同的......算法应该只访问每个节点一次。
  • stackoverflow.com/questions/4932235/… 检查这个。它只会遍历每个节点一次。它使用递归

标签: algorithm binary-tree


【解决方案1】:

这可以在 O(n) 中完成。也就是说,我们只访问树的每个节点一次。 逻辑如下 维护两个变量leftright并将它们初始化为零。 当递归调用左侧增加 left 1 每当有递归调用骑行侧递增 right 1

从root开始,进行中序遍历,检查right是否为零,这意味着我们从来没有递归调用right。如果是打印节点,这意味着我们正在打印树的所有最左边的节点。如果 right 不为零,则它们不被视为边界,因此查找叶节点并打印它们。

在左子树调用完成后的中序遍历中,您冒泡到根,然后我们对右子树进行递归调用。现在首先检查叶子节点并打印它们,然后检查 left 是否为零,这意味着我们对 left 进行了递归调用,因此它们不被视为边界。如果 left 是零打印节点,这意味着我们正在打印树的所有最右边的节点。

代码sn-p是

void btree::cirn(struct node * root,int left,int right)
{



 if(root == NULL)
    return;
if(root)
{

    if(right==0)
    {

        cout<<root->key_value<<endl;
    }

     cirn(root->left,left+1,right);




if(root->left==NULL && root->right==NULL && right>0)
    {

            cout<<root->key_value<<endl;
    }





  cirn(root->right,left,right+1);
  if(left==0)
   {

       if(right!=0)
      {
            cout<<root->key_value<<endl;
       }


   }




}

}

【讨论】:

  • 我认为这不会在 OP 的问题中打印 130。
【解决方案2】:

算法:

  1. 打印左边界
  2. 打印叶子
  3. 打印右边界

void getBoundaryTraversal(TreeNode t) {
        System.out.println(t.t);
        traverseLeftBoundary(t.left);
        traverseLeafs(t);
        //traverseLeafs(t.right);
        traverseRightBoundary(t.right);
    }
    private void traverseLeafs(TreeNode t) {
        if (t == null) {
            return;
        }
        if (t.left == null && t.right == null) {
            System.out.println(t.t);
            return;
        }
        traverseLeafs(t.left);
        traverseLeafs(t.right);
    }
    private void traverseLeftBoundary(TreeNode t) {
        if (t != null) {
            if (t.left != null) {
                System.out.println(t.t);
                traverseLeftBoundary(t.left);
            } else if (t.right != null) {
                System.out.println(t.t);
                traverseLeftBoundary(t.right);
            }
        }
    }

    private void traverseRightBoundary(TreeNode t) {
        if (t != null) {
            if (t.right != null) {
                traverseRightBoundary(t.right);
                System.out.println(t.t);
            } else if (t.left != null) {
                traverseLeafs(t.left);
                System.out.println(t.t);
            }
        }
    }

TreeNode 定义:

class TreeNode<T> {

    private T t;
    private TreeNode<T> left;
    private TreeNode<T> right;

    private TreeNode(T t) {
        this.t = t;
    }
}

【讨论】:

    【解决方案3】:

    您可以通过将 Euler Tour 算法应用于您的树来实现这一点。看到这个link

    或者(如果可以访问)古德里奇等人的书。人(链接。here

    希望对你有帮助

    【讨论】:

      【解决方案4】:

      似乎是一个家庭作业问题,但我需要练习。十年来我没有做过任何关于递归的事情。

      void SimpleBST::print_frame()
      {
         if (root != NULL)
         {
            cout << root->data;
      
            print_frame_helper(root->left, true, false);
            print_frame_helper(root->right, false, true);
            cout << endl;
         }
      }
      
      void SimpleBST::print_frame_helper(Node * node, bool left_edge, bool right_edge)
      {
         if (node != NULL)
         {
            if (left_edge)
               cout << ", " << node->data;
      
            print_frame_helper(node->left, left_edge && true, false);
      
            if ((!left_edge) && (!right_edge))
               if ((node->left == NULL) || (node->right == NULL))
                  cout << node->data << ", ";
      
            print_frame_helper(node->right, false, right_edge && true);
      
            if (right_edge)
               cout << ", " << node->data;
         }
      }
      

      【讨论】:

        【解决方案5】:

        可以通过按前序遍历树来完成解决方案 - O(n)。
        在下面找到示例代码。 Source and some explanation.

        Java 中的示例代码:

        public class Main {
            /**
             * Prints boundary nodes of a binary tree
             * @param root - the root node
             */
            public static void printOutsidesOfBinaryTree(Node root) {
        
                Stack<Node> rightSide = new Stack<>();
                Stack<Node> stack = new Stack<>();
        
                boolean printingLeafs = false;
                Node node = root;
        
                while (node != null) {
        
                    // add all the non-leaf right nodes left
                    // to a separate stack
                    if (stack.isEmpty() && printingLeafs && 
                            (node.left != null || node.right != null)) {
                        rightSide.push(node);
                    }
        
                    if (node.left == null && node.right == null) {
                        // leaf node, print it out
                        printingLeafs = true;
                        IO.write(node.data);
                        node = stack.isEmpty() ? null : stack.pop();
                    } else {
                        if (!printingLeafs) {
                            IO.write(node.data);
                        }
        
                        if (node.left != null && node.right != null) {
                            stack.push(node.right);
                        }
                        node = node.left != null ? node.left : node.right;
                    }
                }
        
                // print out any non-leaf right nodes (if any left)
                while (!rightSide.isEmpty()) {
                    IO.write(rightSide.pop().data);
                }
            }
        }
        

        【讨论】:

          【解决方案6】:

          这是一个简单的解决方案:

          def printEdgeNodes(root, pType, cType):
             if root is None:
                 return
             if pType == "root" or (pType == "left" and cType == "left") or (pType == "right" and cType == "right"):
                  print root.val
             if root.left is None and root.right is None:
                 print root.val
             if pType != cType and pType != "root":
                 cType = "invalid"
             printEdgeNodes(root.left, cType, "left")
          
          def printEdgeNodes(root):
              return printEdgeNodes(root, "root", "root")
          

          【讨论】:

            【解决方案7】:

            你可以递归遍历每个节点并控制何时打印,这里是javascript代码sn-p。

            function findBtreeBoundaries(arr, n, leftCount, rightCount) {
              n = n || 0;
              leftCount = leftCount || 0;
              rightCount = rightCount || 0;
            
              var length = arr.length;
              var leftChildN = 2*n + 1, rightChildN = 2*n + 2;
            
              if (!arr[n]) {
                return;
              }
            
              // this is the left side of the tree
              if (rightCount === 0) {
                console.log(arr[n]);
              }
            
              // select left child node
              findBtreeBoundaries(arr, leftChildN, leftCount + 1, rightCount);
            
              // this is the bottom side of the tree
              if (leftCount !== 0 && rightCount !== 0) {
                console.log(arr[n]);
              }
            
              // select right child node
              findBtreeBoundaries(arr, rightChildN, leftCount, rightCount + 1);
            
              // this is the right side of the tree
              if (leftCount === 0 && rightCount !== 0) {
                console.log(arr[n]);
              }
            
            }
            
            findBtreeBoundaries([100, 50, 150, 24, 57, 130, null, 12, 30, null, 60, null, 132]);
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2012-04-15
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2016-01-22
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多