zoukankan      html  css  js  c++  java
  • 二叉树基础--创建、遍历方法(前序/中序/后序/层序、递归/非递归)

      【作者:Dillonn  出处: http://www.cnblogs.com/Dillonn/p/4226929.html  欢迎转载,请务必保留本行】

      二叉树的创建及遍历是很多二叉树问题的基础,递归遍历逻辑清晰,代码简约漂亮,然则效率低下(所有递归方案的通病,非不得已不用递归);

      非递归遍历高效,却不是能信手写出来的,特别是后续非递归遍历,相信很多资深码工也有这样的经历:

      5年前学习了二叉树的非递归遍历,一个月前复习了并达到能熟练写出的程度,在不参考任何资料的情况下,今天却怎样也写不出来。

      如果你也有过这种经历,恭喜,这说明你是一个正常人类……

      另一方面市面上有些国人写的教材,各种语法、逻辑错误层出不起,不知祸害了多少未来的码工,深感痛心。

      印象比较深刻的有清华大学出版社出版的《数据结果(C++版)》  王红梅、胡明、王涛编著

      如书中第163页后序非递归遍历方法,短短不到30行代码各种语法、逻辑错误如下:  

     1 template <typename T>
     2 void BiTree::PostOrder(BiNode<T> * root)//错误一:正确的写法为void BiTree<T>::PostOrder(BiNode<T> * root)
     3 {
     4     top = -1;
     5     //错误二:应该在这里定义下文用到的栈s(书中说这是具体的代码,不是伪代码)。
     6     wihle(root != NULL || top != -1)
     7     {
     8         while(root != NULL)
     9         {
    10             top++;
    11             s[top].ptr = root;
    12             s[top].flag = 1;
    13             root = root -> lchild;
    14         }
    15         while(top != -1 && s[top].flag ==2)
    16         {
    17             root = s[top--].ptr;
    18             cout << root->data;
    19         }
    20         if(top != -1)
    21         {
    22             s[top].flag = 2;
    23             root = s[top].ptr->rchild;
    24         }
    25         //错误三:致命逻辑错误,栈空时,遍历结束,退出外层循环或函数返回,否则将进入死循环,应该加上如下一行代码。
    26         else break;//书中没有这一行
    27     }
    28 }

      下面咱们来实现一个二叉树Class,在Class中实现以下方法:

      1.创建一颗二叉树;

          2.销毁一颗二叉树;

      3.递归前序遍历方法;

      4.非递归前序遍历方法;

      5.递归中序遍历方法;

      6.非递归中序遍历方法;

      7.递归后序遍历方法;

      8.非递归后序遍历方法;

      9.层序遍历方法(这个应该就没有递归的方法)。

       要点:非递归遍历用栈辅助(深度优先),层序遍历用队列辅助(广度优先)。  

      二叉树节点定义:   

    1 template <typename T>
    2 struct BiNode
    3 {
    4     T data;
    5     BiNode<T> *pLeft;
    6     BiNode<T> *pRight;
    7 };

      

      二叉树Class定义: 

      要点:1.数据成员申明为私有;

         2. 公有成员方法如PreOrder1()为对外接口,调用私有成员方法PreOrderRecursive(BiNode<T> * root)实现其具体功能。

     1 template <typename T>
     2 class BiTree
     3 {
     4     public:
     5         BiTree();
     6         ~BiTree();
     7         void PreOrder1();//递归
     8         void PreOrder2();//非递归
     9         void InOrder1();//递归
    10         void InOrder2();//非递归
    11         void PostOrder1();//递归
    12         void PostOrder2();//非递归
    13         void LevelOrder();
    14     private:
    15         BiNode<T> * root;
    16         void CreateBiTree(BiNode<T> * &root);
    17         void ReleaseBiTree(BiNode<T> * root);
    18         
    19         void PreOrderRecursive(BiNode<T> * root);
    20         void PreOrderNonRecursive(BiNode<T> * root);
    21         
    22         void InOrderRecursive(BiNode<T> * root);
    23         void InOrderNonRecursive(BiNode<T> * root);
    24         
    25         void PostOrderRecursive(BiNode<T> * root);
    26         void PostOrderNonRecursive(BiNode<T> * root);
    27         
    28         void LevelOrder(BiNode<T> * root);
    29 };

      

      创建二叉树:

     1 template <typename T>
     2 void BiTree<T>::CreateBiTree( BiNode<T> * &root)// 根据前序遍历次序创建二叉树
     3 {
     4     T data;
     5     cin>>data;
     6     if(data == INVALID)
     7     {
     8         root = NULL;
     9     }
    10     else
    11     {
    12         root = new BiNode<T>;
    13         root->data = data;
    14         CreateBiTree(root->pLeft);
    15         CreateBiTree(root->pRight);
    16     }
    17 }
    18 
    19 
    20 template <typename T>
    21 BiTree<T>::BiTree():root(NULL)
    22 {
    23     CreateBiTree(root);
    24 }

      销毁二叉树:  

     1 template <typename T>
     2 void BiTree<T>::ReleaseBiTree(BiNode<T> * root)
     3 {
     4     if(root != NULL)
     5     {
     6         ReleaseBiTree(root->pLeft);
     7         ReleaseBiTree(root->pRight);
     8         delete root;
     9     }
    10 }
    11 
    12 
    13 template <typename T>
    14 BiTree<T>::~BiTree()
    15 {
    16     ReleaseBiTree(root);
    17 }

      前序递归遍历:  

     1 template <typename T>
     2 void BiTree<T>::PreOrderRecursive(BiNode<T> * root)
     3 {
     4     if(root != NULL)
     5     {
     6         cout<<root->data<<" ";
     7         PreOrderRecursive(root->pLeft);
     8         PreOrderRecursive(root->pRight);
     9     }
    10 }
    11 
    12 
    13 
    14 template <typename T>
    15 void BiTree<T>::PreOrder1()
    16 {
    17     PreOrderRecursive(root);
    18     cout<<endl;
    19 }

      

      中序递归遍历:

     1 template <typename T>
     2 void BiTree<T>::InOrderRecursive(BiNode<T> * root)
     3 {
     4     if(root != NULL)
     5     {
     6         InOrderRecursive(root->pLeft);
     7         cout<<root->data<<" ";
     8         InOrderRecursive(root->pRight);
     9     }
    10 }
    11 
    12 
    13 template <typename T>
    14 void BiTree<T>::InOrder1()
    15 {
    16     InOrderRecursive(root);
    17     cout<<endl;
    18 }

      

      后序递归遍历:  

     1 template <typename T>
     2 void BiTree<T>::PostOrderRecursive(BiNode<T> * root)
     3 {
     4     if(root != NULL)
     5     {
     6                 PostOrderRecursive(root->pLeft);
     7                 PostOrderRecursive(root->pRight);
     8                 cout<<root->data<<" ";
     9     }
    10 }
    11 
    12 
    13 template <typename T>
    14 void BiTree<T>::PostOrder1()
    15 {
    16     PostOrderRecursive(root);
    17     cout<<endl;
    18 }

      

      层序遍历:  

     1 template <typename T>
     2 void BiTree<T>::LevelOrder(BiNode<T> * root)
     3 {    
     4     BiNode<T> * p;
     5     queue<BiNode<T> *> q;
     6     if(root == NULL) 
     7         return;
     8     q.push(root);
     9     while(!q.empty())
    10     {
    11         p = q.front();
    12         cout << p->data<<" ";
    13         q.pop();
    14         if(p->pLeft != NULL) q.push(p->pLeft);
    15         if(p->pRight != NULL) q.push(p->pRight);
    16     }
    17 }
    18 
    19 template <typename T>
    20 void BiTree<T>::LevelOrder()
    21 {
    22     LevelOrder(root);
    23     cout<<endl;
    24 }

      前序非递归遍历:

     1 template <typename T>
     2 void BiTree<T>:: PreOrderNonRecursive(BiNode<T> * root)
     3 {
     4     stack<BiNode<T> *> s;
     5     while(root != NULL || !s.empty())
     6     {
     7         while(root != NULL)
     8         {
     9             cout<<root->data<<" ";
    10             s.push(root);
    11             root = root->pLeft; 
    12         }
    13         if(!s.empty())
    14         {
    15             root = s.top();
    16             s.pop();
    17             root = root->pRight;
    18         }
    19     }
    20                     
    21 }
    22 
    23 
    24 
    25 
    26 template <typename T>
    27 void BiTree<T>::PreOrder2()
    28 {
    29     PreOrderNonRecursive(root);
    30     cout<<endl;
    31 }

      中序非递归遍历:  

     1 template <typename T>
     2 void BiTree<T>::InOrderNonRecursive(BiNode<T> * root)
     3 {
     4     stack<BiNode<T> *> s;
     5     while(root != NULL || !s.empty())
     6     {
     7         while(root != NULL)
     8         {
     9             s.push(root);
    10             root = root->pLeft; 
    11         }
    12         if(!s.empty())
    13         {
    14             root = s.top();
    15             s.pop();
    16             cout<<root->data<<" ";            
    17             root = root->pRight;
    18         }
    19     }
    20                     
    21 }
    22 
    23 
    24 
    25 template <typename T>
    26 void BiTree<T>::InOrder2()
    27 {
    28     InOrderNonRecursive(root);
    29     cout<<endl;
    30 }

      后序非递归遍历:

     1 template <typename T>
     2 void BiTree<T>::PostOrderNonRecursive(BiNode<T> * root)
     3 {
     4 
     5     stack<BiNode<T> *> s1;
     6     stack<int> s2;//s2辅助记录s1相应位置的元素的状态:s1、s2保持同步。
     7             
     8     while(root != NULL || !s1.empty())
     9     {
    10         while(root != NULL)
    11         {
    12             s1.push(root);
    13             s2.push(1);
    14             root = root->pLeft;
    15         }
    16         if(!s1.empty())
    17         {
    18             if(s2.top()==1)
    19             {
    20                 s2.pop();
    21                 s2.push(2);
    22                 root = s1.top()->pRight;
    23             }
    24             else
    25             {
    26                 root = s1.top();
    27                 s1.pop();
    28                 s2.pop();
    29                 cout<<root->data<<" ";
    30                 root = NULL;    
    31             }
    32         }
    33         
    34     }
    35             
    36 }
    37 
    38 
    39 
    40 template <typename T>
    41 void BiTree<T>::PostOrder2()
    42 {
    43     PostOrderNonRecursive(root);
    44     cout<<endl;
    45 }

      假定我们创建的二叉树形状如下:

     1 /*
     2 假定所创建的二叉树如下图所示
     3                                              A
     4                                            /   
     5                                           B     C
     6                                          /     /
     7                                         D   E  F
     8                                              
     9                                               G
    10 
    11 
    12 创建二叉树的文件:《BiTree.txt》内容如下:
    13 A B D # # E # G # # C  F # # #
    14 
    15 */
    16 const char *preorder  = "A B D E G C F";
    17 const char *inorder   = "D B E G A F C";
    18 const char *postorder = "D G E B F C A";
    19 const char *levelorder= "A B C D E F G";

      

      main函数:

     1 int main()
     2 {
     3     ifstream fin("BiTree.txt");// 输入文件
     4     ofstream fout("out.txt");  //输出文件
     5 
     6     streambuf *cinbackup;
     7     streambuf *coutbackup;
     8 
     9     cinbackup= cin.rdbuf(fin.rdbuf());  //用 rdbuf() 重新定向
    10     coutbackup= cout.rdbuf(fout.rdbuf());  //用 rdbuf() 重新定向
    11 
    12     BiTree<char> *pbitree = new BiTree<char>;//创建一颗二叉树
    13     
    14     cout << "*preorder =   " << preorder << endl;
    15     cout << " PreOrder1(): ";
    16     pbitree->PreOrder1();
    17     cout << " PreOrder2(): ";
    18     pbitree->PreOrder2();
    19     cout<<endl;
    20     
    21     cout << "*inorder =   " << inorder << endl;
    22     cout << " inorder1(): ";
    23     pbitree->InOrder1();
    24     cout << " InOrder2(): ";
    25     pbitree->InOrder2();
    26     cout<<endl;
    27     
    28     cout << "*postorder =   " << postorder << endl;
    29     cout << " PostOrder1(): ";
    30     pbitree->PostOrder1();    
    31     cout << " PostOrder2(): ";
    32     pbitree->PostOrder2();
    33     cout<<endl;
    34     
    35     cout << "*levelorder =  " << levelorder << endl;
    36     cout << " LevelOrder(): ";
    37     pbitree->LevelOrder();
    38 
    39     delete pbitree;
    40     cin.rdbuf(cinbackup);  // 取消,恢复键盘输入
    41     cout.rdbuf(coutbackup);  //取消,恢复屏幕输出
    42     return 0;
    43 }

      

      MVS2005上的运行结果如下图:

      完整的代码: 

      1 #include <iostream>
      2 #include <fstream>
      3 #include <stack>
      4 #include <queue>
      5 
      6 using namespace std;
      7 
      8 
      9 /*
     10 假定所创建的二叉树如下图所示
     11                                              A
     12                                            /   
     13                                           B     C
     14                                          /     /
     15                                         D   E  F
     16                                              
     17                                               G
     18 
     19 
     20 创建二叉树的文件:《BiTree.txt》内容如下:
     21 A B D # # E # G # # C  F # # #
     22 
     23 */
     24 const char *preorder  = "A B D E G C F";
     25 const char *inorder   = "D B E G A F C";
     26 const char *postorder = "D G E B F C A";
     27 const char *levelorder= "A B C D E F G";
     28 
     29 const char INVALID = '#';//INVALID在CreateBiTree()函数中表示空节点,类型适配 template <typename T>
     30 
     31 template <typename T>
     32 struct BiNode
     33 {
     34     T data;
     35     BiNode<T> *pLeft;
     36     BiNode<T> *pRight;
     37 //    BiNode():data(0){cout<<"BiNode Constructor"<<endl;};
     38 //    ~BiNode(){cout<<"BiNode Destructor"<<endl;};
     39 };
     40 
     41 template <typename T>
     42 class BiTree
     43 {
     44     public:
     45         BiTree();
     46         ~BiTree();
     47         void PreOrder1();//递归
     48         void PreOrder2();//非递归
     49         void InOrder1();//递归
     50         void InOrder2();//非递归
     51         void PostOrder1();//递归
     52         void PostOrder2();//非递归
     53         void LevelOrder();
     54     private:
     55         BiNode<T> * root;
     56         void CreateBiTree(BiNode<T> * &root);
     57         void ReleaseBiTree(BiNode<T> * root);
     58         
     59         void PreOrderRecursive(BiNode<T> * root);
     60         void PreOrderNonRecursive(BiNode<T> * root);
     61         
     62         void InOrderRecursive(BiNode<T> * root);
     63         void InOrderNonRecursive(BiNode<T> * root);
     64         
     65         void PostOrderRecursive(BiNode<T> * root);
     66         void PostOrderNonRecursive(BiNode<T> * root);
     67         
     68         void LevelOrder(BiNode<T> * root);
     69 };
     70 
     71 
     72 template <typename T>
     73 void BiTree<T>::CreateBiTree( BiNode<T> * &root)// 根据前序遍历次序创建二叉树
     74 {
     75     T data;
     76     cin>>data;
     77     if(data == INVALID)
     78     {
     79         root = NULL;
     80     }
     81     else
     82     {
     83         root = new BiNode<T>;
     84         root->data = data;
     85         CreateBiTree(root->pLeft);
     86         CreateBiTree(root->pRight);
     87     }
     88 }
     89 
     90 
     91 template <typename T>
     92 void BiTree<T>::ReleaseBiTree(BiNode<T> * root)
     93 {
     94     if(root != NULL)
     95     {
     96         ReleaseBiTree(root->pLeft);
     97         ReleaseBiTree(root->pRight);
     98         delete root;
     99     }
    100 }
    101 
    102 
    103 template <typename T>
    104 BiTree<T>::BiTree():root(NULL)
    105 {
    106     CreateBiTree(root);
    107 }
    108 
    109 
    110 template <typename T>
    111 BiTree<T>::~BiTree()
    112 {
    113     ReleaseBiTree(root);
    114 }
    115 
    116 
    117 template <typename T>
    118 void BiTree<T>::PreOrderRecursive(BiNode<T> * root)
    119 {
    120     if(root != NULL)
    121     {
    122         cout<<root->data<<" ";
    123         PreOrderRecursive(root->pLeft);
    124         PreOrderRecursive(root->pRight);
    125     }
    126 }
    127 
    128 
    129 template <typename T>
    130 void BiTree<T>:: PreOrderNonRecursive(BiNode<T> * root)
    131 {
    132     stack<BiNode<T> *> s;
    133     while(root != NULL || !s.empty())
    134     {
    135         while(root != NULL)
    136         {
    137             cout<<root->data<<" ";
    138             s.push(root);
    139             root = root->pLeft; 
    140         }
    141         if(!s.empty())
    142         {
    143             root = s.top();
    144             s.pop();
    145             root = root->pRight;
    146         }
    147     }
    148                     
    149 }
    150 
    151 
    152 template <typename T>
    153 void BiTree<T>::PreOrder1()
    154 {
    155     PreOrderRecursive(root);
    156     cout<<endl;
    157 }
    158 
    159 
    160 template <typename T>
    161 void BiTree<T>::PreOrder2()
    162 {
    163     PreOrderNonRecursive(root);
    164     cout<<endl;
    165 }
    166 
    167 
    168 template <typename T>
    169 void BiTree<T>::InOrderRecursive(BiNode<T> * root)
    170 {
    171     if(root != NULL)
    172     {
    173         InOrderRecursive(root->pLeft);
    174         cout<<root->data<<" ";
    175         InOrderRecursive(root->pRight);
    176     }
    177 }
    178 
    179 
    180 template <typename T>
    181 void BiTree<T>::InOrderNonRecursive(BiNode<T> * root)
    182 {
    183     stack<BiNode<T> *> s;
    184     while(root != NULL || !s.empty())
    185     {
    186         while(root != NULL)
    187         {
    188             s.push(root);
    189             root = root->pLeft; 
    190         }
    191         if(!s.empty())
    192         {
    193             root = s.top();
    194             s.pop();
    195             cout<<root->data<<" ";            
    196             root = root->pRight;
    197         }
    198     }
    199                     
    200 }
    201 
    202 
    203 template <typename T>
    204 void BiTree<T>::InOrder1()
    205 {
    206     InOrderRecursive(root);
    207     cout<<endl;
    208 }
    209 
    210 
    211 template <typename T>
    212 void BiTree<T>::InOrder2()
    213 {
    214     InOrderNonRecursive(root);
    215     cout<<endl;
    216 }
    217 
    218 
    219 template <typename T>
    220 void BiTree<T>::PostOrderRecursive(BiNode<T> * root)
    221 {
    222     if(root != NULL)
    223     {
    224                 PostOrderRecursive(root->pLeft);
    225                 PostOrderRecursive(root->pRight);
    226                 cout<<root->data<<" ";
    227     }
    228 }
    229 
    230 
    231 template <typename T>
    232 void BiTree<T>::PostOrderNonRecursive(BiNode<T> * root)
    233 {
    234 
    235     stack<BiNode<T> *> s1;
    236     stack<int> s2;//s2辅助记录s1相应位置的元素的状态:s1、s2保持同步。
    237             
    238     while(root != NULL || !s1.empty())
    239     {
    240         while(root != NULL)
    241         {
    242             s1.push(root);
    243             s2.push(1);
    244             root = root->pLeft;
    245         }
    246         if(!s1.empty())
    247         {
    248             if(s2.top()==1)
    249             {
    250                 s2.pop();
    251                 s2.push(2);
    252                 root = s1.top()->pRight;
    253             }
    254             else
    255             {
    256                 root = s1.top();
    257                 s1.pop();
    258                 s2.pop();
    259                 cout<<root->data<<" ";
    260                 root = NULL;    
    261             }
    262         }
    263         
    264     }
    265             
    266 }
    267 
    268 
    269 template <typename T>
    270 void BiTree<T>::PostOrder1()
    271 {
    272     PostOrderRecursive(root);
    273     cout<<endl;
    274 }
    275 
    276 
    277 template <typename T>
    278 void BiTree<T>::PostOrder2()
    279 {
    280     PostOrderNonRecursive(root);
    281     cout<<endl;
    282 }
    283 
    284 
    285 template <typename T>
    286 void BiTree<T>::LevelOrder(BiNode<T> * root)
    287 {    
    288     BiNode<T> * p;
    289     queue<BiNode<T> *> q;
    290     if(root == NULL) 
    291         return;
    292     q.push(root);
    293     while(!q.empty())
    294     {
    295         p = q.front();
    296         cout << p->data<<" ";
    297         q.pop();
    298         if(p->pLeft != NULL) q.push(p->pLeft);
    299         if(p->pRight != NULL) q.push(p->pRight);
    300     }
    301 }
    302 
    303 
    304 template <typename T>
    305 void BiTree<T>::LevelOrder()
    306 {
    307     LevelOrder(root);
    308     cout<<endl;
    309 }
    310 
    311 
    312 
    313 int main()
    314 {
    315 
    316 
    317     ifstream fin("BiTree.txt");// 输入文件
    318     ofstream fout("out.txt");  //输出文件
    319 
    320     streambuf *cinbackup;
    321     streambuf *coutbackup;
    322 
    323     cinbackup= cin.rdbuf(fin.rdbuf());  //用 rdbuf() 重新定向
    324     coutbackup= cout.rdbuf(fout.rdbuf());  //用 rdbuf() 重新定向
    325 
    326     BiTree<char> *pbitree = new BiTree<char>;//创建一颗二叉树
    327     
    328     cout << "*preorder =   " << preorder << endl;
    329     cout << " PreOrder1(): ";
    330     pbitree->PreOrder1();
    331     cout << " PreOrder2(): ";
    332     pbitree->PreOrder2();
    333     cout<<endl;
    334     
    335     cout << "*inorder =   " << inorder << endl;
    336     cout << " inorder1(): ";
    337     pbitree->InOrder1();
    338     cout << " InOrder2(): ";
    339     pbitree->InOrder2();
    340     cout<<endl;
    341     
    342     cout << "*postorder =   " << postorder << endl;
    343     cout << " PostOrder1(): ";
    344     pbitree->PostOrder1();    
    345     cout << " PostOrder2(): ";
    346     pbitree->PostOrder2();
    347     cout<<endl;
    348     
    349     cout << "*levelorder =  " << levelorder << endl;
    350     cout << " LevelOrder(): ";
    351     pbitree->LevelOrder();
    352 
    353     delete pbitree;
    354     cin.rdbuf(cinbackup);  // 取消,恢复键盘输入
    355     cout.rdbuf(coutbackup);  //取消,恢复屏幕输出
    356     return 0;
    357 }
    View Code

      【作者:Dillonn  出处: http://www.cnblogs.com/Dillonn/p/4226929.html  欢迎转载,请务必保留本行】

  • 相关阅读:
    Qt音视频开发11-ffmpeg常用命令
    Qt音视频开发10-ffmpeg控制播放
    Qt音视频开发9-ffmpeg录像存储
    Intellij IDEA 与maven 版本不符 Unable to import maven project See logs for details: No implementation for org.apache.maven.model.path.PathTranslator was bound
    Java Map 遍历史上最全
    java new date 结果与操作系统时间相差8小时处理解决方法
    elasticsearch报错
    Pytorch-基于Transformer的情感分类
    Pytorch-LSTM+Attention文本分类
    PHP FFI调用go,居然比go还快
  • 原文地址:https://www.cnblogs.com/Dillonn/p/4226929.html
Copyright © 2011-2022 走看看