1064 완전한 이진 검색 트리 (출력 시퀀스의 전순 주사를 사용하여 BST 이진 검색)

1064 완전한 이진 검색 트리 (30 分)

이진 검색 트리 (BST)는 재귀 적으로 다음과 같은 속성이 있습니다 이진 트리로 정의된다 :

  • 노드의 왼쪽 하위 트리 노드의 키보다 작은 키 노드 만 포함되어 있습니다.
  • 노드의 오른쪽 서브 트리보다 크거나 노드의 키와 동일한 키 노드 만 포함되어 있습니다.
  • 모두 왼쪽과 오른쪽 서브 트리도 이진 검색 나무이어야합니다.

완전한 이진 트리 (CBT)를 완전히 왼쪽에서 오른쪽으로 채워 바닥 수준의 가능한 예외로 가득 나무입니다.

이제 별개의 음이 아닌 정수 키의 순서를 주어진 고유 한 BST는이 나무가 또한 CBT해야한다는 필요한 경우 구성 할 수있다. 당신은 출력이 BST의 레벨 순서 탐색 순서를 생각하고 있습니다.

입력 사양 :

각 입력 파일은 하나의 테스트 케이스가 포함되어 있습니다. 각 경우에있어서, 첫 번째 라인은 양의 정수 N (≤1000)을 포함한다. 그리고 N 별개의 음이 아닌 정수 키는 다음 줄에 주어진다. 라인의 모든 번호는 공백으로 구분하여 2000보다 큰되지 않습니다.

출력 사양 :

각 테스트 케이스의 경우, 한 줄에 해당하는 완전한 이진 검색 트리의 레벨 순서 탐색 순서로 인쇄 할 수 있습니다. 라인의 모든 번호는 공백으로 구분해야하며, 줄 끝에 여분의 공간이 없어야합니다.

샘플 입력 :

10
1 2 3 4 5 6 7 8 9 0

샘플 출력 :

6 3 8 1 5 7 9 0 2 4

 

참조 갱스터 블로그 : https://blog.csdn.net/richenyunqi/article/details/78868563

이 주제와 아이디어

방법 1 : 이진 트리 검색의 전체 특성을 사용하여 

N은 접합점의 개수

순서대로 배열 노드들에서 얻어진 1. 먼저 입력 N 정렬 값

2. 라운딩 로그 그래피 (플로어 () CEIL은 올림 내림) (N + 1)의 최종 층의 높이 (h)의 예를 제공하기 위해 아래로 제거는 : N = 노드 (7)의 높이가 3 (때문에 단지 루트 노드의 값은 마지막 로그 N + 1 개 계층 키를 제거하는 데 필요한)

 3. 노드의 개수가 최종 층을 얻었다 : N - (POW (2, H) - 1) (단 좌측 노드가 될 수있다, 우측 노드가)

 샘플의 시험 배치 순서 4. 1 : 우리는 좌측 노드 NUM의 수를 알고 0123456789 긴 (의해 좌측 (가장 좌측 노드 선주문) NUM + 결정될 수있다 다음 루트 노드 후) 왼쪽 하위 트리 오른쪽 서브 트리, 편리한 루트 인덱스 레코드 인덱스 시퀀스 출력의 세트에 뿌리를 찾을 수 재귀 적으로 계속

그래서 TEMP2 = (POW (2 시간) - 1) / 2

5. 노드의 좌측 서브 트리의 키 번호를 결정하는 방법이 경우 노드의 최대 개수는 마지막 층은 좌측 서브 트리에 저장 될 수 TEMP2 수득 하였다 (저장 가능한 최대 용량의 마지막 절반이 하나의) 분 (TEMP2, N에 의해 ​​- 왼쪽으로 합산 노드 따라서 수 - (POW (2, H) (1)))은 최종 층 엘리멘트의 좌측 서브 트리를 얻었다이 경우에 저장 될 수 TEMP2 -1 좌측 서브 트리의 마지막 층 번호가 제거 될 수있다 : 합계 = TEMP2 - 1 + 분 (TEMP2, N - (POW (2, H) - 1))                                        

 

특정 코드

:

#include<iostream>
#include<algorithm>
#include<vector>
#include<cmath>
using namespace std;
int n;
vector<int> in,level;
void levelOrder(int start, int end, int index){
	if(start > end) return;
    int sum = end - start + 1;
	int height = (int)floor(log((sum) + 1) / log(2)); //还没强转 log在cmath库中 
	int temp1 = sum - (int)(pow(2, height) - 1);  //最后一层的结点数量 
	int temp2 = pow(2, height) / 2; 	   //最后一层能够容纳的最大结点数量的一半 
	temp1 = min(temp1, temp2);         //取最小是因为temp1可能包含右结点,现在只需要算出左结点
	temp1 = start + temp1 + temp2 - 1;         //此时左子树结点总数为(temp1 + temp2 - 1) 同时加上start(left)就是中序遍历中根结点的下标
	level[index] = in[temp1];
	levelOrder(start, temp1 - 1, 2 * index + 1);
	levelOrder(temp1 + 1, end, 2 * index + 2);
}	
int main(){
	scanf("%d", &n);
	in.resize(n);    //在全局遍历中 用(n)也不能scanf输入 这里注意 只有用resize容器具有具体长度时 才能用scanf赋值 
	level.resize(n);
	for(int i = 0; i < n; i++){
		scanf("%d", &in[i]);
	}
	sort(in.begin(), in.end());
	levelOrder(0, n-1, 0);	
	for(auto i = 0; i < n; i++){
		if(i != 0) printf(" ");
		printf("%d", level[i]);
	}
	return 0;
}

방법 2 :

               순차적으로 각 발견 한 방법 루트 배열 수준으로 각 노드 점 첨자 인덱스의 노드를

               더 편리한 방법은 어레이의 각 요소의 높이에 의해 결정된 각 루트 전순 번호를 찾기 위해 요구되는 수준으로 첨가되지 않은 직접 시퀀스 전순 주사로하고, 좌측 노드 발견

    

              특정 코드 :

           

#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
int n,position=0;
vector<int> level, in;
void levelOrder(int index){
	if(index > n-1) return;      //注意这里是n-1 因为根节点的下标是0 那么最后一个结点的下标为n-1 
	levelOrder(index * 2 + 1);   // 完全二叉搜索树中中序遍历中 第一个结点会是最左边的结点 
	level[index] = in[position++];
	levelOrder(index * 2 + 2);
}
int main(){
	scanf("%d", &n);
	level.resize(n);in.resize(n);
	for(int i = 0; i < n; i++){
		scanf("%d", &in[i]);
	}
	sort(in.begin(),in.end());
	levelOrder(0);
	for(int i = 0; i < n; i++){
		if(i != 0) printf(" ");
		printf("%d", level[i]);
	}
	return 0;
}

 

추천

출처blog.csdn.net/qq_41698081/article/details/91046576