代码改变世界

根据前序遍历和中序遍历的结果确定一颗二叉树并用树形格式打印输出

2013-10-21 01:12  Ross Wang  阅读(1071)  评论(0编辑  收藏  举报

前提

根据一颗二叉树的前序遍历和中序遍历结果肯定可以唯一地确定一颗二叉树.

证明: http://wenku.baidu.com/view/bf365b3431126edb6f1a1041.html

本篇文章主要解决两个问题:

1. 根据所给的前序和中序遍历结果确定一颗二叉树

2. 用我们熟悉的树形格式打印输出二叉树

确定二叉树

主要思想网上有很多帖子都提到了, 基本思路:

1. 从前序遍历结果获取父节点。

2. 用这个父节点把中序遍历结果分为两部分,左边是左子树的结点(可能为空),,右边是右子树的结点(也可能为空)。

3. 如果左子树不为空,递归进行1,2步,右子树类似。

树形格式输出二叉树

一般情况下,无论是前序、中序还是后序,都无法直接输出树形格式的二叉树,因为输出的时候会用到递归,不符合按层输出的要求。

当然如果二叉树的实现方式不同,就有可能直接按层输出。请参考http://www.cnblogs.com/Lowp/p/3379222.html

本文还是按照传统方式实现二叉树,使用类似于数组转置的思路完成。

输出树形结构示意图:

完整代码

  1 #include<iostream>
  2 #include<string>
  3 #include<vector>
  4 
  5 using namespace std;
  6 
  7 /******************************
  8 定义二叉树节点结构
  9 bValue:           结点值
 10 lNode:            左结点指针
 11 rNode:            右结点指针
 12 ******************************/
 13 struct BNode
 14 {
 15     char bValue;  
 16     BNode * lNode;
 17     BNode * rNode;
 18     BNode();
 19 };
 20 
 21 /******************************
 22 定义默认构造函数是为了避免一些编译器在初始化时,
 23 初始值不确定的情况。
 24 比如微软编译器在release编译模式下会对默认构造函数进行优化,
 25 初始值不确定
 26 明确定义默认构造函数可以让程序按照我们设想的方式运行。
 27 ******************************/
 28 BNode::BNode():bValue(0),lNode(NULL),rNode(NULL)
 29 {
 30 }
 31 
 32 /******************************
 33 声明函数DetermineBTree
 34 用来执行具体的二叉树确定和输出
 35 node:             父节点指针
 36 preOrderStr:      前序遍历结果
 37 midOrderStr:      中序遍历结果
 38 ******************************/
 39 void DetermineBTree(BNode * node, const string &preOrderStr, const string &midOrderStr);
 40 
 41 /******************************
 42 声明函数PrintBTree,打印二叉树。
 43 node:             节点指针
 44 ******************************/
 45 void PrintBTree(BNode * node);
 46 
 47 /******************************
 48 声明函数DeleteBTree,释放二叉树所有节点的空间并销毁。
 49 node:             节点指针
 50 ******************************/
 51 void DeleteBTree(BNode * node);
 52 
 53 /******************************
 54 声明函数DepthOfBTree,获取二叉树的深度。
 55 node:             节点指针
 56 ******************************/
 57 int DepthOfBTree(BNode * node);
 58 
 59 int main()
 60 {
 61     //定义前序和中序遍历结果
 62     string preOrderStr = "ABDECFG";
 63     string midOrderStr = "DBEACGF";
 64 
 65     //定义根节点指针
 66     BNode * rootNode = new BNode();
 67     //确定二叉树
 68     DetermineBTree(rootNode,preOrderStr,midOrderStr);
 69     if(!rootNode)
 70     {
 71         cout<<"Cannot determine a BTree according to the given preOrderStr and midOrderStr!"<<endl;
 72     }
 73     else
 74     {
 75         //打印二叉树
 76         PrintBTree(rootNode);
 77         //释放二叉树存储空间
 78         DeleteBTree(rootNode);
 79         cout<<"BTree has been destroyed!"<<endl;
 80     }
 81 
 82     getchar();
 83     return 0;
 84 }
 85 
 86 //定义DetermineBTree的实现体
 87 void DetermineBTree(BNode * node, const string &preOrderStr, const string &midOrderStr)
 88 {
 89     //对前序和中序遍历结果进行基本的合法性检查。
 90     if(preOrderStr.empty() || midOrderStr.empty() || 
 91         preOrderStr.length() !=midOrderStr.length())
 92     {
 93         cout<<"preOrderStr or midOrderStr is not valid!"<<endl;
 94         node = NULL;
 95         return;
 96     }
 97     //根结点不能为空
 98     //递归的时候结点指针在作为实参传入的时候已经初始化了,肯定不会是NULL
 99     if(!node)
100     {
101         cout<<"Error occured, node is NULL!"<<endl;
102         return;
103     }
104 
105     //前序结果的第一个char元素应该就是node的value。
106     node->bValue = preOrderStr[0];
107     //在中序遍历结果中查找根节点。
108     int rootNodeIndex = midOrderStr.find(preOrderStr[0]);
109     if(rootNodeIndex < 0)
110     {
111         cout<<"midOrderStr has a char not in preOrderStr!"<<endl;
112         node = NULL;
113         return;
114     }
115     else if(rootNodeIndex == 0)
116     {
117         //说明该节点没有左子树
118         node->lNode = NULL;
119     }
120     else
121     {
122         string leftMidOrderSubBTreeStr = midOrderStr.substr(0,rootNodeIndex);
123         string leftPreOrderSubBTreeStr = preOrderStr.substr(1,rootNodeIndex);
124         node->lNode = new BNode();
125         DetermineBTree(node->lNode,leftPreOrderSubBTreeStr, leftMidOrderSubBTreeStr);
126     }
127 
128 
129     if(rootNodeIndex ==( preOrderStr.length() - 1))
130     {
131         //说明该节点没有右子树
132         node->rNode = NULL;
133     }
134     else
135     {
136         string rightMidOrderSubBTreeStr = midOrderStr.substr(rootNodeIndex+1);
137         string rightPreOrderSubBTreeStr = preOrderStr.substr(1+rootNodeIndex);
138         node->rNode = new BNode();
139         DetermineBTree(node->rNode,rightPreOrderSubBTreeStr, rightMidOrderSubBTreeStr);
140     }
141 
142 
143 }
144 
145 void GetConvertedBTree(const BNode * node, const int &depth,
146     int layer,vector<string> &outputBTree)
147 {
148     int i;
149     if(node==NULL) return;
150     GetConvertedBTree(node->lNode,depth,layer+1,outputBTree);
151     string row = "";
152     for(i=0;i<2*layer-1;i++)
153     {
154         row.append(" ");
155     }
156     if(layer>0)
157     {
158         row.append("-");
159     }
160     row.append(1,node->bValue);
161     row.resize(2*depth+1, ' ');
162     outputBTree.push_back(row);
163     GetConvertedBTree(node->rNode,depth,layer+1,outputBTree);
164 }
165 
166 //定义PrintBTree的实现体
167 void PrintBTree(BNode * node)
168 {
169     int depth = DepthOfBTree(node) -1;
170     if(depth == 0)
171     {
172         cout<<"This is an empty BTree!"<<endl;
173     }
174     else
175     {
176         vector<string> outputBTree;
177         GetConvertedBTree(node,depth,0,outputBTree);
178 
179         //中序遍历方式输出的二叉树。
180         cout<<"middle ordered output:"<<endl;
181         for(vector<string>::const_iterator it = outputBTree.begin(); 
182             it != outputBTree.end(); ++it)
183         {
184             cout<<*it<<endl;
185         }
186 
187         //调整方向后树形格式的二叉树
188         cout<<"adjusted output:"<<endl;
189         for(int column = 0; column < depth*2+1; ++column)
190         {
191             for(vector<string>::const_iterator it = outputBTree.begin(); 
192                 it != outputBTree.end(); ++it)
193             {
194                 if((*it)[column] == '-')
195                     cout<<"|";
196                 else
197                     cout<<(*it)[column];
198             }
199             cout<<endl;
200         }
201     }
202 }
203 
204 
205 //定义DepthOfBTree的实现体
206 int DepthOfBTree(BNode * node)
207 {
208     int depthTotal(0),depthLeft(0),depthRight(0);
209     if (!node)    
210         depthTotal = 0;
211     else   
212     {
213         depthLeft = DepthOfBTree( node->lNode );
214         depthRight= DepthOfBTree( node->rNode );
215         depthTotal =1 + (depthLeft > depthRight ?depthLeft : depthRight);
216     } 
217     return depthTotal;
218 }
219 
220 //定义DeleteBTree的实现体
221 void DeleteBTree(BNode * node)
222 {
223     //判断输入的根节点是否为空,也就是是否是个空树。
224     if(node)
225     {
226         if(node->lNode)DeleteBTree(node->lNode);
227         if(node->rNode)DeleteBTree(node->rNode);
228         delete node;
229     }
230     else
231         cout<<"This is an empty BTree!"<<endl;
232 }