Двійкові дерева
Бінарне дерево - це дерево з вузлами трьох типів:
- кінцеві вузли, у яких немає дітей
- одинарні вузли, у яких одна дитина
- двійкові вузли, у яких по двоє дітей
Ми можемо представити їх наступною граматикою, наведеною у BNF (форма Backus – Naur):
<e> ::=
<terminal>
| <unary>
| <binary>
<terminal> ::=
"0"
<unary> ::=
"(1" <e> ")"
<binary> ::=
"(2" <e> " " <e> ")"
У цій граматиці вузли задаються в передпорядку, і кожен вузол представлений цифрою, яка є кількістю дітей, які він має.
Числа Моцкіна
Числа Моцкіна ( OEIS ) ( Вікіпедія ) мають багато тлумачень, але одна інтерпретація полягає в тому, що n
число Моцкіна - це кількість різних двійкових дерев з n
вузлами. Починається таблиця чисел Моцкіна
N Motzkin number M(N)
1 1
2 1
3 2
4 4
5 9
6 21
7 51
8 127
...
наприклад, M(5)
це 9, а дев'ять різних двійкових дерев з 5 вузлами є
1 (1 (1 (1 (1 0))))
2 (1 (1 (2 0 0)))
3 (1 (2 0 (1 0)))
4 (1 (2 (1 0) 0))
5 (2 0 (1 (1 0)))
6 (2 0 (2 0 0))
7 (2 (1 0) (1 0))
8 (2 (1 (1 0)) 0)
9 (2 (2 0 0) 0)
Завдання
Візьміть одне додатне ціле число n
як вхід і вивід усіх окремих двійкових дерев з n
вузлами.
Приклади n
від 1 до 5 з дужками, включені для читабельності
0
(1 0)
(1 (1 0))
(2 0 0)
(1 (1 (1 0)))
(1 (2 0 0))
(2 0 (1 0))
(2 (1 0) 0)
(1 (1 (1 (1 0))))
(1 (1 (2 0 0)))
(1 (2 0 (1 0)))
(1 (2 (1 0) 0))
(2 0 (1 (1 0)))
(2 0 (2 0 0))
(2 (1 0) (1 0))
(2 (1 (1 0)) 0)
(2 (2 0 0) 0)
Вхідні дані
Вхід буде одним натуральним числом.
Вихідні дані
Вихід повинен бути зрозумілим поданням різних бінарних дерев із такою кількістю вузлів. Не обов'язково використовувати точний рядок, наведений вище в граматиці BNF: достатньо, щоб використовуваний синтаксис давав однозначне зображення дерев. Наприклад , ви могли б використовувати []
замість ()
, додатковий рівень дужок [[]]
замість []
, зовнішньої дужки присутні або відсутні, додаткові коми або без ком, зайві прогалини, дужки чи ні дужка і т.д.
Все це рівнозначно:
(1 (2 (1 0) 0))
[1 [2 [1 0] 0]]
1 2 1 0 0
12100
(1 [2 (1 0) 0])
.:.--
*%*55
(- (+ (- 1) 1))
-+-11
Також варіант, запропонований @xnor у коментарі. Оскільки існує спосіб перекласти це у формат, який можна зрозуміти, він прийнятний.
[[[]][]] is (2 (1 0) 0)
Щоб зробити це легше зрозуміти , перетворити деякі з []
в ()
подобається так
[([])()]
Тепер, якщо ви почнете з
[]
потім вставити двійковий файл, який потребує двох отриманих виразів
[()()] which is 2
а потім для першого () вставити унар, якому потрібен один вираз, який ви отримаєте
[([])()] which is 21
але так []
чи ()
без внутрішнього брекета може представляти 0 , який не потребує більше виразів ви можете інтерпретувати його як
2100
Зауважте, що відповіді повинні теоретично працювати з нескінченною пам'яттю, але, очевидно, не вистачить пам'яті для обмеженого введення, що залежить від реалізації.
Варіації випуску
BNF xnor Christian Ben
b(t, b(t, t)) [{}{{}{}}] (0(00)) (1, -1, 1, -1)
b(t, u(u(t))) [{}{(())}] (0((0))) (1, -1, 0, 0)
b(u(t), u(t)) [{()}{()}] ((0)(0)) (1, 0, -1, 0)
b(b(t, t), t) [{{}{}}{}] ((00)0) (1, 1, -1, -1)
b(u(u(t)), t) [{(())}{}] (((0))0) (1, 0, 0, -1)
u(b(t, u(t))) [({}{()})] ((0(0))) (0, 1, -1, 0)
u(b(u(t), t)) [({()}{})] (((0)0)) (0, 1, 0, -1)
u(u(b(t, t))) [(({}{}))] (((00))) (0, 0, 1, -1)
u(u(u(u(t)))) [(((())))] ((((0)))) (0, 0, 0, 0)
Можливе місце для перевірки дублікатів дерев
Одне місце для перевірки дубліката - за допомогою М (5).
Це одне дерево було сформовано двічі для M (5) з M (4) дерев
(2 (1 0) (1 0))
Перший додавши одинарну гілку до
(2 (1 0) 0)
по-друге, додавши одинарну гілку до
(2 0 (1 0))
Розуміння BNF
BNF складається з простих правил:
<symbol> ::= expression
де зліва - назва символу в оточенні <>
.
Праворуч - вираз для побудови символу. Деякі правила використовують інші правила в побудові, наприклад
<e> ::= <terminal>
e
може бути terminal
а деякі правила містять символи, які використовуються при побудові символу, наприклад
<terminal> ::= "0"
terminal
- це лише нульовий символ.
Деякі правила мають кілька способів їх побудови, наприклад
<e> ::=
<terminal>
| <unary>
| <binary>
А e
може бути a <terminal>
або a <unary>
або a <binary>
.
А деякі правила - це послідовність частин, наприклад
<unary> ::= "(1" <e> ")"
unary
Це символи (1
слід , що можна побудувати для e
наступних )
.
Ви завжди починаєте зі стартового правила, яке для цього потрібно <e>
.
Деякі прості приклади:
Найпростіша послідовність - справедлива 0
. Тож ми починаємо із стартового правила <e>
і бачимо, що є три варіанти:
<terminal>
| <unary>
| <binary>
тому візьміть перший <terminal>
. Тепер термінал не має вибору і є 0
. Так замінити <terminal>
з 0
в <e>
правилах , і ви зробили.
Тоді наступний (1 0)
. Почніть з <e>
та використовуйте правило, <unary>
яке має
"(1" <e> ")"
Тепер це потрібно, <e>
тому ми повертаємось до <e>
та робимо вибір одного з трьох, цього разу вибираючи, <terminal>
що дає 0
. Заміна 0
на (1 <e> )
дає (1 0)
, і це замінюється на <unary>
так <e>
є (1 0)
.