PAT-二叉树遍历-DFS-BFS相关问题解决方案整理

如何建树?

方式一(二叉树)

dfs使用root左右指针建立树节点关系,返回根节点root

方式二(二叉树)

dfs使用二维数组,int nds[n][2],如:nds[i][0]表示i节点的左子节点,nds[i][1]表示i节点的右子节点

方式三(树)

dfs使用邻接表保存树节点关系,vector nds[n],如:nds[i][j]表示节点i的子节点j

序列转换

前序后序转中序

后序倒数第一个节点为根root,root在前序中为第一个节点
后序倒数第二个节点为root的右子树的根节点rightTreeRoot,rightTreeRoot在前序中将序列分为左边部分(root和root的左子树),右边部分(root的右子树包含rightTreeRoot)
若rightTreeRoot前只有一个节点,那么说明该rightTreeRoot的父节点root只有一个子节点,即rightTreeRoot既可以为root的左子节点也可以为root的右子节点

node * create(int preL,int preR,int postL,int postR) {
    if(preL>preR)return NULL;
    node * root = new node;
    root->data=post[postR];
    root->left=NULL;
    root->right=NULL;
    if(preL==preR)return root;
    int k=preL+1;
    while(k<=preR&&pre[k]!=post[postR-1])k++;
    if(k-preL>1) {
        root->left=create(preL+1,k-1,postL,postL+(k-preL-1)-1);
        root->right=create(k,preR,postL+(k-preL-1),postR-1);
    } else {
        unique = false;
        root->right=create(k,preR,postL+(k-preL-1),postR-1);
    }
    return root;
}

前序中序转后序

前序第一个节点为根root,root在中序中位置为k,将序列分为左边部分(root的左子树),右边部分(root的右子树)
inL~k-1为下次左递归的后序序列,其对应的后序序列为preL+1~preL+(k-inL);
k+1~inR为下次递归的后序序列,其对应的后序序列为postL+(k-inL)+1~preR;

void postFirst(int inL,int inR, int preL,int preR) {
    if(inL>inR||flag) return;
    int k=inL;
    while(k<inR&&in[k]!=pre[preL])k++;
    postFirst(inL, k-1, preL+1, preL+(k-inL));
    postFirst(k+1, inR, preL+(k-inL)+1, preR);
    if(flag==false) {
        printf("%d", pre[preL]);
        flag=true; 
    }
}

后序中序转前序

后序第一个节点为根root,root在中序中位置为k,将序列分为左边部分(root的左子树),右边部分(root的右子树)
inL~k-1为下次左递归的后序序列,其对应的后序序列为postL~postL+(k-inL)-1;
k+1~inR为下次递归的后序序列,其对应的后序序列为postL+(k-inL)~postR-1;

node * create(int postL,int postR,int inL,int inR) {
    if(postL>postR)return NULL;
    node * root=new node;
    root->data=post[postR];
    // 找到当前根节点在中序遍历中的位置
    int i;
    for(i=inL; i<=inR; i++) {
        if(post[postR]==in[i])
            break;
    }
    int numLeft=i-inL;
    root->left=create(postL,postL+numLeft-1,inL,inL+numLeft-1);//inL+numLeft=i
    root->right=create(postL+numLeft,postR-1,inL+numLeft+1,inR);//inL+numLeft=i
    return root;
}

如何进行层级遍历序列?

方式一

建树,借助队列层级遍历

方式二

建树时,记录index到结点(如:节点i的左子节点index=2i+1,节点i的右子节点index=2i+2),之后节点index升序排序,依次打印即为层序序列

如何记录层级?

DFS中如何记录层级?如何记录每层叶子节点数?


dfs函数参数中记录当前处理节点的层级,使用int max_h记录最大层数方便后续层级遍历,可使用int leaf[n]记录对应层级叶子节点数

void dfs(int index,int h) {
    max_h=max(h,max_h);//记录最大层数
    if(nds[index].size()==0) { //叶子节点
        leaf[h]++;
        return;
    }
    for(int i=0; i<nds[index].size(); i++) {
        dfs(nds[index][i],h+1);
    }
}

BFS中如何记录层级?如何记录每层叶子节点数?


使用int h[n]记录节点层级,如:h[i]即为节点i的层级,使用int max_h记录最大层数方便后续层级遍历,可使用int leaf[n]记录对应层级叶子节点数

void bfs(){
    queue<int> q;
    q.push(1);
    while(!q.empty()){
        int now = q.front();
        q.pop();
        max_h=max(max_h,h[now]);
        if(nds[now].size()==0){
            leaf[h[now]]++;
        } else{
            for(int i=0;i<nds[now].size();i++){
                h[nds[now][i]]=h[now]+1;
                q.push(nds[now][i]);
            }
        }
    } 
}

猜你喜欢

转载自www.cnblogs.com/houzm/p/12323919.html