11.1再談樹

有n個頂點的樹具有以下3個特點:連通,不含圈,恰好包含n-1條邊,有意思的是,具備上述3個特點中的任意兩個,就可以推出第三個

11.1.1無根樹轉有根樹

分析:

鄰接矩陣佔用的空間很大,用vector數組即可。由於n個結點的樹,只有n-1條邊,vector數組實際佔用的空間與n成正比

vector<int>G[maxn];
void read_tree(){
    int u,v;
    scanf("%d",&n);
    for(int i=0;i<n-1;i++){
        scanf("%d%d",&u,&v);
        G[u].push_back(v);
        G[v].push_back(u);
    }
}
轉化過程如下:

void dfs(int u,int fa){  //遞歸轉化以u爲根的子樹,u的父節點fa
    int d=G[u].size(); //結點u的相鄰點個數
    for(int i=0;i<d;i++){
        int v=G[u][i];  //結點u的第i個相鄰點V
        if(v!=fa)
            dfs(v,p[v]=u);  //把v的父結點設爲u,然後遞歸
    }
}
主程序設置p[root]=-1(表示根結點的父結點不存在),然後調用dfs(root,-1)即可。初學者最容易犯的錯誤之一就是忘記判斷v是否和父結點相等

11.1.2表達式樹

二叉樹是表達式處理的常用工具

const int maxn=1000;
int lch[maxn],rch[maxn];
char op[maxn];
int nc=0;
int build_tree(char* s,int x,int y){
    int i,c1=-1,c2=-1,p=0;
    int u;
    if(y-x==1){   //僅一個字符,建立單獨結點
        u=++nc;
        lch[u]=rch[u]=0;
        op[u]=s[x];
        return u;
    }
    for(i=x;i<y;i++){
        switch(s[i]){
            case '(': p++; break;
            case ')': p--; break;
            case '+': case '-': if(!p) c1=i; break;
            case '*': case '/': if(!p) c2=i; break;
        }
    }
    if(c1<0) c1=c2;  //找不到括號外的加減法,就要乘除號
    if(c1<0) return build_tree(s,x+1,y-1);  //整個表達式被一對括號括起來
    u=++nc;
    lch[u]=build_tree(s,x,c1);
    rch[u]=build_tree(s,c1+1,y);
    op[u]=s[c1];
    return u;
}




發佈了38 篇原創文章 · 獲贊 2 · 訪問量 8029
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章