득이공간

[백준 C++] 2263 트리의 순회 - 트리 본문

PS/알고리즘 문제풀이

[백준 C++] 2263 트리의 순회 - 트리

쟁득 2024. 4. 12. 14:44

 

2263번: 트리의 순회

첫째 줄에 n(1 ≤ n ≤ 100,000)이 주어진다. 다음 줄에는 인오더를 나타내는 n개의 자연수가 주어지고, 그 다음 줄에는 같은 식으로 포스트오더가 주어진다.

www.acmicpc.net


 

문제풀이

 

중위 순회와 후위 순회 노드 순서가 주어졌을 때 전위 순회 노드 순서를 출력하는 문제입니다.

후위 순회의 맨 뒷 노드를 루트 노드로 지정할 때,

해당 루트 노드를 기준으로 중위 순회 정보에서 양 옆을 쪼개서 재귀 함수를 호출하도록 구현했습니다.

 

다음은 예시입니다.

 

 

중위 순회: 14 5 10 1 16 7 13 3 9 11 2 6 15 4 12 8

후위 순회: 14 10 7 16 1 5 3 13 11 2 4 8 12 15 6 (9)

 

이런 모양의 트리가 주어졌을 때,

후위 순회의 맨 뒷 노드(9)가 첫 루트 노드임을 알 수 있습니다.

해당 루트 노드를 출력하고 중위 순회에서 루트 노드를 기준으로 양 옆을 쪼개줍니다.

 

중위 순회: (14 5 10 1 16 7 13 3) (9) (11 2 6 15 4 12 8)

후위 순회: 14 10 7 16 1 5 3 13 11 2 4 8 12 15 6 (9)

 

쪼개진 중위 순회의 왼쪽 자식 그룹과 오른쪽 자식 그룹의 인덱스 정보를 이용해서

후위 순회도 두 그룹으로 쪼개줍니다.

 

중위 순회: (14 5 10 1 16 7 13 3) (9) (11 2 6 15 4 12 8)

후위 순회: (14 10 7 16 1 5 3 13) (11 2 4 8 12 15 6) (9)

 

그 다음 중위 순회의 왼쪽 자식 시작 인덱스(LIS), 끝 인덱스(LIE),

후위 순회의 왼쪽 자식 시작 인덱스(LPS), 끝 인덱스(LPE)를 파라미터로 재귀함수를 호출해줍니다.

그리고 오른쪽 자식도 마찬가지로 네 개의 매개변수(RIS, RIE, RPS, RPE)를 재귀로 넘겨주어 호출합니다.

 

이 과정을 반복합니다.


코드

cpp
#include <iostream> #include <algorithm> using namespace std; int N; int IO[100001]; int PO[100001]; void Recursive(int IS, int IE, int PS, int PE) { int Root = PO[PE]; ‌cout << Root << ' '; if (PS == PE) { ‌‌return; } int IRIdx = find(IO + IS, IO + IE + 1, Root) - IO; int LeftNum = IRIdx - IS; int RightNum = IE - IRIdx; int RF = IO[IRIdx + 1]; int PRFIdx = find(PO + PS, PO + PE + 1, RF) - PO; if (PE - PRFIdx < RightNum) { ‌‌PRFIdx -= RightNum - (PE - PRFIdx); } if (PRFIdx - 1 >= PS && PRFIdx - 1 < PE) { ‌‌Recursive(IS, IRIdx - 1, PS, PRFIdx - 1); } if (PRFIdx >= PS && PRFIdx < PE) { ‌‌Recursive(IRIdx + 1, IE, PRFIdx, PE - 1); } } int main() { ‌ios::sync_with_stdio(false); ‌cin.tie(nullptr); cout.tie(nullptr); ‌cin >> N; for (int i = 0; i < N; ++i) { ‌‌cin >> IO[i]; } for (int i = 0; i < N; ++i) { ‌‌cin >> PO[i]; } Recursive(0, N - 1, 0, N - 1); }