Algorithm 打印二叉树的边界

Algorithm 打印二叉树的边界,algorithm,tree,binary-tree,binary-search-tree,graph-algorithm,Algorithm,Tree,Binary Tree,Binary Search Tree,Graph Algorithm,在一次采访中,我被要求打印二叉树的边界。比如说 1 / \ 2 3 / \ / \ 4 5 6 7 / \ \ 8 9 10 答案是:1,2,4,8,9,10,7,3 我已作出以下答覆 第一种方法: 我使用了Bool变量来解决上述问题 void printLeftEdges(BinaryTree *p, bool print) { if (!p) return; if (print

在一次采访中,我被要求打印二叉树的边界。比如说

      1
   /    \
  2      3
 /  \   /  \
4    5 6    7
    /   \     \
   8     9     10
答案是:1,2,4,8,9,10,7,3

我已作出以下答覆

第一种方法:

我使用了Bool变量来解决上述问题

void printLeftEdges(BinaryTree *p, bool print) {
   if (!p) return;
   if (print || (!p->left && !p->right))
       cout << p->data << " ";
   printLeftEdges(p->left, print);
   printLeftEdges(p->right, false);
}

void printRightEdges(BinaryTree *p, bool print) {
   if (!p) return;
   printRightEdges(p->left, false);
   printRightEdges(p->right, print);
   if (print || (!p->left && !p->right))
   cout << p->data << " ";
}

void printOuterEdges(BinaryTree *root) {
   if (!root) return;
   cout << root->data << " ";
   printLeftEdges(root->left, true);
   printRightEdges(root->right, true);
}
他的回答是:他对这种方法也不满意。他说你要穿过这棵树三次。这太过分了。如果你有其他解决方案,请给出另一个解决方案

第三种方法: 这一次我选择了级别顺序遍历(BFS)

1:打印各级的起止节点
2:对于每个其他节点,检查其两个子节点是否都为空,然后也打印该节点。
他的回答是:他似乎对这个方法也不满意,因为这个方法需要额外的O(n)阶内存


我的问题是告诉我一个方法,它只遍历一次树,不使用任何Bool变量,也不使用任何额外的内存。有可能吗?

我想这应该可以做到:

traverse(BinaryTree *root)
{
  if (!root) return;
  cout << p->data << " ";
  if (root->left ) traverseL(root->left ); //special function for outer left
  if (root->right) traverseR(root->right); //special function for outer right
}

traverseL(BinaryTree *p)
{
  cout << p->data << " ";
  if (root->left ) traverseL(root->left ); //still in outer left
  if (root->right) traverseC(root->right); 
}

traverseR(BinaryTree *p)
{
  if (root->left ) traverseC(root->left );
  if (root->right) traverseR(root->right); //still in outer right
  cout << p->data << " ";
}

traverseC(BinaryTree *p)
{
  if (!root->left && !root->right) //bottom reached
    cout << p->data << " ";
  else
  {
    if (root->left ) traverseC(root->left );
    if (root->right) traverseC(root->right);
  }
}
遍历(二进制树*根)
{
如果(!root)返回;
cout data left)traverseL(根->左);//左外的特殊函数
if(root->right)遍历器(root->right);//外部右的特殊函数
}
traverseL(二进制树*p)
{
cout data left)traverseL(root->left);//仍在左外侧
如果(根->右)遍历(根->右);
}
遍历器(二进制树*p)
{
如果(根->左)遍历(根->左);
if(root->right)遍历器(root->right);//仍在右外侧
cout data left&!root->right)//到达底部
cout data left)遍历(root->left);
如果(根->右)遍历(根->右);
}
}
遍历
功能开始。 在每个方法的开头去掉了空查询(避免在每一端调用一个函数)。 不需要bool变量,只需使用三种不同的遍历方法:

  • 一个用于左边缘,在遍历之前输出节点
  • 一个用于右边缘,在遍历后输出节点
  • 一个用于所有其他节点,如果没有兄弟节点,则输出该节点

下面是Python3中的递归解决方案,时间复杂度为O(n)。这里的算法是从上到下打印最左边的节点,从左到右打印叶子节点,从下到上打印最右边的节点。为左树和右树遍历添加布尔标志
(isLeft,isRight)
,可简化代码并提高O(n)的时间复杂度

方法
O(n)没有额外的空间和树的单次遍历。

我将树节点分为四种类型的节点

类型1->形成左边界的节点(如8)

键入0->不构成边界的节点(如12)

类型3->形成右边界的节点(如22)

叶节点(如4,10,14)

