图解数据结构(6)——树及树的遍历

转载自http://www.cppblog.com/guogangj/archive/2009/10/16/98772.html

树,顾名思义,长得像一棵树,不过通常我们画成一棵倒过来的树,根在上,叶在下。不说那么多了,图一看就懂:

当然了,引入了树之后,就不得不引入树的一些概念,这些概念我照样尽量用图,谁会记那么多文字?

树这种结构还可以表示成下面这种方式,可见树用来描述包含关系是很不错的,但这种包含关系不得出现交叉重叠区域,否则就不能用树描述了,看图:

面试的时候我们经常被考到的是一种叫“二叉树”的结构,二叉树当然也是树的一种了,它的特点是除了叶以外的节点都有两个子,图:

由此我们还可以推出“三叉树”:

当然还有“四叉树”,“五叉树”,“六叉树”……但太难画了,节点太多,略过。

九、树的遍历(Traversal)

值得再提一下的是二叉树,因为它确实比较特别,节点有两个子,这两个子是有左右之分的,颠倒一下左右,就是不一样的二叉树了,所以左右是不能随便颠倒的。


在第三篇讲到“队”的时候,提及到了广度优先遍历(Breadth-first traversal),除了广度优先遍历之外,还有深度优先遍历(Depth-first Traversal),深度优先遍历又可分为:前序遍历(Preorder Traversal),后序遍历(Postorder Traversal)和中序遍历(Inorder Traversal),其中中序遍历只有对二叉树才有意义,下图解释这几种遍历:

好了,又到代码阶段,写点代码。我看过许多数据结构的教材,二叉树遍历都是必不可少的内容,而且我知道的全部都是用递归实现的,现在,我要求你不用递归,实现对二叉树的中序遍历。怎么办?我给个提示:广度优先遍历时候我们用了队,中序遍历,我们使用*栈*。看看能不能写出来,我也来写:

  1. #include <stdio.h>  
  2.   
  3. // TreeNode  
  4. //////////////////////////////////////////////////////////////////////////  
  5. struct TreeNode  
  6. {  
  7.     char m_cVal;  
  8.     TreeNode* m_pLeft;  
  9.     TreeNode* m_pRight;  
  10.   
  11.     TreeNode(char cVal);  
  12.     ~TreeNode();  
  13. };  
  14.   
  15. TreeNode::TreeNode(char cVal)  
  16. {  
  17.     m_cVal = cVal;  
  18.     m_pLeft = 0;  
  19.     m_pRight = 0;  
  20. }  
  21.   
  22. TreeNode::~TreeNode()  
  23. {  
  24.       
  25. }  
  26.   
  27. //Stack  
  28. //////////////////////////////////////////////////////////////////////////  
  29. class Stack  
  30. {  
  31. public:  
  32.     Stack(int iAmount = 10);  
  33.     ~Stack();  
  34.       
  35.     //return 1 means succeeded, 0 means failed.  
  36.     int Pop(TreeNode* &pVal);  
  37.     int Push(TreeNode* pVal);  
  38.     int Top(TreeNode* &pVal);  
  39.   
  40.     //1 means not null, 0 means null.  
  41.     int NotNull();  
  42. private:  
  43.     TreeNode **m_ppData;  
  44.     int m_iCount;  
  45.     int m_iAmount;  
  46. };  
  47.   
  48. Stack::Stack(int iAmount)  
  49. {  
  50.     m_ppData = new TreeNode*[iAmount];  
  51.     m_iCount = 0;  
  52.     m_iAmount = iAmount;  
  53. }  
  54.   
  55. Stack::~Stack()  
  56. {  
  57.     delete m_ppData;  
  58. }  
  59.   
  60. int Stack::Pop(TreeNode* &pVal)  
  61. {  
  62.     if(m_iCount>0)  
  63.     {  
  64.         --m_iCount;  
  65.         pVal = m_ppData[m_iCount];  
  66.         return 1;  
  67.     }  
  68.     return 0;  
  69. }  
  70.   
  71. int Stack::Push(TreeNode* pVal)  
  72. {  
  73.     if(m_iCount<m_iAmount)  
  74.     {  
  75.         m_ppData[m_iCount] = pVal;  
  76.         ++m_iCount;  
  77.         return 1;  
  78.     }  
  79.     return 0;  
  80. }  
  81.   
  82. int Stack::Top(TreeNode* &pVal)  
  83. {  
  84.     if(m_iCount>0 && m_iCount<=m_iAmount)  
  85.     {  
  86.         pVal = m_ppData[m_iCount-1];  
  87.         return 1;  
  88.     }  
  89.     return 0;  
  90. }  
  91.   
  92. int Stack::NotNull()  
  93. {  
  94.     if(m_iCount!=0)  
  95.         return 1;  
  96.     return 0;  
  97. }  
  98.   
  99. int main(int argc, char* argv[])  
  100. {  
  101.     //Construct the tree.  
  102.     //      A  
  103.     //    /   \  
  104.     //   /     \  
  105.     //  B       C  
  106.     //   \     / \  
  107.     //    D   E   F  
  108.     //     \       \  
  109.     //      G       H  
  110.     //             / \  
  111.     //            I   J  
  112.     //           / \  
  113.     //          K   L  
  114.     TreeNode nA('A');  
  115.     TreeNode nB('B');  
  116.     TreeNode nC('C');  
  117.     TreeNode nD('D');  
  118.     TreeNode nE('E');  
  119.     TreeNode nF('F');  
  120.     TreeNode nG('G');  
  121.     TreeNode nH('H');  
  122.     TreeNode nI('I');  
  123.     TreeNode nJ('J');  
  124.     TreeNode nK('K');  
  125.     TreeNode nL('L');  
  126.   
  127.     nA.m_pLeft = &nB;  
  128.     nA.m_pRight = &nC;  
  129.     nB.m_pRight = &nD;  
  130.     nD.m_pRight = &nG;  
  131.     nC.m_pLeft = &nE;  
  132.     nC.m_pRight = &nF;  
  133.     nF.m_pRight = &nH;  
  134.     nH.m_pLeft = &nI;  
  135.     nH.m_pRight = &nJ;  
  136.     nI.m_pLeft = &nK;  
  137.     nI.m_pRight = &nL;  
  138.   
  139.     Stack st;  
  140.   
  141.     //Inorder traversal  
  142.     TreeNode *pVal = &nA;  
  143.     int iPopped = 0;  
  144.     while(pVal!=0)  
  145.     {  
  146.         if(pVal->m_pLeft!=0 && iPopped==0)  
  147.         {  
  148.             st.Push(pVal);  
  149.             pVal = pVal->m_pLeft;  
  150.             iPopped = 0;  
  151.         }  
  152.         else if(pVal->m_pRight!=0)  
  153.         {  
  154.             printf("%c ", pVal->m_cVal);  
  155.             pVal = pVal->m_pRight;  
  156.             iPopped = 0;  
  157.         }  
  158.         else  
  159.         {  
  160.             printf("%c ", pVal->m_cVal);  
  161.             if(0==st.Pop(pVal))  
  162.                 break;  
  163.             iPopped = 1;  
  164.         }  
  165.     }  
  166.   
  167.     return 0;  
  168. }  

猜你喜欢

转载自blog.csdn.net/ytlcainiao/article/details/45915301