web-dev-qa-db-ger.com

Einen binären Baum umkehren (von links nach rechts)

Ich habe mir Interview-Fragen angesehen und vor kurzem bin ich auf eine Frage gestoßen, in der Sie gefragt wurden, wie Sie einen allgemeinen binären Baum umkehren können, z. 

Wenn wir zum Beispiel den binären Baum hätten

     6
   /   \
  3     4
 / \   / \
7   3 8   1

Umkehren würde es schaffen

     6
   /   \
  4     3
 / \   / \
1   8 3   7

Ich konnte mir keine gute Implementierung für die Lösung dieses Problems vorstellen. Kann jemand gute Ideen anbieten? 

Vielen Dank

31
user1234831

Sie können Rekursion verwenden:

static void reverseTree(final TreeNode root) {
    final TreeNode temp = root.right;
    root.right = root.left;
    root.left = temp;

    if (root.left != null) {
        reverseTree(root.left);
    }

    if (root.right != null) {
        reverseTree(root.right);
    }
}

Basierend auf den Kommentaren:

static void reverseTree(final TreeNode root) {
    if (root == null) {
        return;
    }

    final TreeNode temp = root.right;
    root.right = root.left;
    root.left = temp;

    reverseTree(root.left);

    reverseTree(root.right);
}
80
Petar Ivanov

Umkehren eines binären Baums in O (1). 

    struct NormalNode {
      int value;
      struct NormalNode *left;
      struct NormalNode *right;
    };

    struct ReversedNode {
      int value;
      struct ReversedNode *right;
      struct ReversedNode *left;
    };

    struct ReversedNode *reverseTree(struct NormalNode *root) {
      return (struct ReversedNode *)root;
    }
12
Zhipeng YANG

Es gibt ein paar interessante Teile zu dieser Frage. Da Ihre Sprache Java ist, haben Sie höchstwahrscheinlich einen generischen Node class.

class Node<T> {
    private final T data;
    private final Node left;
    private final Node right;
    public Node<T>(final T data, final Node left, final Node right) {
        this.data  = data;
        this.left  = left;
        this.right = right;
    }
    ....
}

Zweitens kann das Umkehren, manchmal auch als Invertieren bezeichnet, entweder durch Verändern des linken und rechten Felds des Knotens oder durch Erstellen eines new - Knotens wie beim Original, jedoch mit einem linken und rechten untergeordneten Element erfolgen. Der erste Ansatz ist in eine andere Antwort gezeigt, während der zweite Ansatz hier dargestellt ist:

class Node<T> {
    // See fields and constructor above...

    public Node<T> reverse() {
        Node<T> newLeftSubtree = right == null ? null : right.reverse();
        Node<T> newRightSubtree = left == null ? null : left.reverse();
        return Node<T>(data, newLeftSubtree, newRightSubtree); 
    }
}

Die Idee, eine Datenstruktur nicht zu mutieren, ist eine der Ideen hinter persistenten Datenstrukturen , die ziemlich interessant sind.

5
Ray Toal

Ich habe gesehen, dass sich die meisten Antworten nicht auf Nullzeigerprobleme konzentrieren.

public static Node invertBinaryTree(Node node) {

    if(node != null) {
        Node temp = node.getLeftChild();

        node.setLeftChild(node.getRightChild());
        node.setRigthChild(temp);

        if(node.left!=null) { 
            invertBinaryTree(node.getLeftChild());
        }
        if(node.right !=null) {
            invertBinaryTree(node.getRightChild());
        }
    }

    return node;
}

Im obigen Code führen wir nur rekursive Aufrufe aus, wenn das linke/rechte untergeordnete Element des Wurzelknotens nicht null ist. Es ist einer der schnellsten Ansätze!

0

Sie können den linken und den rechten Knoten wie folgt rekursiv austauschen.

// helper method
private static void reverseTree(TreeNode<Integer> root) {
    reverseTreeNode(root);
}

private static void reverseTreeNode(TreeNode<Integer> node) {
    TreeNode<Integer> temp = node.left;
    node.left   = node.right;
    node.right  = temp;

    if(node.left != null)
        reverseTreeNode(node.left);

    if(node.right != null)
        reverseTreeNode(node.right);
}

Demonstrationscode für Java

import Java.util.LinkedList;
import Java.util.Queue;

public class InvertBinaryTreeDemo {

    public static void main(String[] args) {

        // root node
        TreeNode<Integer> root  = new TreeNode<>(6);

        // children of root
        root.left               = new TreeNode<Integer>(3);
        root.right              = new TreeNode<Integer>(4);

        // grand left children of root
        root.left.left          = new TreeNode<Integer>(7);
        root.left.right         = new TreeNode<Integer>(3);

        // grand right childrend of root
        root.right.left         = new TreeNode<Integer>(8);
        root.right.right        = new TreeNode<Integer>(1);

        System.out.println("Before invert");
        traverseTree(root);

        reverseTree(root);

        System.out.println("\nAfter invert");
        traverseTree(root);
    }

    // helper method
    private static void reverseTree(TreeNode<Integer> root) {
        reverseTreeNode(root);
    }

    private static void reverseTreeNode(TreeNode<Integer> node) {
        TreeNode<Integer> temp = node.left;
        node.left   = node.right;
        node.right  = temp;

        if(node.left != null)
            reverseTreeNode(node.left);

        if(node.right != null)
            reverseTreeNode(node.right);
    }

    // helper method for traverse
    private static void traverseTree(TreeNode<Integer> root) {
        Queue<Integer> leftChildren     = new LinkedList<>();
        Queue<Integer> rightChildren    = new LinkedList<>();

        traverseTreeNode(root, leftChildren, rightChildren);

        System.out.println("Tree;\n*****");

        System.out.printf("%3d\n", root.value);

        int count = 0;
        int div = 0;
        while(!(leftChildren.isEmpty() && rightChildren.isEmpty())) {
            System.out.printf("%3d\t%3d\t", leftChildren.poll(), rightChildren.poll());
            count += 2;
            div++;
            if( (double)count == (Math.pow(2, div))) {
                System.out.println();
                count = 0;
            }
        }

        System.out.println();
    }

    private static void traverseTreeNode(TreeNode<Integer> node, Queue<Integer> leftChildren, Queue<Integer> rightChildren) {
        if(node.left != null)
            leftChildren.offer(node.left.value);

        if(node.right != null)
            rightChildren.offer(node.right.value);

        if(node.left != null) {
            traverseTreeNode(node.left, leftChildren, rightChildren);
        }

        if(node.right != null) {
            traverseTreeNode(node.right, leftChildren, rightChildren);
        }
    }

    private static class TreeNode<E extends Comparable<E>> {

        protected E value;
        protected TreeNode<E> left;
        protected TreeNode<E> right;

        public TreeNode(E value) {
            this.value = value;
            this.left = null;
            this.right = null;
        }

    }

}

Ausgabe

Before invert
Tree;
*****
  6
  3   4 
  7   3   8   1 

After invert
Tree;
*****
  6
  4   3 
  1   8   3   7 
0