在我的方法中,我只是在做树遍历的递归方法(刚刚修改),其中我的函数是这种形式的

  void recFunc(btNode *temp,int type)
   {
      //Leaf Nodes
     if((temp->left == NULL)&&(temp->right == NULL))
                 cout << temp->data <<  " ";
     // type -1 Nodes must be printed before their children
   else if(type == 1)cout << temp->data << " ";
   else {;}


   if(type == 3)
   {
    if(temp->left)recFunc(temp->left,0);
    if(temp->right)recFunc(temp->right,3);
     //type 3 nodes must be printed after their children
    cout << temp->data << " ";
   }   
   else if(type == 1)
   {
    if(temp->left)recFunc(temp->left,1);
    if(temp->right)recFunc(temp->right,0);
   }
   else if(type == 0)
   {
    if(temp->left)recFunc(temp->left,0);
    if(temp->right)recFunc(temp->right,0);
   }
   else {;}
    }
void recFunc(btNode*temp,int类型)
{
//叶节点
如果((临时->左==NULL)和(&(临时->右==NULL))
无法保留数据,0);
如果(临时->右侧)recFunc(临时->右侧,3);
//类型3节点必须在其子节点之后打印
cout data left)recFunc(临时->左,1);
如果(临时->右侧)recFunc(临时->右侧,0);
}
else if(type==0)
{
如果(临时->左)recFunc(临时->左,0);
如果(临时->右侧)recFunc(临时->右侧,0);
}
else{;}
}
我在哪里改装了汽车

  • 在我的复发函数中,类型1的节点必须使其左侧节点 作为类型1,必须在呼叫其子女之前打印(如果他们 存在)
  • 类型3的节点必须按相反的顺序打印。因此,它们必须 给孩子打电话后打印。他们还必须指定 右键子节点作为类型3节点
  • 类型为0的节点不得打印,它们将其子节点指定为 类型0节点
  • 叶节点只能直接打印并返回

  • //解决方案的4个不同部分的4个差异列表 1) 左边框2)右边框3)左树中的叶子4)右树中的叶子

    public class PRintBinaryTreeBoundary {
    
    
        ArrayList<TreeNode> leftBorderList=new ArrayList<>();
        ArrayList<TreeNode> leftLEafNode=new ArrayList<>();
    
        ArrayList<TreeNode> rightBorderList=new ArrayList<>();
        ArrayList<TreeNode> rightLEafNode=new ArrayList<>();
    
    
    
        public static void main(String[] args) {
            // TODO Auto-generated method stub
             /*  1
               /    \
              2      3
             /  \   /  \
            4    5 6    7
                /   \     \
               8     9     10*/
            TreeNode one=new TreeNode(1);
    
            TreeNode two=new TreeNode(2);
            TreeNode three=new TreeNode(3);
            TreeNode four=new TreeNode(4);
            TreeNode five=new TreeNode(5);
            TreeNode six=new TreeNode(6);
            TreeNode seven=new TreeNode(7);
            TreeNode eight=new TreeNode(8);
    
            TreeNode nine=new TreeNode(9);
            TreeNode ten=new TreeNode(10);
    
    
            one.left=two; one.right=three;
    
            two.left=four;two.right=five;
    
            three.left=six;three.right=seven;
    
    
            five.left=eight;
    
            six.right=nine;
    
            seven.right=ten;
    
    
            PRintBinaryTreeBoundary p=new PRintBinaryTreeBoundary();
            p.print(one);
    
    
    
    
    
        }
    
        private void print(TreeNode one) {
            System.out.println(one.val);
    
            populateLeftBorderList(one.left);
            populateRightBorderList(one.right);
    
            populateLeafOfLeftTree(one.left);
            populateLeafOfRightTree(one.right);
    
    
            System.out.println(this.leftBorderList);
            System.out.println(this.leftLEafNode);
    
            System.out.println(this.rightLEafNode);
            Collections.reverse(this.rightBorderList);
            System.out.println(this.rightBorderList);
    
    
    
        }
    
        private void populateLeftBorderList(TreeNode node) {
    
            TreeNode n = node;
    
            while (n != null) {
                this.leftBorderList.add(n);
                n = n.left;
            }
    
        }
    
        private void populateRightBorderList(TreeNode node) {
    
            TreeNode n = node;
            while (n != null) {
                this.rightBorderList.add(n);
                n = n.right;
            }
    
        }
    
        private void populateLeafOfLeftTree(TreeNode leftnode) {
    
            Queue<TreeNode> q = new LinkedList<>();
            q.add(leftnode);
    
            while (!q.isEmpty()) {
    
                TreeNode n = q.remove();
    
                if (null == n.left && null == n.right && !this.leftBorderList.contains(n)) {
                    leftLEafNode.add(n);
                }
    
                if (null != n.left)
                    q.add(n.left);
    
                if (null != n.right)
                    q.add(n.right);
    
            }
        }
    
        private void populateLeafOfRightTree(TreeNode rightNode) {
    
            Queue<TreeNode> q = new LinkedList<>();
            q.add(rightNode);
    
            while (!q.isEmpty()) {
    
                TreeNode n = q.remove();
    
                if (null == n.left && null == n.right && !this.rightBorderList.contains(n)) {
                    rightLEafNode.add(n);
                }
    
                if (null != n.left)
                    q.add(n.left);
    
                if (null != n.right)
                    q.add(n.right);
    
            }
    
        }
    }
    
    公共类PRintBinaryTreeBoundary{
    ArrayList leftBorderList=新建ArrayList();
    ArrayList leftLEafNode=新的ArrayList();
    ArrayList rightBorderList=新建ArrayList();
    ArrayList rightLEafNode=新建ArrayList();
    公共静态void main(字符串[]args){
    //TODO自动生成的方法存根
    /*  1
    /    \
    2      3
    /  \   /  \
    4    5 6    7
    /   \     \
    8     9     10*/
    TreeNode 1=新的TreeNode(1);
    TreeNode 2=新的TreeNode(2);
    TreeNode三=新的TreeNode(3);
    TreeNode 4=新的TreeNode(4);
    TreeNode 5=新的TreeNode(5);
    TreeNode 6=新的TreeNode(6);
    TreeNode 7=新的TreeNode(7);
    TreeNode 8=新的TreeNode(8);
    TreeNode九=新的TreeNode(9);
    TreeNode十=新的TreeNode(10);
    一。左=二;一。右=三;
    二。左=四;二。右=五;
    三。左=六;三。右=七;
    五。左=八;
    六.右=九;
    七。右=十;
    PRintBinaryTreeBoundary p=新的PRintBinaryTreeBoundary();
    p、 印刷品(一份);
    }
    私人作废打印(TreeNode one){
    System.out.println(1.val);
    公共边界列表(左一);
    populateRightBorderList(右一);
    一棵树(左一);
    一棵恐怖树(右一);
    System.out.println(this.leftBorderList);
    System.out.println(this.leftLeaf节点);
    System.out.println(this.rightleaf节点);
    Collections.reverse(此.rightBorderList);
    System.out.println(this.rightBorderList);
    }
    私有void populateLeftBorderList(TreeNode节点){
    树节点n=节点;
    while(n!=null){
    这个.leftBorderList.add(n);
    
    #Print tree boundary nodes
    def TreeBoundry(node,isLeft,isRight):
        #Left most node and leaf nodes
        if(isLeft or isLeaf(node)): print(node.data,end=' ')
        #Process next left node
        if(node.getLeft() is not None): TreeBoundry(node.getLeft(), True,False)
        #Process next right node
        if(node.getRight() is not None):TreeBoundry(node.getRight(), False,True)
        #Right most node
        if(isRight and not isLeft and  not isLeaf(node)):print(node.data,end=' ')
    
    #Check is a node is leaf
    def isLeaf(node):
       if (node.getLeft() is None and  node.getRight() is None):
           return True
       else:
           return False
    
    #Get started
    #https://github.com/harishvc/challenges/blob/master/binary-tree-edge-nodes.py
    TreeBoundry(root,True,True)
    
      void recFunc(btNode *temp,int type)
       {
          //Leaf Nodes
         if((temp->left == NULL)&&(temp->right == NULL))
                     cout << temp->data <<  " ";
         // type -1 Nodes must be printed before their children
       else if(type == 1)cout << temp->data << " ";
       else {;}
    
    
       if(type == 3)
       {
        if(temp->left)recFunc(temp->left,0);
        if(temp->right)recFunc(temp->right,3);
         //type 3 nodes must be printed after their children
        cout << temp->data << " ";
       }   
       else if(type == 1)
       {
        if(temp->left)recFunc(temp->left,1);
        if(temp->right)recFunc(temp->right,0);
       }
       else if(type == 0)
       {
        if(temp->left)recFunc(temp->left,0);
        if(temp->right)recFunc(temp->right,0);
       }
       else {;}
        }
    
    public class PRintBinaryTreeBoundary {
    
    
        ArrayList<TreeNode> leftBorderList=new ArrayList<>();
        ArrayList<TreeNode> leftLEafNode=new ArrayList<>();
    
        ArrayList<TreeNode> rightBorderList=new ArrayList<>();
        ArrayList<TreeNode> rightLEafNode=new ArrayList<>();
    
    
    
        public static void main(String[] args) {
            // TODO Auto-generated method stub
             /*  1
               /    \
              2      3
             /  \   /  \
            4    5 6    7
                /   \     \
               8     9     10*/
            TreeNode one=new TreeNode(1);
    
            TreeNode two=new TreeNode(2);
            TreeNode three=new TreeNode(3);
            TreeNode four=new TreeNode(4);
            TreeNode five=new TreeNode(5);
            TreeNode six=new TreeNode(6);
            TreeNode seven=new TreeNode(7);
            TreeNode eight=new TreeNode(8);
    
            TreeNode nine=new TreeNode(9);
            TreeNode ten=new TreeNode(10);
    
    
            one.left=two; one.right=three;
    
            two.left=four;two.right=five;
    
            three.left=six;three.right=seven;
    
    
            five.left=eight;
    
            six.right=nine;
    
            seven.right=ten;
    
    
            PRintBinaryTreeBoundary p=new PRintBinaryTreeBoundary();
            p.print(one);
    
    
    
    
    
        }
    
        private void print(TreeNode one) {
            System.out.println(one.val);
    
            populateLeftBorderList(one.left);
            populateRightBorderList(one.right);
    
            populateLeafOfLeftTree(one.left);
            populateLeafOfRightTree(one.right);
    
    
            System.out.println(this.leftBorderList);
            System.out.println(this.leftLEafNode);
    
            System.out.println(this.rightLEafNode);
            Collections.reverse(this.rightBorderList);
            System.out.println(this.rightBorderList);
    
    
    
        }
    
        private void populateLeftBorderList(TreeNode node) {
    
            TreeNode n = node;
    
            while (n != null) {
                this.leftBorderList.add(n);
                n = n.left;
            }
    
        }
    
        private void populateRightBorderList(TreeNode node) {
    
            TreeNode n = node;
            while (n != null) {
                this.rightBorderList.add(n);
                n = n.right;
            }
    
        }
    
        private void populateLeafOfLeftTree(TreeNode leftnode) {
    
            Queue<TreeNode> q = new LinkedList<>();
            q.add(leftnode);
    
            while (!q.isEmpty()) {
    
                TreeNode n = q.remove();
    
                if (null == n.left && null == n.right && !this.leftBorderList.contains(n)) {
                    leftLEafNode.add(n);
                }
    
                if (null != n.left)
                    q.add(n.left);
    
                if (null != n.right)
                    q.add(n.right);
    
            }
        }
    
        private void populateLeafOfRightTree(TreeNode rightNode) {
    
            Queue<TreeNode> q = new LinkedList<>();
            q.add(rightNode);
    
            while (!q.isEmpty()) {
    
                TreeNode n = q.remove();
    
                if (null == n.left && null == n.right && !this.rightBorderList.contains(n)) {
                    rightLEafNode.add(n);
                }
    
                if (null != n.left)
                    q.add(n.left);
    
                if (null != n.right)
                    q.add(n.right);
    
            }
    
        }
    }
    
    // Java program to print boundary traversal of binary tree 
    
    /* A binary tree node has data, pointer to left child 
       and a pointer to right child */
    class Node { 
    int data; 
    Node left, right; 
    
     Node(int item) 
     { 
        data = item; 
        left = right = null; 
     } 
    } 
    
    class BinaryTree { 
    Node root; 
    
    // A simple function to print leaf nodes of a binary tree 
    void printLeaves(Node node) 
    { 
        if (node != null) { 
            printLeaves(node.left); 
    
            // Print it if it is a leaf node 
            if (node.left == null && node.right == null) 
                System.out.print(node.data + " "); 
            printLeaves(node.right); 
        } 
    } 
    
    // A function to print all left boundary nodes, except a leaf node. 
    // Print the nodes in TOP DOWN manner 
    void printBoundaryLeft(Node node) 
    { 
        if (node != null) { 
            if (node.left != null) { 
    
                // to ensure top down order, print the node 
                // before calling itself for left subtree 
                System.out.print(node.data + " "); 
                printBoundaryLeft(node.left); 
            } 
            else if (node.right != null) { 
                System.out.print(node.data + " "); 
                printBoundaryLeft(node.right); 
            } 
    
            // do nothing if it is a leaf node, this way we avoid 
            // duplicates in output 
        } 
    } 
    
    // A function to print all right boundary nodes, except a leaf node 
    // Print the nodes in BOTTOM UP manner 
    void printBoundaryRight(Node node) 
    { 
        if (node != null) { 
            if (node.right != null) { 
                // to ensure bottom up order, first call for right 
                // subtree, then print this node 
                printBoundaryRight(node.right); 
                System.out.print(node.data + " "); 
            } 
            else if (node.left != null) { 
                printBoundaryRight(node.left); 
                System.out.print(node.data + " "); 
            } 
            // do nothing if it is a leaf node, this way we avoid 
            // duplicates in output 
        } 
    } 
    
    // A function to do boundary traversal of a given binary tree 
    void printBoundary(Node node) 
    { 
        if (node != null) { 
            System.out.print(node.data + " "); 
    
            // Print the left boundary in top-down manner. 
            printBoundaryLeft(node.left); 
    
            // Print all leaf nodes 
            printLeaves(node.left); 
            printLeaves(node.right); 
    
            // Print the right boundary in bottom-up manner 
            printBoundaryRight(node.right); 
        } 
    } 
    
    // Driver program to test above functions 
    public static void main(String args[]) 
    { 
        BinaryTree tree = new BinaryTree(); 
        tree.root = new Node(20); 
        tree.root.left = new Node(8); 
        tree.root.left.left = new Node(4); 
        tree.root.left.right = new Node(12); 
        tree.root.left.right.left = new Node(10); 
        tree.root.left.right.right = new Node(14); 
        tree.root.right = new Node(22); 
        tree.root.right.right = new Node(25); 
        tree.printBoundary(tree.root); 
    } 
    } 
    
    class Node {
        Node left;
        Node right;
        int data;
        Node(int d) {
           data = d;
           left = right = null;
        }
    }
    
    class BinaryTree {
        Node root;
        public void getBoundary() {
           preorderLeft(root);
           inorderLeaves(root);
           postorderRight(root);
        }
        public boolean isLeaf(Node node) {
           if (node != null && node.left == null && node.right == null) return true;
           return false;
        }
        public void preorderLeft(Node start) {
           if (start != null && isLeaf(start) == false) System.out.print(start.data + " ");
           if (start.left != null) preorderLeftSide(start.left);
        }
        public void inorderLeaves(Node start) {
           if(start == null) return;
           if(start.left != null) inorderLeaves(start.left);
           if(start.left == null && start.right == null) System.out.print(start.data + " ");
           if(start.right != null) inorderLeaves(start.right);
        }
        public void postorderRight(Node start) {
           if(start.right != null) postorderRightSide(start.right);
           if(start != null && isLeaf(start) == false) System.out.print(start.data + " ");
        }
    }
    
    map<int,int>tmap;    #store the vertical distance and level
    list<int>llist;  #store the node values
    
    void Buildfunction(root,d, l){
        if(root == NULL){
            return; 
        } else if(tmap.count(d) == 0){
           tmap[d] = l;
           llist.push_back(root->data);
        } else if((root->left == NULL && root->right==NULL) || tmap[d] < l){
           tmap[d] = l;
           llist.push_back(root->data);  
        }
        Buildfunction(root->left,d--,l++);
        Buildfunction(root->right,d++,l++);  
    }
    
    class Node:
    
        def __init__(self, data):
            self.data = data
            self.left = None
            self.right = None
    
    
    def printLeaves(root):
        if (root):
            printLeaves(root.left)
            if root.left is None and root.right is None:
                print(root.data),
    
            printLeaves(root.right)
    
    
    def printBoundaryC(node):
        if not node.left or not node.right:
            print(node.data)
        if node.left:
            printBoundaryC(node.left)
        if node.right:
            printBoundaryC(node.right)
    
    
    def printBoundaryLeft(root):
        print(root.data)
        if root.left:
            printBoundaryLeft(root.left)
        if root.right:
            printBoundaryC(root.right)
    
    def printBoundaryRight(root):
        if root.right:
            printBoundaryRight(root.right)
        elif root.left:
            printBoundaryC(root.left)
        print(root.data)
    
    def printBoundary(root):
        if (root):
            print(root.data)
    
            if root.left:
                printBoundaryLeft(root.left)
            if root.right:
                printBoundaryRight(root.right)
    
    
    
    root = Node(20)
    root.left = Node(8)
    root.left.left = Node(4)
    root.left.right = Node(12)
    root.left.right.left = Node(10)
    root.left.right.left.right = Node(5)
    root.left.right.right = Node(14)
    root.right = Node(22)
    root.right.right = Node(25)
    printBoundary(root)