數據結構——構造二叉樹的方法匯總(遞歸與迭代構造)


序言

一、根據前序序列構造

1.1 控制台遞歸構造

1.2 字符串遞歸構造

1.3 字符串迭代構造

二、根據前(后)序序列和中序序列構造

2.1 字符串遞歸構造

2.2 字符串迭代構造

三、總結

四、參考文獻

 

 

 

序言

  本篇文章將介紹二叉樹的常見構造方法,總體涵蓋控制台輸入字符串構造和根據字符串構造,兩者構造的區別是,前者構造序列需要從控制台輸入,后者構造序列可以通過現有字符串直接構造;並且通過遞歸與迭代兩種思路進行構造,我們將先通過遞歸進行構造,然后將遞歸轉化為迭代,如果不知道如何將遞歸轉化為迭代,請參看文章數據結構——遞歸與非遞歸

 

 

一、根據前序序列構造

  假設有如下一顆二叉樹:

 

 

   我們可以根據圖示二叉樹寫出他的前序序列為:ABDC。如果反過來,已知前序序列ABDC,我們能不能根據前序序列畫出二叉樹呢,答案是不能。我們可以將二叉樹稍微改造一下,用#代表空結點,改造結果如下所示:

 

 

 我們寫出改造后的二叉樹的前序序列:AB#D##C##。現在我們就可以根據改造后的二叉樹前序序列唯一地構造二叉樹了。

 

1.1 控制台遞歸構造

  控制台遞歸構造,就是將前序序列通過控制台輸入的方式逐一錄入,然后將錄入的前序序列通過遞歸進行構造。我們將二叉樹采用二叉鏈表的方式進行存儲,即結點包含三部分,數據域,左孩子和右孩子。如下圖所示:

 

 

 

給出二叉樹結點的定義,代碼如下:

1 /* 二叉樹結點 */
2 template <typename DataType>
3 struct BiNode
4 {
5     DataType data;
6     BiNode<DataType>* lChild;
7     BiNode<DataType>* rChild;
8 };

 

我們給出二叉樹的定義,代碼如下:

 1 template <typename DataType>
 2 class BiTree
 3 {
 4 public:
 5     BiTree() { root = create(); }  // 構造函數
 6     ~BiTree();   // 析構函數
 7 private:
 8     BiNode<DataType>* create();    // 控制台遞歸構造二叉樹
 9     BiNode<DataType>* root;        // 二叉樹根結點
10 };    

 

接下來我們實現控制台遞歸構造二叉樹的方法 BiNode<DataType>* create();代碼如下:

 1 template <typename DataType>
 2 BiNode<DataType>* BiTree<DataType>::create()
 3 {
 4     BiNode<DataType>* bt;
 5     char ch;
 6     std::cin >> ch;  // 控制台錄入
 7     if ('#' == ch)
 8     {
 9         bt = nullptr;
10     }
11     else
12     {
13         bt = new BiNode<DataType>;
14         bt->data = ch;
15         bt->lChild = create();    // 遞歸構造左子樹
16         bt->rChild = create();    // 遞歸構造右子樹
17     }
18     return bt;
19 }

 

 

1.2 字符串遞歸構造

字符串遞歸構造,就是傳入一個字符串前序序列作為參數,然后進行遞歸構造二叉樹。我們依舊采用二叉鏈表的方式,本文二叉樹的存儲結構我們一直采用二叉鏈表的方式。

修改二叉樹的定義如下:

 1 template <typename DataType>
 2 class BiTree
 3 {
 4 public:
 5     BiTree() { root = create(); }
 6     BiTree(std::string tree, int index) { root = create(tree, index); }
 7     ~BiTree();
 8 private:
 9     BiNode<DataType>* create();  
10     BiNode<DataType>* create(std::string tree, int& index);
11     BiNode<DataType>* root;  // 二叉樹根節點
12 };  

 

接下來我們實現字符串遞歸構造二叉樹的方法 BiNode<DataType>* create(std::string tree, int& index);代碼如下:

 1 template <typename DataType>
 2 BiNode<DataType>* BiTree<DataType>::create(std::string tree, int& index)
 3 {
 4     BiNode<DataType>* bt;
 5     char ch;
 6     ch = tree[index];
 7     if ('#' == ch)
 8     {
 9         bt = nullptr;
10     }
11     else
12     {
13         bt = new BiNode<DataType>;
14         bt->data = ch;
15         bt->lChild = create(tree, ++index);
16         bt->rChild = create(tree, ++index);
17     }
18     return bt;
19 }

 

 

