Eu tenho um monte de objetos em uma estrutura plana. Esses objetos têm uma propriedade ID
e uma ParentID
propriedade para que possam ser organizados em árvores. Eles não estão em uma ordem específica. Cada ParentID
propriedade não corresponde necessariamente a uma ID
na estrutura. Portanto, podem haver várias árvores emergindo desses objetos.
Como você processaria esses objetos para criar as árvores resultantes?
Não estou tão longe de uma solução, mas tenho certeza de que está longe de ser a ideal ...
Preciso criar essas árvores para inserir dados em um banco de dados, na ordem correta.
Não há referências circulares. Um nó é um RootNode quando ParentID == null ou quando ParentID não pode ser encontrado nos outros objetos
algorithm
tree
language-agnostic
Costo
fonte
fonte
Respostas:
Armazene IDs dos objetos em um mapeamento de tabela de hash para o objeto específico. Enumere todos os objetos e encontre seu pai, se existir, e atualize seu ponteiro pai de acordo.
fonte
Com base na resposta de Mehrdad Afshari e no comentário de Andrew Hanlon para uma aceleração, aqui está minha opinião.
Diferença importante para a tarefa original: Um nó raiz possui ID == parentID.
fonte
Aqui está um algoritmo JavaScript simples para analisar uma tabela plana em uma estrutura de árvore pai / filho que é executada em N tempo:
fonte
console.log(JSON.stringify(root, null, 2));
para imprimir bastante a saída.Solução Python
Por exemplo:
Produz:
fonte
def recurse(id, pages): for row in rows: if row['id'] == id: print(f'''{row['id']}:{row['parent_id']} {row['path']} {row['title']}''') recurse(row['id'], rows)
Versão JS que retorna uma raiz ou uma matriz de raízes, cada uma das quais terá uma propriedade da matriz Filhos contendo os filhos relacionados. Não depende da entrada ordenada, compacta decentemente e não usa recursão. Aproveitar!
fonte
Encontrei uma versão JavaScript incrível aqui: http://oskarhane.com/create-a-nested-array-recursively-in-javascript/
Digamos que você tenha uma matriz como esta:
E você deseja que os objetos sejam aninhados assim:
Aqui está uma função recursiva que faz isso acontecer.
Uso:
fonte
Para qualquer pessoa interessada em uma versão C # da solução de Eugene, observe que o node_list é acessado como um mapa; portanto, use um dicionário.
Lembre-se de que esta solução só funciona se a tabela for classificada por parent_id .
O nó é definido da seguinte maneira.
fonte
new Node { parent_id = 7, id = 9 },
impedenode_list.Add(item.id, item);
a conclusão porque a Chave não pode se repetir; é um erro de digitação; então, em vez de id = 9 , digite id = 8Eu escrevi uma solução genérica em C # com base na resposta do @Mehrdad Afshari:
fonte
Aqui está a solução java da resposta de Mehrdad Afshari.
fonte
Por mais vaga que a pergunta me pareça, provavelmente criaria um mapa a partir do ID para o objeto real. No pseudo-java (não verifiquei se funciona / compila), pode ser algo como:
E para procurar cada pai:
Ao reutilizar
getRealObject(ID)
e fazer um mapa de objeto para uma coleção de objetos (ou seus IDs), você também obtém um mapa pai-> filho.fonte
Eu posso fazer isso em 4 linhas de código e tempo O (n log n), assumindo que Dictionary seja algo como um TreeMap.
EDIT : Ok, e agora eu li que alguns parentIDs são falsos, então esqueça o acima e faça o seguinte:
fonte
A maioria das respostas pressupõe que você esteja procurando fazer isso fora do banco de dados. Se suas árvores são relativamente estáticas por natureza e você só precisa mapear as árvores no banco de dados, considere o uso de representações de conjuntos aninhados no lado do banco de dados. Confira os livros de Joe Celko (ou aqui para uma visão geral de Celko). Com qualquer uma das abordagens, você pode pular completamente o mapeamento das árvores antes de carregar os dados no banco de dados. Apenas pensei em oferecer isso como uma alternativa, pode ser completamente inapropriado para suas necessidades específicas. Toda a parte "ordem correta" da pergunta original implica que você precisa que a ordem esteja "correta" no banco de dados por algum motivo? Isso pode me levar a lidar com as árvores lá também.
Se estiver vinculado aos dbs do Oracle de qualquer maneira, confira o CONNECT BY para obter abordagens SQL diretas.
fonte
Não é exatamente o mesmo que o solicitante procurou, mas tive dificuldade em entender as respostas formuladas de forma ambígua fornecidas aqui e ainda acho que essa resposta se encaixa no título.
Minha resposta é mapear uma estrutura plana para uma árvore diretamente no objeto, onde tudo o que você tem é um
ParentID
em cada objeto.ParentID
énull
ou0
se é uma raiz. Oposto ao solicitante, presumo que todos os pontos válidos sejamParentID
para outra coisa na lista:fonte
aqui está uma implementação em ruby:
Ele catalogará pelo nome do atributo ou pelo resultado de uma chamada de método.
fonte
A resposta aceita parece muito complexa para mim, por isso estou adicionando uma versão Ruby e NodeJS dela
Suponha que a lista de nós simples tenha a seguinte estrutura:
As funções que transformarão a estrutura da lista plana acima em uma árvore têm a seguinte aparência
para Ruby:
para NodeJS:
fonte
null
precisa ser paraundefined
null == undefined => true
in NodeJSUma maneira elegante de fazer isso é representar os itens da lista como uma string contendo uma lista de pais separada por pontos e, finalmente, um valor:
Ao montar uma árvore, você acabaria com algo como:
Eu tenho uma biblioteca de configuração que implementa essa configuração de substituição (árvore) nos argumentos da linha de comando (lista). O algoritmo para adicionar um único item à lista em uma árvore está aqui .
fonte
Você está preso usando apenas esses atributos? Caso contrário, pode ser bom criar uma matriz de nós filhos, onde você pode percorrer todos esses objetos uma vez para criar esses atributos. A partir daí, selecione o nó com filhos, mas sem pais, e construa iterativamente sua árvore de cima para baixo.
fonte
versão java
fonte