树的双亲表示法

83 阅读1分钟

题目

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;
}