1. 程式人生 > >第五章題解

第五章題解

二叉鏈表 就是 一個 eno 方便 root color turn int

第五章 樹和二叉樹

本章我們重點學習了樹和二叉樹的定義、二叉樹的性質、存儲結構、二叉樹的先中後序遍歷。簡略的學習了樹和森林的存儲結構、遍歷,大致講解了哈夫曼樹的基本感念。在學習過程中,建樹和二叉樹的遍歷對我來講比較難。建樹可以用順序存儲也可以用二叉鏈表存儲,二叉樹的遍歷可以用遞歸實現也可以用非遞歸實現。下面主要講講我在PTA做題過程的一些感想和思路。

List Leaves

這道題的思路很簡單: 構造二叉樹的結點結構體、建立二叉樹、利用隊列輸出葉子結點

第一步 構造二叉樹的結點結構體

由於這道題的數據N只在10以內,所以我用了順序存儲結構。

1 typedef struct{ //定義二叉樹的結點結構 
2 int Left; 3 int Right; 4 }BiTreenode;

第二步 建立二叉樹

這裏要註意的問題有:

1.輸入的是char類型數據,因此為了標號方便要將其ASCII碼減去0的ASCII碼

2. 要定義一個數組root(bool類型或者int類型),以利於標記這個結點的子樹是否是根結點

int Buildtree(BiTreenode T[]){ 
    
    bool root[10]={false};
    int n,i;
    char x,y;
    cin>>n;
    
    for
(i=0;i<n;i++){ cin>>x>>y; if(x!=-){//判斷左兒子是否為空,若不為空則左二子不為根結點,賦值為true T[i].Left=x-0; root[T[i].Left]=true; } else T[i].Left=-1; if(y!=-){ //判斷右兒子是否為空,若不為空則右兒子不為根結點,賦值為true T[i].Right=y-
0; root[T[i].Right]=true; } else T[i].Right=-1; } for (int i=0; i<n; i++){//尋找根結點 ,當 root[]為-1時該式子成立,返回i的下標,即根節點的下標 if(!root[i]) return i; } }

第三步 利用隊列輸出葉子結點

利用隊列的好處是先進先出,而且在push一個數據之後就將它pop出來直接對它的左右孩子進行比較,非常方便

void OrderTree(BiTreenode T[],int x){//利用隊列輸出葉子結點 
    
    queue<int> q;
    int k;
    q.push(x);//將根節點入隊 
    while(!q.empty()){//當隊列不為空的時候,繼續執行循環 
        
        int tmp=q.front();//訪問隊列的首結點,也就是將最早入隊的結點的下標賦值給tmp 
        
        if(T[tmp].Left!=-1) //若該節點的左兒子不為空,則將它壓入隊列中 
        q.push(T[tmp].Left);
        if(T[tmp].Right!=-1)//若該節點的右兒子不為空,則將它壓入隊列中 
        q.push(T[tmp].Right); 
        
        q.pop();   //彈出隊列中的第一個元素 
        if(T[tmp].Left==-1 && T[tmp].Right==-1){ //若該結點的左兒子和右兒子均為空,則該結點為葉子結點,輸出該葉子結點 
            cout<<tmp;
            if(!q.empty()) //若隊列不為空,則輸出的不是最後一個葉子結點,在輸出空格 
            cout<<" ";
        }    
            
    } 
}    

樹的同構

這道題的思路主要是:構造結點結構體、構造二叉樹、將兩棵二叉樹進行比較。

第一步 構造結點結構體

這道題我也是用了順序存儲結構,與上一道題不一樣的地方是,這道題需要輸入字符域element。

typedef struct Treenode{
    char element;
    int left;
    int right;
}Treenode;

第二步 構造二叉樹

與上一道題目大同小異,主要是這裏需要構造兩棵樹。

第三步 將兩棵二叉樹進行比較

這個步驟有些復雜,主要是在比較過程中要把邏輯思路搞清楚。

1. 兩棵樹都是空樹的情況

2. 其中一棵樹是空樹的情況下

3. 根節點都存在但數值不同

4. 左子樹不存在,則遞歸判斷右子樹

5. 左子樹同時不空則無需交換左右子樹,否則交換左右子樹

bool Comparetree(int R1,int R2){
    
    
    if( (R1==Null) && (R2==Null) )
        return true;//兩棵樹都為空,則同構 
        
    if( ((R1==Null) && (R2!=Null)) || ((R1!=Null) && (R2==Null)) )
        return false;//兩棵樹中有一棵為空,另外一棵樹不為空,則不同構
         
    if( T1[R1].element!=T2[R2].element ) 
        return false;//若兩棵樹都不為空,但樹根的值不相同,則不同構 
        
    if( (T1[R1].left==Null) && (T2[R2].left==Null) ) 
        return Comparetree( T1[R1].right,T2[R2].right );//兩棵樹都不為空,根的值相同。若左子樹都為空,則是否同構取決於右邊,遞歸調用右子樹的判別 
        
    if( ((T1[R1].left!=Null) && (T2[R2].left!=Null)) && ((T1[T1[R1].left].element)==(T2[T2[R2].left].element)) ) 
        return(Comparetree(T1[R1].left,T2[R2].left) && Comparetree(T1[R1].right,T2[R2].right));//左子樹是否同時不空,若同時不空則無需交換左右子樹 
        
    else return (Comparetree(T1[R1].left,T2[R2].right) && Comparetree(T1[R1].right,T2[R2].left));
};

目標總結:

完成了三分之二的題解,比上次進步一點。

下次目標:

完成所有題解。

第五章題解