Vamos supor que você tenha uma árvore binária completa (ou seja, cada nó interno possui exatamente dois descendentes não vazios). Cada nó contém um número inteiro diferente de zero. Você tem a tarefa de codificar e decodificar a árvore em / de uma lista de números inteiros.
A árvore é armazenada internamente, algo como:
struct node {
int data;
struct node *left, *right;
};
E você tem que implementar duas funções:
int *encode(struct node *root);
struct node *decode(int *array);
Depende de você como você codifica e decodifica.
Pontos por:
- comprimento mínimo de codificação
- complexidade (idealmente linear em número de nós)
- originalidade
Não há pontos para o comprimento do código-fonte e você não está restrito a C.
Exemplo de árvore:
5
/ \
3 2
/ \
2 1
/ \
9 9
code-challenge
tree-traversal
Alexandru
fonte
fonte
int *
é uma caixa preta para o usuário.Respostas:
~ 1,03 N
Parece que todas as respostas até agora levam pelo menos 2 * N * 32 bits para serem armazenadas. (Exceto as soluções em idiomas que permitem valores inteiros maiores que 32 bits, como as soluções Haskell e Ruby - mas elas ainda precisam de bytes extras para codificar sempre que os dados forem maiores que 16K.)
Aqui está uma solução que leva apenas N + teto (N / 32) +1 ints de armazenamento. Isso se aproxima de 1,03125 N para N grande e está abaixo de 1,1 N para todos os N maiores que 20.
A idéia é armazenar um bit extra para cada nó em que 1 é "hasChildren". Esses bits são compactados em N / 32 palavras na frente.
(compile a implementação aqui)
fonte
Este programa Haskell codifica uma árvore de n nós em n Inteiros. O truque é que ele codifique os dados do nó duplicado e, em seguida, use o bit de ordem inferior para indicar se este é um nó folha ou um nó interior.
Tecnicamente, a
Parser
mônada aqui é over-kill, já que existe apenas um analisador criado,decoder
e eu poderia ter colocado a lógica de encadeamento do analisador diretamente lá. Mas, dessa maneira, o decodificador é muito claro e,Parser
apesar do tamanho pequeno, é uma estrutura de análise simples e razoável.Ao executar isso, você obtém:
fonte
Em C
A codificação:
A decodificação:
A Principal:
Nota. Cada nó é codificado como dois números inteiros (mais um int para a contagem de nós).
Portanto, a árvore fornecida codifica assim:
fonte
Em Ruby, com a mesma codificação que @MtnViewMark :
O custo é um número inteiro por nó (
data << 1 | has_childs
):fonte
Dada uma árvore binária com
n
nós, isso a codifica em uma lista de2n + 1
números inteiros. Os algoritmos de codificação e decodificação têmO(n)
complexidade.Eu uso o número 0 como marcador de sentinela ao codificar, indicando quando desdobro a recursão. Então, quando estou decodificando, coloco os nós da árvore que estou criando em uma pilha (das sortes) e uso os 0s na lista para acompanhar onde adicionar o próximo nó. Não tentei, mas tenho certeza de que a decodificação seria interrompida se a árvore não estivesse completa.
Salve isso como
encode.c
compilado e executado. Este programa usa a árvore de exemplo que você forneceu e eu a testei em algumas outras com êxito.fonte
Meu código codifica a árvore em uma travessia de pré-encomenda, cada folha em duas entradas (seus dados seguidos por 0) e cada nó interno em um int (seus dados seguidos pelo filho esquerdo e depois pelo direito). Para uma árvore binária completa (como você a define) com n nós, n deve ser ímpar e existem (n + 1) / 2 folhas e (n-1) / 2 nós internos, então isso é 3n / 2 + 1 / 2 inteiros para a codificação.
aviso: não testado, apenas digitado.
fonte
Aqui está a minha tentativa. Ele armazena a árvore em uma matriz de tamanho 2 ** profundidade + 1. Ele usa
a[0]
para manter o tamanho ea[size]
o índice do primeiro "nó vazio" encontrado em uma travessia profunda. (Um nó vazio é o local em que um filho seria armazenado se o pai tivesse um). Cada nó vazio contém o índice do próximo nó vazio que será encontrado.Esse esquema evita a reserva de bits para marcar os filhos de presença, para que cada nó possa usar o intervalo inteiro completo. Também permite árvores desequilibradas - um pai pode ter apenas um filho.
resultado:
O codificador:
O decodificador:
(obrigado @daniel sobral por corrigir a formatação)
fonte
Scala:
Essa é uma abordagem que usa sintaxe obsoleta, mas compila sem erros no Scala 2.9.1. Ele gera uma árvore e decodifica todas as árvores codificadas para a mesma matriz usada na codificação. Talvez eu me livre de alguma maneira dos avisos obsoletos hoje.Uau - isso foi simples. A primeira ideia funcionou imediatamente.
fonte