По-перше, я припускаю, що всі елементи відрізняються. Жодна кількість послідовностей не збирається повідомити вам форму дерева з елементами [3,3,3,3,3]
. Можна, звичайно, реконструювати деякі дерева з повторюваними елементами; Я не знаю, які хороші умови існують.
Продовжуючи негативні результати, ви не можете повністю відновити бінарне дерево з його послідовності попереднього замовлення та після замовлення. [1,2]
попереднє замовлення, [2,1]
після замовлення має бути 1
в корені, але це 2
може бути або ліва дитина, або права дитина. Якщо вас не хвилює ця неоднозначність, ви можете реконструювати дерево за допомогою наступного алгоритму:
- Нехай - обхід попереднього замовлення, а - обхід після замовлення. У нас повинно бути , і це корінь дерева.[ х1, … , Хн][ ун, … , У1]х1= у1
- х2 - найменша ліва дитина кореня, а - найменша права дитина. Якщо , кореневий вузол не одинаковий; повторити курси на та щоб створити єдине піддерево.у2х2= у2[ х2, … , Хн][ ун, … , У2]
- В іншому випадку, нехай і є такими індексами, що і . - обхід попереднього замовлення лівого піддерева, , правого піддерева, і аналогічно для обходу після замовлення. У лівому піддереві є елементів, а в правому піддереві є елементів. Повторіть один раз для кожного піддерева.
До речі, цей метод узагальнює дерева з довільним розгалуженням. За допомогою довільного розгалуження з’ясуйте розмір лівого піддерева і відріжте його елементи з обох списків, потім повторіть, щоб відрізати друге піддерево зліва тощо.ijх2= уiу2= хj[ х2, … , Хj - 1][xj,…,xn]j−2=n−i+1i−2=n−j+1
j−2
Як зазначалося, час роботи - це з найгіршим випадком (у випадку з двома дітьми ми шукаємо кожен список лінійно). Ви можете перетворити це на якщо попередньо обробити списки для побудови кінцевої структури карти від значень елементів до позицій у вхідних списках . Також використовуйте масив або кінцеву карту, щоб перейти від індексів до значень; дотримуйтесь глобальних індексів, щоб рекурсивні дзвінки отримували цілі карти і приймали діапазон як аргумент, щоб знати, на що діяти.O(n2)Θ(n2)nO(nlg(n))nlg(n)
За допомогою обходу попереднього замовлення та обходу замовлення ви можете відновити дерево таким чином:[ z 1 , … , z n ][x1,…,xn][z1,…,zn]
- Корінь - голова обходу попереднього замовлення .x1
- Нехай - індекс такий, що . Тоді - це порядок обходу лівої дитини, а - порядок обходу правильної дитини. За кількістю елементів, - це обхід попереднього замовлення лівої дитини та що належить дитині. Повторіть, щоб побудувати лівий і правий підтрубки.z k = x 1kzk=x1[ z k + 1 , … , z n ] [ x 2 , … , x k ] [ x k + 1 , … , x n ][z1,…,zk−1][zk+1,…,zn][x2,…,xk][xk+1,…,xn]
Знову ж таки, цей алгоритм є як зазначено, і його можна виконати в якщо список попередньо обробляється в кінцевій карті від значень до позицій.O ( nO(n2)O(nlg(n))
Після замовлення плюс замовлення, звичайно, симетричний.