题目
EOJ data structure 1063
如何输出后序遍历。
先考虑如何才能压缩查找时间。首先,我们不需要考虑树存放的数据的情况。我们只需要考虑树各节点之间的逻辑关系。
思路1
- 节点的初始编号就是数据。所以,为了节省查找时间,要按照每个节点父节点的大小来进行排序。这样可以让父节点相同的数据点聚集起来,还有助于二分查找的实现(便于找子节点)。
- 考虑到树原本的状态在排序后可能会被打乱,影响后序遍历的效果。所以排序时也要保证父节点相同的节点原编号顺序不变。
#include<bits/stdc++.h>
using namespace std;
#ifdef LOG
ofstream lout("log.txt");
#endif
//-----------------------------------
#define endl '\n'
using LL=long long;
constexpr int SIZE=1e5+7;
struct node{
int NO;
int parent;
bool operator<(const node& x)const{
if(parent==x.parent){
return NO<x.NO;
}
return parent<x.parent;
}//sort based on parent size
};
node arr[SIZE];
int N;
int binary_search(int x){
int l=0,r=N-1;
int mid;
while(l<=r){
mid=(l+r)/2;
if(arr[mid].parent==x){
while(arr[mid-1].parent==x)
--mid;
return mid;
}else if(arr[mid].parent<x){
l=mid+1;
}else{
r=mid-1;
}
}
return -10;
}
void postOrder(int p){
int pos=binary_search(p);
if(pos!=-10){
while(arr[pos].parent==p){
postOrder(arr[pos].NO);
++pos;
}
}
cout<<p<<' ';
}
void solve(){
cin>>N;
int tem;
for(int iN=0;iN<N;++iN){
cin>>tem;
arr[iN].NO=iN;
arr[iN].parent=tem;
}
sort(arr,arr+N);
postOrder(0);
}
int main(){
#ifdef LOCAL
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
#endif
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
solve();
return 0;
}
思路2
用map<int,vector<int>>存储父节点到其所有子节点的映射。
#include<bits/stdc++.h>
using namespace std;
#ifdef LOG
ofstream lout("log.txt");
#endif
//-----------------------------------
#define endl '\n'
using LL=long long;
map<int,vector<int>> dic;
void postOrder(int p){
for(int t:dic[p]){
postOrder(t);
}
cout<<p<<' ';
}
void solve(){
int N;
cin>>N;
int tem;
for(int iN=0;iN<N;++iN){
cin>>tem;
dic[tem].push_back(iN);
}
postOrder(0);
}
int main(){
#ifdef LOCAL
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
#endif
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
solve();
return 0;
}