Cómo convertir un árbol binario de árbol binario de búsqueda en el lugar, es decir, no podemos utilizar cualquier espacio adicional.
Cómo convertir un árbol binario a binario árbol de búsqueda en el lugar, es decir, no podemos utilizar cualquier espacio extra
fuente por usuario bit-question
En otros idiomas...
Un árbol binario por lo general es un árbol binario de búsqueda, en cuyo caso no se requiere ninguna conversión.
Tal vez usted necesita para aclarar la estructura de lo que está convirtiendo a. Es desequilibrada árbol de código fuente? ¿No está ordenada por la clave que desea buscar en? ¿Cómo se llega a la estructura de directorios?
Bueno, si se trata de una pregunta de la entrevista, la primera cosa que me gustaría dejar escapar (con el pensamiento real cero) es la siguiente: recorrer todo el binaria recursiva y y encontrar el elemento más pequeño. Sacarlo del árbol binario. Ahora, repita el proceso en el que usted repite todo el árbol y encontrar el elemento más pequeño, y añadirlo como padre del último elemento que se encuentra (con el elemento anterior convertirse en hijo izquierdo del nodo nuevo). Repita tantas veces como sea necesario hasta que el árbol original está vacía. Al final, lo que queda es la peor posible árbol binario ordenado - una lista enlazada. El puntero apunta al nodo raíz, que es el elemento más grande.
Este es un algoritmo horrible, todo alrededor - O (n ^ 2) el tiempo de funcionamiento con la peor salida de árbol binario es posible, pero es un punto de partida decente antes de llegar a algo mejor y tiene la ventaja de que usted sea capaz de escribir el código para en cerca de 20 líneas en una pizarra.
Usted no da mucho para seguir adelante, pero si el requisito es lo que creo que es, usted tiene un árbol binario ya creado y sentado en la memoria, pero no ordenadas (la forma en que desea que se ordenan, de todos modos).
Estoy asumiendo que los nodos del árbol se parecen
struct tree_node {
struct tree_node * left;
struct tree_node * right;
data_t data;
};
También estoy asumiendo que usted puede leer C
Aunque podríamos simplemente sentarse alrededor preguntándose por qué este árbol fuera creado sin haber sido creado con el fin ordenada que no nos hace ningún bien, así que voy a ignorarlo y simplemente trato con la clasificación de la misma.
El requisito de que no se utilizará ningún espacio adicional es impar. Temporalmente no habrá espacio adicional, aunque sólo sea en la pila. Voy a asumir que significa que llamar a malloc o algo así, y también que el árbol resultante tiene que usar más memoria que el árbol original no ordenado.
La primera y más sencilla solución es hacer un recorrido en preorden del árbol sin ordenar la eliminación de cada nodo de ese árbol y haciendo una inserción ordenada en un nuevo árbol. Esto es O (n + n log (n)), que es O (n log (n)).
Si esto no es lo que quieren y que van a tener que usar las rotaciones y esas cosas ..... eso es horrible!
Pensé que podía hacer esto haciendo una versión impar de una pila de clasificación, pero me encontré con problemas. Otra cosa que no vienen a la mente, lo que sería terriblemente lento, habría que hacer una versión impar de ordenamiento de burbuja en el árbol.
Para ello cada nodo se compara y posiblemente intercambia con cada uno de los niños es directa (y por tanto también con su padre) varias veces hasta que se recorre el árbol y no encuentras los swaps necesarios. Haciendo una especie agitador (ordenamiento de burbuja que va de izquierda a derecha y de derecha a izquierda) de esta funcionaría mejor, y después de la pasada inicial no tendría que recorrer hacia abajo subárboles que no parecían fuera de orden con respecto a su padre .
Estoy seguro de que, o bien este algorthm fue ideado por otra persona antes que yo y tiene un nombre fresco que yo no sé, o que es fundamentalmente defectuoso de alguna manera que no estoy viendo.
El subir con los cálculos de tiempo de ejecución para la segunda sugerencia es bastante complicado. Al principio pensé que simplemente sería O (n ^ 2), al igual que la burbuja y agitador tipo, pero no puedo satisfacer a mí mismo que el subárbol evitación de recorrido podría no ganar lo suficiente para que sea un poco mejor que O (n ^ 2). Esencialmente burbuja y agitador tipo reciben esta optimización también, pero sólo en los extremos, donde sortedness total ocurre temprano y se pueden talar los límites. Con esta versión se obtiene del árbol oppurtunities, para evitar posiblemente trozos en el medio del conjunto así. Bueno, como he dicho, es probable que fatalmente defectuoso.
Hacer finde recorrido del árbol binario y almacenar el resultado. ordenar los resultados con el fin de formar el árbol de búsqueda binaria tomando elemento medio de la lista clasificada como root acending (esto se puede hacer mediante la búsqueda binaria). por lo que tenemos árbol binario de búsqueda equilibrado.
No siguiente algoritmo para llegar a la solución.
1) encontrar el sucesor en orden sin utilizar ningún espacio.
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) hacer en el recorrido orden sin necesidad de utilizar el espacio.
a) Encuentre el primer nodo de recorrido en orden. Debe dejado la mayor parte del niño del árbol si tiene, o hacia la izquierda del primer hijo derecho si tiene, o el propio hijo derecho. b) Utilizar anterior algoritmo para encontrar a cabo inoder sucesor del primer nodo. c) Repita el paso 2 para todo el sucesor devuelto.
Utilice por encima del 2 algoritmo y hacer el recorrido en el orden en el árbol binario sin utilizar espacio adicional. Formar el árbol de búsqueda binaria cuando se hace el recorrido. Sin embargo, la complejidad es O(N2)peor de los casos.
pila de clasificación del árbol .. complejidad nlogn ..
Hacer la orden posterior de recorrido y desde que crear un árbol de búsqueda binaria.
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';
}
}
Convertir Binary Tree a un lista- doblemente enlazada se puede hacer in situ en O (n)
luego clasificarla utilizando ordenamiento por mezcla, nlogn
Convertir la lista de nuevo a un árbol - O (n)
nlogn solución simple.
#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);
}