Analyse
Ihre Definition eines binären Baum wir folgendes gegeben haben,
Jeder Knoten haben ein Elternteil, L-Kind, und R-Kind .. Wo:
L < N
R > N
P > N
Wir können dies auch tun:
L < N AND R > N => L < N < R => L < R
L < N AND P > N => L < N < P => L < P
R > N AND P > N => N < MIN(P,R)
N < MIN(P,R) AND L < N => L < N < MIN(P,R)
Und das jetzt lassen Sie versuchen, es erweitert, N.L = Left-child of N
:
N.L < N
N.R > N
N.P > N
N.L.L < N.L < MIN(N, N.L.R)
N.L.R > N.L > N.L.L
N.R.L < N.R < MIN(N, N.R.R)
N.R.R > N.R > N.R.L
IF N IS N.P LEFT-CHILD: N < N.P < MIN(N.P.P, N.P.R)
IF N IS N.P RIGHT-CHILD: N > N.P.R
Lösungsvorschlag
Dieses Problem scheint komplex, aber meine Lösung wird Sortierung mittels fusionieren nach Werten in einer Traversierfolgeliste Einfügen von links- Right-Parent, das dem Zusammenführen helfen wird, eine Zeitkomplexität irgendwo zwischen seinem Durchschnitts- und Optimalfall zu erhalten, aber mit einem kleinen Trick, der die Vergleiche verwendet, die ich oben gemacht habe.
Zunächst sammeln wir Baumknoten in einer Liste, Links-Rechts-Elternteil-Traversal verwendet wird, angesichts der Tatsache, dass: N.L < N < MIN(N.R, N.P)
und mit den Eltern ein höheres Gewicht zu geben unter der Annahme O(N.R) <= O(N.P)
mit Werten linear abnehmen, wenn wir links-Seite jedes Mal gehen .. > N.R.R > N.R > N > N.L > N.L.L > ..
.
Nach dem Sammeln der Baumknoten in dieser Traversierungsreihenfolge enthält die Liste einige sortierte Chunks, die die Merge-Sortierung unterstützen, die wir als nächstes verwenden werden.
Diese Lösung funktioniert in: Time = O(n log n + n)
, Space = O(n)
Hier wird der Algorithmus in Java (nicht getestet) geschrieben ist:
private class Node Comparable<Node>
{
public Node R;
public Node L;
public int value;
public Node (Node L, int val, Node R)
{
this.L = L;
this.value = val;
this.R = R;
}
@Override
public int compareTo(Node other)
{
return ((other != null) ? (this.value-other.value) : 0);
}
}
class Main
{
private static Node head;
private static void recursive_collect (Node n, ArrayList<Node> list)
{
if (n == null) return;
if (n.left != null) recursive_collect (n.L, list);
if (n.right != null) recursive_collect (n.R, list);
list.add(n.value);
}
public static ArrayList<Node> collect()
{
ArrayList<Node> list = new ArrayList<Node>();
recursive_collect (head, list);
return list;
}
// sorting the tree: O(n log n + n)
public static ArrayList<Node> sortTree()
{
// Collecting nodes: O(n)
ArrayList<Node> list = collect();
// Merge Sort: O(n log n)
Collections.sort(list);
return list;
}
// The example in the picture you provided
public static void createTestTree()
{
Node left1 = new Node (new Node(null,-2,null), -1, new Node(null,0,null));
Node left2 = new Node (new Node(null,-1,null), 0, new Node(null,1,null));
Node right = new Node (left2, 1, new Node(null,2,null));
head = new Node (left1, 0, right);
}
// test
public static void main(String [] args)
{
createTestTree();
ArrayList<Node> list = sortTree();
for (Node n : list)
{
System.out.println(n.value);
}
}
}
Was meinst du mit 'O (1) und O (n) Zeit Komplexität'? Meinst du O (1) Raum? Ich kann mir vorstellen, dass es einen O (n) -Algorithmus gibt, indem der Baum auf ähnliche Weise wie AVL-Bäume balanciert wird und dann eine Inorder-Traversierung ausgeführt wird. –
Was bedeutet Sortierung genau? Die Methode muss eine sortierte Liste zurückgeben? drucken? Können wir den Baum verändern? – Knoothe
Ist der O (1) -Raum eine echte Anforderung? Es ist schwierig (wenn wir den Baum nicht modifizieren können), in O (1) -Raum zu tun. Vielleicht war es O (Höhe)? Übrigens, bfs braucht Omega (n) Raum. Nicht O (log n). – Knoothe