用set维护有序序列,逐一插入元素构造搜索二叉树BST
D. Tree Construction(给一个序列建立二叉搜索树,输出除第一个节点(根节点)外 每个节点的父节点
逐一插入节点构造二叉树的过程中,用set维护已经插入二叉树的有序序列
对于即将插入的节点,要在二叉树中找到父节点(顺便记录父节点)
要先在二叉树中找到与他相邻的值,要么是比它小的数的右孩子,要么是
比它大的数的左孩子
总之父节点一定在与他相邻的两个节点当中,因为找位置插入的规则就是先找到相邻节点
举个例子,虽然根节点的左子树的最右下角节点与根节点相邻但根节点已有左孩子,这个最右下节点不能认根结点当父节点,插入规则就是这样的,会找到一个没有左/右孩子的节点插入
函数lower_bound()在first和last中的前闭后开区间进行二分查找,
返回大于或等于val的第一个元素位置。
如果所有元素都小于val,则返回last的位置
也就是会返回一个(s.end())++
没找到会返回s.end(),一定要讨论这点,说明该节点只有相邻更小的节点
//#include<iostream>
//#include<stdio.h>
//#include <stdlib.h>
//#include <math.h>
//#include<algorithm>
//#include <bits/stdc++.h>
//----------------不许写万能头
#include <iostream>
#include <map>
#include <set>
using namespace std;
set<int> s;
map<int,int> lm;//插入 父节点和它映射的左儿子
map<int,int> rm;//插入 父节点和它映射的右儿子
//判断一个就够了,左节点有右儿子一定 做右节点的左儿子
int main(){
ios::sync_with_stdio(false);cin.tie(0);
int n;
cin>>n;
int v;
cin>>v;
s.insert(v);
int res;//先记录每次输出的父节点数值,最后确定的那个格式
for(int i=2;i<=n;i++){
cin>>v;
set<int>::iterator it;
it=s.lower_bound(v);
//没找到会返回s.end(),一定要讨论这点,说明该节点只有相邻更小的节点
//要么做相邻更小节点的右儿子要么做相邻更大的节点的左儿子
//it返回s.end()或者it已有左儿子显然只能选前者
if(it!=s.end()&&lm.count(*it)==0){//后者情况
res=*it;
lm.insert(make_pair(*it,v));
}
else{
it--;
res=*it;
// rm.insert(make_pair(*it,v));记录而已,不靠这个判断是否有右儿子
}
s.insert(v);
if(i!=n)cout<<res<<" ";
else cout<<res;
}
return 0;
}