Supongamos que tiene un árbol binario completo (es decir, cada nodo interno tiene exactamente dos descendientes no vacíos). Cada nodo contiene un número entero distinto de cero. Se le da la tarea de codificar y decodificar el árbol en / desde una lista de enteros.
El árbol se almacena internamente algo así como:
struct node {
int data;
struct node *left, *right;
};
Y tienes que implementar dos funciones:
int *encode(struct node *root);
struct node *decode(int *array);
Depende de usted cómo codifica y decodifica.
Puntos por:
- longitud mínima de codificación
- complejidad (idealmente lineal en número de nodos)
- originalidad
No hay puntos para la longitud del código fuente y no está restringido a C.
Ejemplo de árbol:
5
/ \
3 2
/ \
2 1
/ \
9 9
code-challenge
tree-traversal
Alexandru
fuente
fuente
int *
Es una caja negra para el usuario.Respuestas:
~ 1.03 N
Parece que todas las respuestas hasta ahora requieren al menos 2 * N * 32 bits para almacenar. (Excepto las soluciones en lenguajes que permiten valores enteros de más de 32 bits, como las soluciones Haskell y Ruby, pero aún así necesitarán bytes adicionales para codificar cada vez que los datos sean mayores a 16K).
Aquí hay una solución que solo requiere N + techo (N / 32) +1 pulgadas de almacenamiento. Esto se acerca a 1.03125 N para N grande, y está por debajo de 1.1 N para todo N mayor que 20.
La idea es almacenar un bit extra para cada nodo donde 1 es "hasChildren". Estos bits se empaquetan en N / 32 palabras por adelantado.
(implementación completa aquí)
fuente
Este programa Haskell codifica un árbol de n nodos en n Enteros. El truco es que codifica los datos del nodo duplicados, y luego usa el bit de orden inferior para indicar si se trata de un nodo hoja o un nodo interior.
Técnicamente, la
Parser
mónada aquí está sobre-matando, ya que solo se creó un analizador,decoder
y podría haber puesto la lógica de encadenamiento del analizador directamente allí. Pero de esta manera, el decodificador es muy claro y, aParser
pesar de su pequeño tamaño, es un marco de análisis simple y razonable.Ejecutar esto te lleva a:
fuente
Cía
El codificar:
La decodificación:
Principal:
Nota. Cada nodo está codificado como dos enteros (más un int para el recuento de nodos).
Entonces el árbol suministrado codifica así:
fuente
En Ruby, con la misma codificación que @MtnViewMark :
El costo es un entero por nodo (
data << 1 | has_childs
):fuente
Dado un árbol binario con
n
nodos, esto lo codifica en una lista de2n + 1
enteros. Los algoritmos de codificación y decodificación tienenO(n)
complejidad.Utilizo el entero 0 como marcador centinela cuando codifico, lo que indica cuándo despliego la recursividad. Luego, cuando estoy decodificando, pongo los nodos de árbol que estoy creando en una pila (más o menos) y uso los 0 en la lista para realizar un seguimiento de dónde agregar el siguiente nodo. No lo he intentado, pero estoy bastante seguro de que la decodificación se rompería si el árbol no estuviera completo.
Guardado esto como
encode.c
compilado y ejecutado. Este programa utiliza el árbol de ejemplo que proporcionó, y lo he probado en algunos otros con éxito.fuente
Mi código codifica el árbol en un recorrido previo al pedido, cada hoja en dos entradas (sus datos seguidos de 0) y cada nodo interno en un int (sus datos seguidos por su hijo izquierdo, luego su derecho). Para un árbol binario completo (como lo define) con n nodos, n debe ser impar, y hay (n + 1) / 2 hojas y (n-1) / 2 nodos internos, por lo que es 3n / 2 + 1 / 2 enteros para la codificación.
advertencia: no probado, solo lo escribí.
fuente
Aquí está mi intento. Almacena el árbol en una matriz de tamaño 2 ** profundidad + 1. Se utiliza
a[0]
para mantener el tamaño ya[size]
para mantener el índice del primer "nodo vacío" que encuentra en un recorrido transversal primero. (Un nodo vacío es el lugar donde se almacenaría un hijo si el padre tuviera uno). Cada nodo vacío contiene el índice del siguiente nodo vacío que se encontrará.Este esquema evita la reserva de bits para marcar los elementos secundarios de presense, por lo que cada nodo puede usar el rango entero completo. También permite árboles desequilibrados: un padre solo puede tener un hijo.
salida:
El codificador:
El decodificador:
(gracias @daniel sobral por arreglar el formato)
fuente
Scala:
Este es un enfoque que utiliza una sintaxis obsoleta, pero se compila sin errores en Scala 2.9.1. Genera un árbol y decodifica cada árbol codificado en la misma matriz utilizada para la codificación. Tal vez hoy me deshago de las advertencias obsoletas.Wow, eso fue simple. La primera idea funcionó de inmediato.
fuente