1. 程式人生 > >數據結構:靜態鏈表實現樹的同構

數據結構:靜態鏈表實現樹的同構

phi truct 判斷 fin 給定 lib 其中 鏈表實現 不同的

寫在最前面

按照課程講解的思路來寫,邏輯關系能夠理解清楚了,但是實際運行起來實在是有問題,雖然在PTA上能夠通過。但是我自己看不出問題來,並且,看了一遍又一遍仍然看不出來!(可能自己太笨。。)這就說明有著很嚴肅的問題!
所以,與其這樣糾結,不如按照自己理解的思路來寫一遍

補充一下題目要求

給定兩棵樹T1和T2。如果T1可以通過若幹次左右孩子互換就變成T2,則我們稱兩棵樹是“同構”的。例如圖1給出的兩棵樹就是同構的,因為我們把其中一棵樹的結點A、B、G的左右孩子互換後,就得到另外一棵樹。而圖2就不是同構的。

現給定兩棵樹,請你判斷它們是否是同構的。
輸入格式:
輸入給出2棵二叉樹樹的信息。對於每棵樹,首先在一行中給出一個非負整數N (≤10),即該樹的結點數(此時假設結點從0到N?1編號);隨後N行,第i行對應編號第i個結點,給出該結點中存儲的1個英文大寫字母、其左孩子結點的編號、右孩子結點的編號。如果孩子結點為空,則在相應位置上給出“-”。給出的數據間用一個空格分隔。註意:題目保證每個結點中存儲的字母是不同的。

輸出格式:
如果兩棵樹是同構的,輸出“Yes”,否則輸出“No”。

輸入樣例1(對應圖1):
8
A 1 2
B 3 4
C 5 -
D - -
E 6 -
G 7 -
F - -
H - -
8
G - 4
B 7 6
F - -
A 5 1
H - -
C 0 -
D - -
E 2 -
輸出樣例1:
Yes
輸入樣例2(對應圖2):
8
B 5 7
F - -
A 0 3
C 6 -
H - -
D - -
G 4 -
E 1 -
8
D 6 -
B 5 -
E - -
H - -
C 0 2
G - 3
F - -
A 1 4
輸出樣例2:
No

課程講解的思路

#include <cstdio>
#include <cstdlib>

//按題目的意思,存儲樹的是靜態鏈表
//即建一個結構,裏面三個變量char型結點字母,int型的左右孩子的位置

#define MaxTree 10 //題目的意思:最多十個結點
#define ElementType char
#define Tree int
#define Null -1

Tree BuildTree(struct TreeNode T[]);
int Isomorphic(Tree R1, Tree R2);

//建一個二叉樹的結構,並用數組的元素指向該結構
struct TreeNode
{
        ElementType Element;
        Tree Left;
        Tree Right;
}T1[MaxTree], T2[MaxTree];
//這樣就可以直接按題目要求進行逐行讀入了

//程序的整體框架
int main()
{
    Tree R1, R2;

    R1 = BuildTree(T1);
    //printf("%d\n", R1);
    R2 = BuildTree(T2);
    //printf("%d\n", R2);
    if (Isomorphic(R1, R2)) // 返回1說明同構,返回0說明不同構
        printf("Yes\n");
    else
        printf("No\n");

    return 0;

}

//建二叉樹
//1、將結點、左右孩子的位置讀入數組結構
//2、通過遍歷數組,找出頭結點
//沒有其他結點指向的就是頭結點,所以可以用一個標誌

