Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Algorithm 二叉树的打印边界_Algorithm_Binary Tree - Fatal编程技术网

Algorithm 二叉树的打印边界

Algorithm 二叉树的打印边界,algorithm,binary-tree,Algorithm,Binary Tree,如何打印二叉树的外部框架 顺序是从上到下,从左到右,然后从下到上 打印所有最左侧节点和最右侧节点 打印所有叶节点 打印只有一个叶的所有节点 100 / \ 50 150 / \ / 24 57 130 / \ \ \ 12 30 60 132 e、 g: 输出应该是 100、50、24、12、30、57、60、130、132、150 如果我们编写三个不同的函数来打印左

如何打印二叉树的外部框架

  • 顺序是从上到下,从左到右,然后从下到上
  • 打印所有最左侧节点和最右侧节点
  • 打印所有叶节点
  • 打印只有一个叶的所有节点

             100
            /   \ 
          50     150
         / \      /
       24   57   130
      /  \    \    \
    12   30    60   132
    
  • e、 g: 输出应该是 100、50、24、12、30、57、60、130、132、150

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


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

    您可以通过应用于树的Euler Tour算法来实现这一点。见此:

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


    我希望这有帮助

    看起来像是家庭作业的问题,但我需要练习。我已经十年没有做过递归了

    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;
       }
    }
    
    void SimpleBST::print_frame()
    {
    if(root!=NULL)
    {
    cout数据;
    打印框架辅助对象(根->左、真、假);
    打印框架辅助对象(根->右、假、真);
    cout left==NULL)| |(节点->右==NULL))
    cout数据正确、错误、正确和正确);
    如果(右边缘)
    这可以在O(n)中完成,也就是说,我们只访问树的每个节点一次。
    逻辑如下
    保持两个变量leftright并将其初始化为零。
    当存在对左侧的递归调用时,按1递增left
    当有递归调用时,骑乘侧增量为1

    从根开始,按顺序遍历并检查right是否为零,这意味着我们从未对right进行过递归调用。如果是print node,这意味着我们正在打印树的所有最左侧节点。如果right为非零,则它们不被视为边界,因此查找叶节点并打印它们

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

    代码片段是

    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;
           }
    
    
       }
    
    
    
    
    }
    
    void btree::cirn(结构节点*root,int left,int right)
    {
    if(root==NULL)
    返回;
    如果(根)
    {
    如果(右==0)
    {
    coutright==NULL&&right>0)
    {
    
    cout该解决方案可以通过按预顺序-O(n)遍历树来完成。
    在下面查找示例代码

    Java中的示例代码:

    公共类主{
    /**
    *打印二叉树的边界节点
    *@param root-根节点
    */
    公共静态void printOutsidesOfBinaryTree(节点根){
    堆栈右侧=新堆栈();
    堆栈=新堆栈();
    布尔printingLeafs=false;
    节点=根;
    while(节点!=null){
    //将所有非叶右节点添加到左节点
    //分门别类
    if(stack.isEmpty()&&printingLeafs&&
    (node.left!=null | | node.right!=null)){
    右侧推(节点);
    }
    if(node.left==null&&node.right==null){
    //叶节点,打印出来
    printingLeafs=true;
    IO.write(节点数据);
    node=stack.isEmpty()?null:stack.pop();
    }否则{
    如果(!printingLeafs){
    IO.write(节点数据);
    }
    if(node.left!=null&&node.right!=null){
    stack.push(node.right);
    }
    node=node.left!=null?node.left:node.right;
    }
    }
    //打印出任何非叶右节点(如果有左节点)
    而(!rightSide.isEmpty()){
    IO.write(rightSide.pop().data);
    }
    }
    }
    
    算法:

  • 打印左边界
  • 打印树叶
  • 打印右边界


  • TreeNode
    定义:

    class TreeNode<T> {
    
        private T t;
        private TreeNode<T> left;
        private TreeNode<T> right;
    
        private TreeNode(T t) {
            this.t = t;
        }
    }
    
    类树节点{
    私人T;
    私有树节点左;
    私有树节点权;
    私有树节点(T){
    t=t;
    }
    }
    
    这里有一个简单的解决方案:

    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")
    

    您可以递归地遍历每个节点并控制何时打印,下面是javascript代码片段

    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]);
    

    O(n+2logn)
    is
    O(n)
    @interjay是对的,我们可以跳过常量部分,它等于O(n)检查一下。它的时间和空间复杂性与简单遍历相同algo@interjay我知道O(n+2logn)是O(n),但我说的是不同的..算法应该只访问每个节点一次。检查这个。它将只遍历每个节点一次。它使用递归。我认为这不会在OP的问题中打印130。
    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]);