1.3 字符串迭代構造

我們將字符串遞歸構造改寫成字符串迭代構造。

修改二叉樹定義, 代碼如下:

 1 template <typename DataType>
 2 class BiTree
 3 {
 4 public:
 5     BiTree() { root = create(); }
 6     BiTree(std::string tree, int index) { root = create(tree, index); }
 7     BiTree(std::string tree) { createIter(tree, 0); }
 8     ~BiTree();
 9 private:
10     BiNode<DataType>* create();
11     BiNode<DataType>* create(std::string tree, int& index);
12     void createIter(std::string tree, int index);
13     BiNode<DataType>* root;
14 };

 

接下來我們實現字符串迭代構造二叉樹的方法 void createIter(std::string tree, int index);代碼如下:

 1 template <typename DataType>
 2 void BiTree<DataType>::createIter(std::string tree, int index)
 3 {
 4     root = new BiNode<DataType>;
 5     root->data = '*';
 6     BiNode<DataType>* bt = root;
 7     BiNode<DataType>* stack[20];
 8     int top = -1;    // 棧頂指針
 9 
10     while ('#' != tree[index] || -1 != top)
11     {
12         while ('#' != tree[index])
13         {
14             if (bt == nullptr || '*' != bt->data)
15             {
16                 bt = new BiNode<DataType>;
17             }
18             bt->data = tree[index];
19             stack[++top] = bt;  // 保存現場
20             ++index;            // 修改局部變量
21             if ('#' == tree[index])
22             {
23                 bt->lChild = nullptr;
24             }
25             else {
26                 bt->lChild = new BiNode<DataType>;
27                 bt = bt->lChild;
28                 bt->data = '*';
29             }
30         }
31 
32         bt = stack[top--];        // 恢復現場
33         ++index;                // 修改局部變量
34         if ('#' != tree[index])
35         {
36             bt->rChild = new BiNode<DataType>;
37             bt = bt->rChild;
38             bt->data = '*';
39         }
40         else
41         {
42             bt->rChild = nullptr;
43         }
44     }
45 }

 

 

二、根據前(后)序序列和中序序列構造

  我們可以根據前序序列和中序序列唯一地確定二叉樹,確定方法請參考文獻2

2.1 字符串遞歸構造

修改二叉樹定義, 代碼如下:

 1 template <typename DataType>
 2 class BiTree
 3 {
 4 public:
 5     BiTree() { root = create(); }
 6     BiTree(std::string tree, int index) { root = create(tree, index); }
 7     BiTree(std::string tree) { createIter(tree, 0); }
 8     BiTree(std::string preOrder, std::string inOrder, int n) { root = create(preOrder, inOrder, n); }
 9     ~BiTree();
10 private:
11     BiNode<DataType>* create();
12     BiNode<DataType>* create(std::string tree, int& index);
13     void createIter(std::string tree, int index);
14     BiNode<DataType>* create(std::string preOrder, std::string inOrder, int length);
15 
16     BiNode<DataType>* root;
17 };

 

接下來我們實現字符串遞歸構造二叉樹的方法BiNode<DataType>* create(std::string preOrder, std::string inOrder, int length);代碼如下:

 1 template <typename DataType>
 2 BiNode<DataType>* BiTree<DataType>::create(std::string preOrder, std::string inOrder, int n)
 3 {
 4     BiNode<DataType>* bt;
 5 
 6     if (0 == n)
 7     {
 8         bt = nullptr;
 9     }
10     else
11     {
12         bt = new BiNode<DataType>;
13         bt->data = preOrder[0];
14         int n = inOrder.find(preOrder[0], 0);
15         std::string lPreOrder = preOrder.substr(1, n);
16         std::string lInOrder = inOrder.substr(0, n);
17         std::string rPreOrder = preOrder.substr(n + 1, preOrder.size() - 1 - n);
18         std::string rInOrder = inOrder.substr(n + 1, inOrder.size() - 1 - n);
19         bt->lChild = create(lPreOrder, lInOrder, n);
20         bt->rChild = create(rPreOrder, rInOrder, inOrder.size() - 1 - n);
21     }
22 
23     return bt;
24 }

 

 

2.2 字符串迭代構造

 

 

三、總結

 

 

四、參考文獻

1、[二叉樹地建立方法總結](https://www.cnblogs.com/llhthinker/p/4906631.html)

2、數據結構——從概念到C++實現(第三版) 王紅梅、王慧、王新穎 編著

 


免責聲明!

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



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