Tree BuildTree(struct TreeNode T[])
{
    int N;
    int Isnode[MaxTree] = {0};
    char cl, cr; //因為有'-'存在,所以先用char型變量暫存,然後再放到結構裏
    scanf("%d\n", &N);
    if (N) {
        for (int i = 0; i < N; i++) {
            scanf("%c %c %c\n", &T[i].Element, &cl, &cr); //'-'在結構裏用-1表示
            if (cl != '-') {
                T[i].Left = cl - '0'; //在這裏可以同時加入對於根結點的判斷
                Isnode[T[i].Left] = 1;
            }
            else
                T[i].Left = Null;
            if (cr != '-') {
                T[i].Right = cr - '0';
                Isnode[T[i].Right] = 1;
            }
            else
                T[i].Right = Null;
        }
        //最後遍歷一遍結構數組,Isnode為0的就是頭結點
        for (int m = 0; m < N; m++) {
            if (!Isnode[m])
                return m;
        }
    }
    return Null;
}

//下面來判斷是否為同構
//都為空樹,直接返回1;一個空一個不空,直接返回0
//都不空:結點不同,直接0;結點相同,再看子樹
//左子樹同不存在,就遞歸調用右子樹
//左子樹存在,看是否相等,不相等就交換左右子樹,再遞歸調用
int Isomorphic(Tree R1, Tree R2)
{
    if ((R1 == Null) && (R2 == Null))
        return 1;
    if (((R1 == Null) && (R2 != Null)) || ((R1 != Null) && (R2 == Null)))
        return 0;
    if (T1[R1].Element != T2[R2].Element)
        return 0;
    if ((T1[R1].Left == Null) &&(T2[R2].Left) == Null)
        return Isomorphic(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 (Isomorphic(T1[R1].Left, T2[R2].Left) && Isomorphic(T1[R1].Right, T2[R2].Right));
    else
        return (Isomorphic(T1[R1].Left, T2[R2].Right) && Isomorphic(T1[R1].Right, T2[R2].Left));

}

自己理解的思路

#include <cstdio>
#include <cstdlib>

#define MaxTree 10
#define Null -1

struct TreeNode
{
    char Element;
    int Left;
    int Right;
}T1[MaxTree], T2[MaxTree];

int MadeTree (struct TreeNode T[]);
int Isomorphic(int R1, int R2);

int main()
{
    int R1, R2;

    R1 = MadeTree(T1);
    R2 = MadeTree(T2);
    if (Isomorphic(R1, R2))
        printf("Yes\n");
    else
        printf("No\n");

    return 0;
}

int MadeTree(struct TreeNode T[])
{
    int N;
    scanf("%d\n", &N);

    if (!N)
        return Null;
    else {
        char l,r;
        int Root[MaxTree] = {0};
        for (int i = 0; i < N; i++) {
            scanf("%c %c %c\n", &T[i].Element, &l, &r);
            if (l != '-') {
                T[i].Left = l - '0';
                Root[T[i].Left] = 1;
            }
            else
                T[i].Left = Null;
            if (r != '-') {
                T[i].Right = r - '0';
                Root[T[i].Right] = 1;
            }
            else
                T[i].Right = Null;
        }
        for (int m = 0; m < N; m++) {
            if (!Root[m])
                return m;
        }
    }
    return Null;
}

int Isomorphic(int R1, int R2)
{
    if ((R1 == Null) && (R2 == Null))
        return 1;
    if (((R1 == Null) && (R2 != Null)) || ((R1 != Null) && (R2 == Null)))
        return 0;
    if (T1[R1].Element != T2[R2].Element)
        return 0;
    if ((T1[R1].Left == Null) && (T2[R2].Left == Null))
        return Isomorphic(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 (Isomorphic(T1[R1].Left, T2[R2].Left) &&
        Isomorphic(T1[R1].Right, T2[R2].Right));
    else
        return (Isomorphic(T1[R1].Left, T2[R2].Right) &&
        Isomorphic(T1[R1].Right, T2[R2].Left));
}

但是這樣寫,好像並沒有什麽本質的區別,和照抄沒啥兩樣……
然後本地運行還是有問題:不是正常的回車結束。

暫時還沒想明白是啥問題,應該是輸入輸出有關。

數據結構:靜態鏈表實現樹的同構