이진 나무
이진 트리는 세 가지 유형의 노드가있는 트리입니다.
- 자식이없는 터미널 노드
- 하나의 자식이있는 단항 노드
- 각각 2 개의 자식이있는 이진 노드
BNF (Backus–Naur 형식)로 주어진 다음 문법으로 표현할 수 있습니다 .
<e> ::=
<terminal>
| <unary>
| <binary>
<terminal> ::=
"0"
<unary> ::=
"(1" <e> ")"
<binary> ::=
"(2" <e> " " <e> ")"
이 문법에서 노드는 사전 순서대로 제공되며 각 노드는 자식 수인 숫자로 표시됩니다.
모츠 킨 숫자
Motzkin 숫자 ( OEIS ) ( Wikipedia )는 많은 해석을 가지고 있지만 한 가지 해석은 n
Motzkin 숫자는 n
노드 가있는 별개의 이진 트리의 수입니다 . Motzkin 숫자 표가 시작됩니다
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 개의 노드가있는 9 개의 이진 트리는
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)
중복 트리를 확인할 수있는 장소
중복을 확인하는 곳은 M (5)입니다.
이 하나의 나무는 M (4) 나무에서 M (5)에 대해 두 번 생성되었습니다.
(2 (1 0) (1 0))
첫 번째에 단항 분기를 추가하여
(2 (1 0) 0)
둘째로 단항 분기를 추가하여
(2 0 (1 0))
BNF 이해
BNF는 간단한 규칙으로 구성됩니다.
<symbol> ::= expression
여기서 왼쪽은로 둘러싸인 기호 이름 <>
입니다.
오른쪽에는 심볼을 구성하는 표현이 있습니다. 일부 규칙은 구성에서 다른 규칙을 사용합니다 (예 :
<e> ::= <terminal>
e
될 수 있습니다 terminal
일부 규칙에는 기호를 구성하는 데 사용되는 문자가 있습니다. 예 :
<terminal> ::= "0"
terminal
문자 0입니다.
일부 규칙에는 여러 가지 방법으로 구성 할 수 있습니다. 예 :
<e> ::=
<terminal>
| <unary>
| <binary>
는 e
a <terminal>
또는 a <unary>
또는 a 일 수 있습니다 <binary>
.
그리고 일부 규칙은 일련의 부분입니다.
<unary> ::= "(1" <e> ")"
A는 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)
.