Primeiro, vou assumir que todos os elementos são distintos. Nenhuma quantidade de sequencializações lhe dirá a forma de uma árvore com elementos [3,3,3,3,3]
. É possível reconstruir algumas árvores com elementos duplicados, é claro; Não sei que condições suficientes existem.
Continuando com os resultados negativos, você não pode reconstruir completamente uma árvore binária apenas a partir de suas seqüências de pré e pós-ordem. [1,2]
pré [2,1]
- encomenda, a pós-encomenda deve ter 1
na raiz, mas 2
pode ser a criança esquerda ou a criança certa. Se você não se importa com essa ambiguidade, pode reconstruir a árvore com o seguinte algoritmo:
- Seja o percurso de pré-ordem e [ y n , … , y 1 ] seja o percurso de pós-ordem. Devemos ter x 1 = y 1 , e esta é a raiz da árvore.[x1,…,xn][yn,…,y1]x1=y1
- é o filho mais à esquerda da raiz e y 2 é o filho mais à direita. Se x 2 = y 2 , o nó raiz é unário; recursione sobre [ x 2 , … , x n ] e [ y n , … , y 2 ] para criar a única subárvore.x2y2x2=y2[x2,…,xn][yn,…,y2]
- Caso contrário, deixa e j são os índices de tal modo que x 2 = y i e y 2 = x j . [ x 2 , … , x j - 1 ] é a travessia de pré-ordem da subárvore esquerda, [ x j , … , x n ] a da subárvore direita e da mesma forma para as travessias de pós-ordem. A subárvore esquerda tem j - 2 = n - i +ijx2=yiy2=xj[x2,…,xj−1][xj,…,xn] elementos e a subárvore direita possui i - 2 = n - j + 1 elementos. Recursar uma vez para cada subárvore.
A propósito, esse método generaliza para árvores com ramificações arbitrárias. Com ramificações arbitrárias, descubra a extensão da subárvore esquerda e recorte seuselementos j - 2 de ambas as listas, depois repita para cortar a segunda subárvore da esquerda e assim por diante.j−2=n−i+1i−2=n−j+1
j−2
Como afirmado, o tempo de execução é com Θ ( n 2 ) no pior caso (no caso de dois filhos, pesquisamos cada lista linearmente). Você pode transformar isso em O ( nO(n2)Θ(n2) se você pré-processar as listas para criar um nO(nlg(n)) estrutura finita do mapa, dos valores dos elementos às posições nas listas de entrada. Também use uma matriz ou mapa finito para ir de índices a valores; atenha-se aos índices globais, para que as chamadas recursivas recebam todos os mapas e tomem um intervalo como argumento para saber em que agir.nlg(n)
Com o percurso de pré-ordem e o percurso em ordem [ z 1 , … , z n ] , você pode reconstruir a árvore da seguinte maneira:[x1,…,xn][z1,…,zn]
- A raiz é a cabeça da passagem de pré-ordem .x1
- Seja o índice tal que z k = x 1 . Então [ z 1 , … , z k - 1 ] é a travessia em ordem do filho esquerdo e [ z k + 1 , … , z n ] é a travessia em ordem do filho certo. Indo pelo número de elementos, [ x 2 , … , x k ] é a travessia de pré-ordem do filho esquerdo e [ x kkzk=x1[z1,…,zk−1][zk+1,…,zn][x2,…,xk]o da criança certa. Recomenda-se criar as subárvores esquerda e direita.[xk+1,…,xn]
Novamente, esse algoritmo é conforme declarado, e pode ser executado em O ( nO(n2) se a lista for pré-processada em um mapa finito de valores a posições.O(nlg(n))
A pós-ordem e a ordem são obviamente simétricas.
2
é um filho esquerdo ou um filho direito. Isso corresponde ao caso "subárvore única" do algoritmo de reconstrução.