由一道面试题“打印二叉树中和为某一值的路径”想到的二叉树的创建问题。

今年要找工作了,前两天看了下面试题,其中有一道打印二叉树中和为某一值的路径面试题目,猛然想起很有必要吧二叉树的创建问题好好看看,正好今天周六,实验室没什么事情,就写了一上午代码,把这个问题好好理解下,希望各位大牛看到后,能给点指导意见补充或者纠正下,谢谢各位支持。好了 饿的不行了 吃饭去了。

View Code
  1 // 二叉树中和为某一值.cpp : 定义控制台应用程序的入口点。
2 //
3
4 /***********************************************************************
5 题目:输入一棵二叉树和一个整数,打印出二叉树中节点值的和为输入整数的所有路径
6 从树的根节点开始往下一直到叶节点所经过的结点形成一条路径。
7 // 10
8 // / \
9 // 5 12
10 // /\
11 // 4 7
12 // 有两条路径上的结点和为22 一条是10-5-7 另外一条是10-12
13
14 对于 递归构建二叉树 输入序列为10 5 4 0 0 7 0 0 12 0 0
15 *************************************************************************/
16
17
18
19 #include "stdafx.h"
20 #include <vector>
21 #include <stdlib.h>
22 #include <iostream>
23 using namespace std;
24
25 struct BinaryTreeNode
26 {
27 int m_nValue;
28 BinaryTreeNode *m_pLeft;
29 BinaryTreeNode *m_pRight;
30 };
31
32
33
34 /************************************************分割线****************************************************/
35 /******************** 第一种创建二叉树方法 ****************************/
36 /************************************************分割线*****************************************************/
37 /************************************************************************************************************
38 此种方法借鉴了何海涛老师的方法,这种方法有点类似第四种方案,插入创建二叉树。他的特点是用户保证输入的正确性
39 是一种非常简练的测试用创建二叉树方案。
40 ***********************************************************************************************************/
41 BinaryTreeNode* CreatBinaryTreeNode(int value)
42 {
43 BinaryTreeNode* pnode=new BinaryTreeNode();
44 pnode->m_nValue=value;
45 pnode->m_pLeft=NULL;
46 pnode->m_pRight=NULL;
47 return pnode;
48 }
49
50 void ConnectBinaryTreeNode(BinaryTreeNode *pparent,BinaryTreeNode *pleft,BinaryTreeNode* pright)
51 {
52 if(pparent!=NULL)
53 {
54 pparent->m_pLeft=pleft;
55 pparent->m_pRight=pright;
56 }
57 }
58
59
60 /************************************************分割线****************************************************/
61 /******************** 第二种创建二叉树方法 ****************************/
62 /************************************************分割线*****************************************************/
63 /*********************************************************************************************************
64 这种方案网上有人称之为无参数创建,其实创建二叉树思路可以归结为两点:
65 1 没有参数传递,这种方案一般都是要在返回值上下文章,返回根节点。
66 2 有参数传递, 但是无返回值。这一种其实比较难点,因为指针传值和内存传递过程中
67 有可能没搞清楚怎么回事就已经被释放或成为非法指针。
68 **********************************************************************************************************/
69 BinaryTreeNode* CreateBinaryTreeNode()
70 {
71 int value;
72 cout<<"请输入节点值: ";
73 cin>>value;
74 cout<<endl;
75 if(!value) return NULL;
76 BinaryTreeNode* pRoot=new BinaryTreeNode();
77 pRoot->m_nValue=value;
78 pRoot->m_pLeft=CreateBinaryTreeNode();
79 pRoot->m_pRight=CreateBinaryTreeNode();
80 return pRoot;
81 }
82 /************************************************分割线****************************************************/
83 /******************** 第三种创建二叉树方法 ****************************/
84 /************************************************分割线*****************************************************/
85 /********************************************************************************************************
86 这种方案就是难了点,传递过程我们要始终保证改变的是实参的指针值。
87 *********************************************************************************************************/
88 void CreateBinaryTreeNode(BinaryTreeNode **t)
89 {
90 int value;
91 cout<<"请输入节点值: ";
92 cin>>value;
93 cout<<endl;
94 if(!value)
95 {
96 *t=NULL; //此处一定要加此条语句,不然后面再遍历时报错。
97 return;
98 }
99 *t=(BinaryTreeNode *)malloc(sizeof(BinaryTreeNode));
100 if(*t==NULL)
101 {
102 cerr<<"out of memory"<<endl;
103 exit(1);
104 }
105 (*t)->m_nValue=value;
106 //&t=pRoot;
107 CreateBinaryTreeNode(&((*t)->m_pLeft));
108 CreateBinaryTreeNode(&((*t)->m_pRight));
109 }
110 /************************************************分割线****************************************************/
111 /******************** 第四种创建二叉树方法 ****************************/
112 /************************************************分割线*****************************************************/
113
114 /*****************************************************************************************************
115 第四种这种方案比较理想化,建议采用这种方案。
116 *****************************************************************************************************/
117 //第四种方法有两个函数构成一个是BinaryTreeNode* CreatBinaryTreeNode(int value) 因为这个函数上述已经实现 故不再赘述
118 //另一个函数是下面实现的插入函数。
119 void insert(BinaryTreeNode **pRoot,int value)
120 {
121 if(!value) return;
122 BinaryTreeNode *pnode=CreatBinaryTreeNode(value);
123 if(!pnode)
124 {
125 cerr<<"out of memory"<<endl;
126 exit(1);
127 }
128 if(!(*pRoot))
129 {
130 *pRoot=pnode;
131 }
132 else if(pnode->m_nValue>(*pRoot)->m_nValue)
133 insert(&((*pRoot)->m_pRight),pnode->m_nValue);
134 else
135 insert(&((*pRoot)->m_pLeft),pnode->m_nValue);
136
137 }
138
139
140 /***************************************创建方法完毕****************************************/
141 /*******************************************************************************************/
142
143
144
145
146
147
148 void DestroyTree(BinaryTreeNode* pRoot) //销毁指针函数
149 {
150 if(pRoot != NULL)
151 {
152 BinaryTreeNode* pLeft = pRoot->m_pLeft;
153 BinaryTreeNode* pRight = pRoot->m_pRight;
154
155 delete pRoot;
156 pRoot = NULL;
157
158 DestroyTree(pLeft);
159 DestroyTree(pRight);
160 }
161 }
162
163
164 void FindPath(BinaryTreeNode *pRoot,int expectedsum,vector<int> path,int currentsum);
165 void FindPath(BinaryTreeNode *pRoot,int expectedsum)
166 {
167 if(pRoot==NULL)
168 return;
169 int currentsum=0;
170 vector<int> path;
171 FindPath(pRoot,expectedsum,path,currentsum);
172 }
173 //下面这个为查找二叉树中和为定值的函数
174 void FindPath(BinaryTreeNode *pRoot,int expectedsum,vector<int> path,int currentsum)
175 {
176 currentsum+=pRoot->m_nValue;
177 cout<<pRoot->m_nValue<<" being visited"<<endl;
178 path.push_back(pRoot->m_nValue);
179 bool isLeaf=pRoot->m_pLeft==NULL&&pRoot->m_pRight==NULL; //判断是否为叶子节点
180 if(currentsum==expectedsum&&isLeaf)
181 {
182 cout<<"we have find path list: "<<endl;
183 vector<int>::iterator iter=path.begin();
184 for(;iter!=path.end();iter++)
185 cout<<*iter<<"\t";
186 cout<<endl;
187 }
188 if(currentsum>=expectedsum) //对树进行剪枝 =也在剪枝范围内。见test1
189 return;
190 if(pRoot->m_pLeft!=NULL)
191 FindPath(pRoot->m_pLeft,expectedsum,path,currentsum);
192 if(pRoot->m_pRight!=NULL)
193 FindPath(pRoot->m_pRight,expectedsum,path,currentsum);
194 currentsum-=pRoot->m_nValue;
195 path.pop_back();
196
197 }
198
199
200 void Test(const char* str,BinaryTreeNode *pRoot,int expectedsum)
201 {
202 cout<<str<<" have begin: "<<endl;
203 FindPath(pRoot,expectedsum);
204 cout<<endl;
205 }
206
207 void Test1()
208 {
209 BinaryTreeNode *pNode10=CreatBinaryTreeNode(10);
210 BinaryTreeNode *pNode5=CreatBinaryTreeNode(5);
211 BinaryTreeNode *pNode12=CreatBinaryTreeNode(12);
212 BinaryTreeNode *pNode4=CreatBinaryTreeNode(4);
213 BinaryTreeNode *pNode7=CreatBinaryTreeNode(7);
214 BinaryTreeNode *pNode11=CreatBinaryTreeNode(11);
215 BinaryTreeNode *pNode13=CreatBinaryTreeNode(13);
216 ConnectBinaryTreeNode(pNode10,pNode5,pNode12);
217 ConnectBinaryTreeNode(pNode5,pNode4,pNode7);
218 ConnectBinaryTreeNode(pNode12,pNode11,pNode13);
219 Test("test1",pNode10,22);
220 DestroyTree(pNode10);
221
222 }
223
224
225 void Test2()
226 {
227 cout<<"方法二创建二叉树"<<endl;
228 BinaryTreeNode* pnode=CreateBinaryTreeNode();
229 Test("test2",pnode,22);
230 DestroyTree(pnode);
231 }
232
233 void Test3()
234 {
235 cout<<"方法三创建二叉树"<<endl;
236 BinaryTreeNode *t=NULL;
237 CreateBinaryTreeNode(&t);
238 Test("test3",t,22);
239 DestroyTree(t);
240
241 }
242
243 void Test4()
244 {
245 cout<<"方法四创建二叉树"<<endl;
246 BinaryTreeNode *pRoot=CreatBinaryTreeNode(10);
247 insert(&pRoot,5);
248 insert(&pRoot,12);
249 insert(&pRoot,4);
250 insert(&pRoot,7);
251 Test("test4",pRoot,22);
252 DestroyTree(pRoot);
253
254 }
255 int _tmain(int argc, _TCHAR* argv[])
256 {
257
258 Test1();
259 Test2();
260 Test3();
261 Test4();
262
263 return 0;
264 }

 

posted on 2012-03-10 12:46  北冥茶花开  阅读(1324)  评论(0编辑  收藏  举报

导航