Wie ein binären Baum auf binären Suchbaum in-place konvertieren, das heißt, wir können keinen zusätzlichen Platz nutzen.
Wie ein binären Baum auf binären Suchbaum in-place konvertieren, das heißt, wir können keinen zusätzlichen Raum nutzen
quelle vom benutzer bit-question
In anderen Sprachen...
Ein binärer Baum in der Regel ist ein binärer Suchbaum, wobei in diesem Fall keine Konvertierung erforderlich ist.
Vielleicht müssen Sie die Struktur klären, was Sie von konvertieren. Ist Ihr Quellbaum unausgeglichen? Ist es nicht der Schlüssel, den Sie suchen auf möchten bestellt? Wie kamen Sie auf dem Quellbaum?
Nun, wenn dies eine Interviewfrage ist, das erste, was ich würde herausplatzen (mit Null eigentlichen Gedanken) ist dies: iterieren die gesamte binäre rekursiv und und das kleinste Element finden. Nehmen Sie es aus dem binären Baum. Nun wiederholen Sie den Vorgang, bei dem Sie den gesamten Baum durchlaufen und das kleinste Element finden, und fügen Sie es als Eltern des letzten Elements gefunden (mit dem vorherigen Elemente des neuen Knotens linkes Kind zu werden). Wiederholen Sie so oft wie nötig, bis der ursprüngliche Baum leer ist. Am Ende werden Sie mit dem schlimmstmöglichen sortierten binären Baum links - eine verbundene Liste. Der Zeiger zeigt auf den Root-Knoten, die das größte Element ist.
Dies ist ein schrecklicher Algorithmus all-around - O (n ^ 2) Laufzeit mit der schlechtesten möglichen binären Baum ausgegeben, aber es ist ein anständigen Ausgangspunkt, bevor besser mit etwas kommen und hat den Vorteil, Sie den Code zu schreiben, in der Lage, für es in etwa 20 Zeilen auf einem Whiteboard.
Man braucht nicht viel geben zu gehen, aber wenn die Anforderung ist, was ich denke, es ist, haben Sie ein binärer Baum bereits im Speicher erstellt und sitzen, aber nicht sortiert (wie Sie es sortiert werden soll, sowieso).
Ich gehe davon aus, dass der Baumknoten aussieht
struct tree_node {
struct tree_node * left;
struct tree_node * right;
data_t data;
};
Ich gehe davon aus, dass Sie C lesen
Während wir uns nur fragen, sitzen konnte um, warum dieser Baum jemals ohne in sortierter Reihenfolge erstellt wurde geschaffen zu haben, die uns nicht tun etwas Gutes, so mit Ich werde es ignorieren und einfach behandeln sie zu sortieren.
Die Anforderung, dass kein zusätzlicher Raum verwendet werden ungerade ist. Vorübergehend wird es besonders viel Platz sein, wenn auch nur auf den Stapel. Ich gehe davon aus, dass es bedeutet, dass malloc oder so ähnlich nennen und auch, dass der resultierende Baum nicht mehr Speicher als der original unsortiert Baum zu verwenden hat.
Die erste und einfachste Lösung ist es, eine Vorordnungsdurchquerung des unsortierten Baumes zu tun , jeden Knoten aus dem Baum zu entfernen und ein sortierte Einsetzen in einen neuen Baum zu tun. Dies ist O (n + n log (n)), die O (n log (n)).
Wenn dies nicht das, was sie wollen, und Sie gehen zu müssen, Drehungen und Sachen benutzen ..... das ist schrecklich!
Ich dachte, dass Sie dies tun könnte durch eine ungerade Version eines Haufens Art zu tun, aber ich lief in Probleme. Eine andere Sache, die den Sinn kam, die schrecklich langsam sein würde, wäre eine seltsame Version von Bubble Sort auf dem Baum zu tun.
Hierzu jeder Knoten verglichen wird und möglicherweise mit jedem, es ist direkt Kinder (und damit auch mit der Mutter) getauscht wiederholt, bis Sie den Baum durchlaufen und keine benötigten Swaps finden. Doing ein Shaker sort (Blase Art, die nach rechts und von rechts nach links links geht) Version dieser würde am besten funktionieren, und nach dem Anstich würden Sie nicht nach unten Teilbäume durchqueren müssen, die nicht aus, um in Bezug sah es Eltern .
Ich bin sicher, dass entweder diese algorthm wurde von jemand anderem vor mir ausgedacht und hat einen coolen Namen, ich weiß nicht genau, oder dass es in irgendeiner Weise grundlegend falsch, dass ich nicht zu sehen.
Kommen Sie mit den Laufzeitberechnungen für den zweiten Vorschlag up ist ein ziemlich kompliziert. Zuerst dachte ich, dass es einfach O wäre (n ^ 2), wie Blase und Shaker Sorten, aber ich kann mich nicht überzeugen, dass die Unterstruktur Traversal Vermeidung nicht genug gewinnen könnte, um es ein wenig besser als O (n ^ 2). Im Wesentlichen Blase und Shaker Sorten auch diese Optimierung, aber nur an den Enden, wo insgesamt sortedness früh auftritt und Sie können die Grenzen fällen. Mit dieser Baum-Version erhalten Sie oppurtunities möglicherweise auch Stücke in der Mitte des Satzes zu vermeiden. Nun, wie ich schon sagte, ist es wahrscheinlich tödlich fehlerhaft.
Haben Inorder Traversal des binären Baums und das Ergebnis. sortieren Sie das Ergebnis in acending Um den binären Suchbaum zu bilden, indem mittleres Element der sortierten Liste als root unter (dies kann unter Verwendung von binärer Suche durchgeführt). so erhalten wir ausgewogenen binären Suchbaum.
Sie folgenden Algorithmus, um die Lösung zu erreichen.
1) finden die um Nachfolger ohne jeden Raum verwendet wird.
Node InOrderSuccessor(Node node)
{
if (node.right() != null)
{
node = node.right()
while (node.left() != null)
node = node.left()
return node
}
else
{
parent = node.getParent();
while (parent != null && parent.right() == node)
{
node = parent
parent = node.getParent()
}
return parent
}
}
2) Sie um Traversal ohne Leerzeichen zu verwenden.
a) Bestimmen Sie den ersten Knoten von Inorder Traversal. Es sollte die meisten Kind des Baumes links, wenn es hat, oder der erste rechte Kind verlassen, wenn es hat, oder rechtes Kind selbst. b) Verwenden obigen Algorithmus, um herauszufinden, inoder Nachfolger des ersten Knotens. c) Wiederholen Sie Schritt 2 für alle zurück Nachfolger.
Verwenden Sie oben 2 - Algorithmus und tut das , um Traversal auf Binärbaum ohne zusätzlichen Platzbedarf. Bildet den binären Suchbaum , wenn Traversal tun. Aber Komplexität ist O(N2)schlimmster Fall.
Stapelsortier den Baum .. nlogn Komplexität ..
Hat die Nachordnungsdurchquerung und von dem Erstellen eines binären Suchbaumes.
struct Node * newroot = '\0';
struct Node* PostOrder(Struct Node* root)
{
if(root != '\0')
{
PostOrder(root->left);
PostOrder(root->right);
insertBST(root, &newroot);
}
}
insertBST(struct Node* node, struct Node** root)
{
struct Node * temp, *temp1;
if( root == '\0')
{
*root == node;
node->left == '\0';
node->right == '\0';
}
else
{
temp = *root;
while( temp != '\0')
{
temp1= temp;
if( temp->data > node->data)
temp = temp->left;
else
temp = temp->right;
}
if(temp1->data > node->data)
{
temp1->left = node;
}
else
{
temp1->right = node;
}
node->left = node->right = '\0';
}
}
Konvertieren Binary Tree zu einem doppelt verknüpften Listen- können Inplace in O (n) durchgeführt werden
sie dann sortieren mit Mergesort, nlogn
Konvertieren Sie die Liste zurück an einen Baum - O (n)
Einfache nlogn Lösung.
#include <stdio.h>
#include <stdlib.h>
typedef int data_t;
struct tree_node {
struct tree_node * left;
struct tree_node * right;
data_t data;
};
/* a bonsai-tree for testing */
struct tree_node nodes[10] =
{{ nodes+1, nodes+2, 1}
,{ nodes+3, nodes+4, 2}
,{ nodes+5, nodes+6, 3}
,{ nodes+7, nodes+8, 4}
,{ nodes+9, NULL, 5}
,{ NULL, NULL, 6}
,{ NULL, NULL, 7}
,{ NULL, NULL, 8}
,{ NULL, NULL, 9}
};
struct tree_node * harvest(struct tree_node **hnd)
{
struct tree_node *ret;
while (ret = *hnd) {
if (!ret->left && !ret->right) {
*hnd = NULL;
return ret;
}
if (!ret->left ) {
*hnd = ret->right;
ret->right = NULL;;
return ret;
}
if (!ret->right) {
*hnd = ret->left;
ret->left = NULL;;
return ret;
}
hnd = (rand() &1) ? &ret->left : &ret->right;
}
return NULL;
}
void insert(struct tree_node **hnd, struct tree_node *this)
{
struct tree_node *ret;
while ((ret= *hnd)) {
hnd = (this->data < ret->data ) ? &ret->left : &ret->right;
}
*hnd = this;
}
void show(struct tree_node *ptr, int indent)
{
if (!ptr) { printf("Null\n"); return; }
printf("Node(%d):\n", ptr->data);
printf("%*c=", indent, 'L'); show (ptr->left, indent+2);
printf("%*c=", indent, 'R'); show (ptr->right, indent+2);
}
int main(void)
{
struct tree_node *root, *this, *new=NULL;
for (root = &nodes[0]; this = harvest (&root); ) {
insert (&new, this);
}
show (new, 0);
return 0;
}
struct Node
{
int value;
Node* left;
Node* right;
};
void swap(int& l, int& r)
{
int t = l;
l = r;
r = t;
}
void ConvertToBST(Node* n, Node** max)
{
if (!n) return;
// leaf node
if (!n->left && !n->right)
{
*max = n;
return;
}
Node *lmax = NULL, *rmax = NULL;
ConvertToBST(n->left, &lmax);
ConvertToBST(n->right, &rmax);
bool swapped = false;
if (lmax && n->value < lmax->value)
{
swap(n->value, lmax->value);
swapped = true;
}
if (rmax && n->value > rmax->value)
{
swap(n->value, n->right->value);
swapped = true;
}
*max = n;
if (rmax && rmax->value > n->value) *max = rmax;
// If either the left subtree or the right subtree has changed, convert the tree to BST again
if (swapped) ConvertToBST(n, max);
}