C語言二叉樹的創建、(先中后序)遍歷以及存在的問題


 1 #include<stdlib.h>
 2 #include<stdio.h>
 3 
 4 #define True 1
 5 #define False 0
 6 
 7 typedef char TElemType;
 8 typedef struct TNode {
 9     TElemType data;
10     struct    TNode *lchild, *rchild;
11 }TNode,*BinTree;
12 
13 int CreateBinTree(BinTree T)
14 {
15     TElemType ch;
16     scanf("%c",&ch);
17     if (ch == '#')
18         T = NULL;
19     else 
20     {
21         T = (TNode *)malloc(sizeof(TNode));
22         T->data = ch;
23         CreateBinTree(T->lchild);//創建左子樹
24         CreateBinTree(T->rchild);//創建右子樹
25     }
26     return 0;
27 }
28 
29 void PreOrderTraverse(BinTree T)     //先序遍歷
30 {
31     if (T!=NULL)
32     {
33         //        Visit(T->data);
34         printf("%c", T->data);
35         PreOrderTraverse(T->lchild);
36         PreOrderTraverse(T->rchild);
37     }
38 }
39 
40 void InOrderTraverse(BinTree T)      //中序遍歷
41 {
42     if (T != NULL)
43     {
44         InOrderTraverse(T->lchild);
45 //        Visit(T->data);
46         printf("%c", T->data);
47         InOrderTraverse(T->rchild);
48     }
49 }
50 
51 void PostOrderTraverse(BinTree T)    //后序遍歷
52 {
53     if (T != NULL)
54     {
55         PostOrderTraverse(T->lchild);
56         PostOrderTraverse(T->rchild);
57         printf("%c", T->data);
58     }
59 }
60 
61 
62 
63 int main()
64 {
65     BinTree a;
66     CreateBinTree(a);
67     PreOrderTraverse(a);
68     return 0;
69 }

滿懷憧憬寫完了代碼,讓我絕望的是,一運行就出現了問題:能夠輸入樹的信息,但是無法輸出,因此,我認為是二叉樹的遍歷函數出了問題,但是又無法單單從代碼看出

於是,我就寫了如下代碼,自行構建了一個二叉樹:

 1         BinTree a=NULL;
 2     BinTree b = NULL;
 3     BinTree c = NULL;
 4     a = (BinTree)malloc(sizeof(TNode));
 5     b = (BinTree)malloc(sizeof(TNode));
 6     c = (BinTree)malloc(sizeof(TNode));
 7     a->rchild = b;
 8     b->lchild = c;
 9     a->lchild = NULL;
10     b->rchild = NULL;
11     c->lchild = NULL;
12     c->rchild = NULL;
13     a->data = 'A';
14     b->data = 'B';
15     c->data = 'C';
16 
17     PreOrderTraverse(a);
18     printf("\n");
19     InOrderTraverse(a);
20     printf("\n");
21     PostOrderTraverse(a);        

結果卻成功地輸出了自行構造的二叉樹。由此可見我的遍歷函數並沒有問題,因此必定是二叉樹的create函數出了問題,但是為何我卻能夠輸入呢?

我在網上查了查相關的代碼,發現一個采用引用值傳遞的算法,將create函數修改如下:

int CreateBinTree(BinTree &T)  //引用值傳遞
{
    TElemType ch;
    scanf_s("%c",&ch,sizeof(ch));
    if (ch == '#')
        T = NULL;
    else 
    {
        T = (TNode *)malloc(sizeof(TNode));
        T->data = ch;
        CreateBinTree(T->lchild);//構造左子樹
        CreateBinTree(T->rchild);//構造右子樹
    }
    return 0;
}

嘗試着運行,成功了!

???這時我感到很奇怪。

為啥之前的不行呢?

這時,又看到使用BinTree作返回值的算法,修改后如下:

 1 BinTree creatBTree()   //以BinTree為返回值
 2 {
 3     TElemType ch;
 4     BinTree T;
 5     scanf_s("%c", &ch, sizeof(ch));
 6     if (ch == '#')
 7         T = NULL;
 8     else
 9     {
10         T = (TNode *)malloc(sizeof(TNode));
11         T->data = ch;
12         T->lchild=creatBTree();//構造左子樹
13         T->rchild=creatBTree();//構造右子樹
14     }
15     return T;
16 }

毫無疑問,同樣能成功實現需求。

那么問題來了?為什么之前的不行呢?

因為我之前用的int CreateBinTree(BinTree T);是單純的值傳遞,就像swap(a,b)無法交換兩值那樣,雖然的確通過動態內存分配和鏈表構造了一個二叉樹,但是在主函數中定義的a的值並沒有任何改變,因此在遍歷a時會毫無反應。

而引用作函數參數傳遞,能夠直接對a的值進行改變,以a為根節點構建二叉樹。

以BinTree為返回值就更不用說了,直接將新構建的二叉樹賦值給a。

為了嘗試地址為參數傳遞是否可行,寫了如下函數

int CreateRoot(BinTree *T),細節如下:

1 int CreateBinTree(BinTree *T)
2 {
3     TElemType ch;
4     scanf("%c",&ch);
5     *T=(BinTree)malloc(sizeof(TNode));
6     (*T)->data=ch;
7     (*T)->lchild=NULL;
8     (*T)->rchild=NULL;//設置左右孩子為NULL,以防陷入無限循環
9  } 

能夠成功插入根節點!

看到這里,便可以輕松完成遞歸構造函數:

 1 int CreateBinTree(BinTree *T)
 2 {
 3     TElemType ch;
 4     scanf("%c",&ch);
 5     if (ch == '#')
 6         *T = NULL;  //若寫成T=NULL ,可能會陷入無限循環
 7     else 
 8     {
 9         *T = (BinTree)malloc(sizeof(TNode));
10         (*T)->data = ch;
11         CreateBinTree(&(*T)->lchild);//left child
12         CreateBinTree(&(*T)->rchild);//right child
13     }
14     return 0;
15 }
16 //在本函數中最需要注意的就是,所有地方都必須以(*T)的形式出現

寫完這個隨筆,對二叉樹的理解增進了不少,今天的學習給我帶來了不小的回報,繼續努力~


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM