遍历二叉树的各种操作(非递归遍历)

更多二叉树的操作见http://blog.csdn.net/Hackbuteer1/article/details/6686858

http://blog.csdn.net/Hackbuteer1/article/details/8022138

先使用先序的方法建立一棵二叉树,然后分别使用递归与非递归的方法实现前序、中序、后序遍历二叉树,并使用了两种方法来进行层次遍历二叉树,一种方法就是使用STL中的queue,另外一种方法就是定义了一个数组队列,分别使用了front和rear两个数组的下标来表示入队与出队,还有两个操作就是求二叉树的深度、结点数。。。

[cpp] view plain copy
 
  1. #include<iostream>
  2. #include<queue>
  3. #include<stack>
  4. usingnamespacestd;
  5. //二叉树结点的描述
  6. typedefstructBiTNode
  7. {
  8. chardata;
  9. structBiTNode*lchild,*rchild;//左右孩子
  10. }BiTNode,*BiTree;
  11. //按先序遍历创建二叉树
  12. //BiTree*CreateBiTree()//返回结点指针类型
  13. //voidCreateBiTree(BiTree&root)//引用类型的参数
  14. voidCreateBiTree(BiTNode**root)//二级指针作为函数参数
  15. {
  16. charch;//要插入的数据
  17. scanf("\n%c",&ch);
  18. //cin>>ch;
  19. if(ch=='#')
  20. *root=NULL;
  21. else
  22. {
  23. *root=(BiTNode*)malloc(sizeof(BiTNode));
  24. (*root)->data=ch;
  25. printf("请输入%c的左孩子:",ch);
  26. CreateBiTree(&((*root)->lchild));
  27. printf("请输入%c的右孩子:",ch);
  28. CreateBiTree(&((*root)->rchild));
  29. }
  30. }
  31. //前序遍历的算法程序
  32. voidPreOrder(BiTNode*root)
  33. {
  34. if(root==NULL)
  35. return;
  36. printf("%c",root->data);//输出数据
  37. PreOrder(root->lchild);//递归调用,前序遍历左子树
  38. PreOrder(root->rchild);//递归调用,前序遍历右子树
  39. }
  40. //中序遍历的算法程序
  41. voidInOrder(BiTNode*root)
  42. {
  43. if(root==NULL)
  44. return;
  45. InOrder(root->lchild);//递归调用,前序遍历左子树
  46. printf("%c",root->data);//输出数据
  47. InOrder(root->rchild);//递归调用,前序遍历右子树
  48. }
  49. //后序遍历的算法程序
  50. voidPostOrder(BiTNode*root)
  51. {
  52. if(root==NULL)
  53. return;
  54. PostOrder(root->lchild);//递归调用,前序遍历左子树
  55. PostOrder(root->rchild);//递归调用,前序遍历右子树
  56. printf("%c",root->data);//输出数据
  57. }
  58. /*
  59. 二叉树的非递归前序遍历,前序遍历思想:先让根进栈,只要栈不为空,就可以做弹出操作,
  60. 每次弹出一个结点,记得把它的左右结点都进栈,记得右子树先进栈,这样可以保证右子树在栈中总处于左子树的下面。
  61. */
  62. voidPreOrder_Nonrecursive2(BiTreeT)//先序遍历的非递归
  63. {
  64. if(!T)
  65. return;
  66. stack<BiTree>s;
  67. s.push(T);
  68. while(!s.empty())
  69. {
  70. BiTreetemp=s.top();
  71. cout<<temp->data<<"";
  72. s.pop();
  73. if(temp->rchild)
  74. s.push(temp->rchild);
  75. if(temp->lchild)
  76. s.push(temp->lchild);
  77. }
  78. }
  79. voidPreOrder_Nonrecursive(BiTreeT)//先序遍历的非递归
  80. {
  81. if(!T)
  82. return;
  83. stack<BiTree>s;
  84. while(T)//左子树上的节点全部压入到栈中
  85. {
  86. s.push(T);
  87. cout<<T->data<<"";
  88. T=T->lchild;
  89. }
  90. while(!s.empty())
  91. {
  92. BiTreetemp=s.top()->rchild;//栈顶元素的右子树
  93. s.pop();//弹出栈顶元素
  94. while(temp)//栈顶元素存在右子树,则对右子树同样遍历到最下方
  95. {
  96. cout<<temp->data<<"";
  97. s.push(temp);
  98. temp=temp->lchild;
  99. }
  100. }
  101. }
  102. voidInOrderTraverse(BiTreeT)//中序遍历的非递归
  103. {
  104. if(!T)
  105. return;
  106. stack<BiTree>S;
  107. BiTreecurr=T->lchild;//指向当前要检查的节点
  108. S.push(T);
  109. while(curr!=NULL||!S.empty())
  110. {
  111. while(curr!=NULL)//一直向左走
  112. {
  113. S.push(curr);
  114. curr=curr->lchild;
  115. }
  116. curr=S.top();
  117. S.pop();
  118. cout<<curr->data<<"";
  119. curr=curr->rchild;
  120. }
  121. }
  122. voidPostOrder_Nonrecursive(BiTreeT)//后序遍历的非递归
  123. {
  124. stack<BiTree>S;
  125. BiTreecurr=T;//指向当前要检查的节点
  126. BiTreeprevisited=NULL;//指向前一个被访问的节点
  127. while(curr!=NULL||!S.empty())//栈空时结束
  128. {
  129. while(curr!=NULL)//一直向左走直到为空
  130. {
  131. S.push(curr);
  132. curr=curr->lchild;
  133. }
  134. curr=S.top();
  135. //当前节点的右孩子如果为空或者已经被访问,则访问当前节点
  136. if(curr->rchild==NULL||curr->rchild==previsited)
  137. {
  138. cout<<curr->data<<"";
  139. previsited=curr;
  140. S.pop();
  141. curr=NULL;
  142. }
  143. else
  144. curr=curr->rchild;//否则访问右孩子
  145. }
  146. }
  147. voidPostOrder_Nonrecursive(BiTreeT)//后序遍历的非递归双栈法
  148. {
  149. stack<BiTree>s1,s2;
  150. BiTreecurr;//指向当前要检查的节点
  151. s1.push(T);
  152. while(!s1.empty())//栈空时结束
  153. {
  154. curr=s1.top();
  155. s1.pop();
  156. s2.push(curr);
  157. if(curr->lchild)
  158. s1.push(curr->lchild);
  159. if(curr->rchild)
  160. s1.push(curr->rchild);
  161. }
  162. while(!s2.empty())
  163. {
  164. printf("%c",s2.top()->data);
  165. s2.pop();
  166. }
  167. }
  168. intvisit(BiTreeT)
  169. {
  170. if(T)
  171. {
  172. printf("%c",T->data);
  173. return1;
  174. }
  175. else
  176. return0;
  177. }
  178. voidLeverTraverse(BiTreeT)//方法一、非递归层次遍历二叉树
  179. {
  180. queue<BiTree>Q;
  181. BiTreep;
  182. p=T;
  183. if(visit(p)==1)
  184. Q.push(p);
  185. while(!Q.empty())
  186. {
  187. p=Q.front();
  188. Q.pop();
  189. if(visit(p->lchild)==1)
  190. Q.push(p->lchild);
  191. if(visit(p->rchild)==1)
  192. Q.push(p->rchild);
  193. }
  194. }
  195. voidLevelOrder(BiTreeBT)//方法二、非递归层次遍历二叉树
  196. {
  197. BiTNode*queue[10];//定义队列有十个空间
  198. if(BT==NULL)
  199. return;
  200. intfront,rear;
  201. front=rear=0;
  202. queue[rear++]=BT;
  203. while(front!=rear)//如果队尾指针不等于对头指针时
  204. {
  205. cout<<queue[front]->data<<"";//输出遍历结果
  206. if(queue[front]->lchild!=NULL)//将队首结点的左孩子指针入队列
  207. {
  208. queue[rear]=queue[front]->lchild;
  209. rear++;//队尾指针后移一位
  210. }
  211. if(queue[front]->rchild!=NULL)
  212. {
  213. queue[rear]=queue[front]->rchild;//将队首结点的右孩子指针入队列
  214. rear++;//队尾指针后移一位
  215. }
  216. front++;//对头指针后移一位
  217. }
  218. }
  219. intdepth(BiTNode*T)//树的深度
  220. {
  221. if(!T)
  222. return0;
  223. intd1,d2;
  224. d1=depth(T->lchild);
  225. d2=depth(T->rchild);
  226. return(d1>d2?d1:d2)+1;
  227. //return(depth(T->lchild)>depth(T->rchild)?depth(T->lchild):depth(T->rchild))+1;
  228. }
  229. intCountNode(BiTNode*T)
  230. {
  231. if(T==NULL)
  232. return0;
  233. return1+CountNode(T->lchild)+CountNode(T->rchild);
  234. }
  235. intmain(void)
  236. {
  237. BiTNode*root=NULL;//定义一个根结点
  238. intflag=1,k;
  239. printf("本程序实现二叉树的基本操作。\n");
  240. printf("可以进行建立二叉树,递归先序、中序、后序遍历,非递归先序、中序遍历及非递归层序遍历等操作。\n");
  241. while(flag)
  242. {
  243. printf("\n");
  244. printf("|--------------------------------------------------------------|\n");
  245. printf("|二叉树的基本操作如下:|\n");
  246. printf("|0.创建二叉树|\n");
  247. printf("|1.递归先序遍历|\n");
  248. printf("|2.递归中序遍历|\n");
  249. printf("|3.递归后序遍历|\n");
  250. printf("|4.非递归先序遍历|\n");
  251. printf("|5.非递归中序遍历|\n");
  252. printf("|6.非递归后序遍历|\n");
  253. printf("|7.非递归层序遍历|\n");
  254. printf("|8.二叉树的深度|\n");
  255. printf("|9.二叉树的结点个数|\n");
  256. printf("|10.退出程序|\n");
  257. printf("|--------------------------------------------------------------|\n");
  258. printf("请选择功能:");
  259. scanf("%d",&k);
  260. switch(k)
  261. {
  262. case0:
  263. printf("请建立二叉树并输入二叉树的根节点:");
  264. CreateBiTree(&root);
  265. break;
  266. case1:
  267. if(root)
  268. {
  269. printf("递归先序遍历二叉树的结果为:");
  270. PreOrder(root);
  271. printf("\n");
  272. }
  273. else
  274. printf("二叉树为空!\n");
  275. break;
  276. case2:
  277. if(root)
  278. {
  279. printf("递归中序遍历二叉树的结果为:");
  280. InOrder(root);
  281. printf("\n");
  282. }
  283. else
  284. printf("二叉树为空!\n");
  285. break;
  286. case3:
  287. if(root)
  288. {
  289. printf("递归后序遍历二叉树的结果为:");
  290. PostOrder(root);
  291. printf("\n");
  292. }
  293. else
  294. printf("二叉树为空!\n");
  295. break;
  296. case4:
  297. if(root)
  298. {
  299. printf("非递归先序遍历二叉树:");
  300. PreOrder_Nonrecursive(root);
  301. printf("\n");
  302. }
  303. else
  304. printf("二叉树为空!\n");
  305. break;
  306. case5:
  307. if(root)
  308. {
  309. printf("非递归中序遍历二叉树:");
  310. InOrderTraverse(root);
  311. printf("\n");
  312. }
  313. else
  314. printf("二叉树为空!\n");
  315. break;
  316. case6:
  317. if(root)
  318. {
  319. printf("非递归后序遍历二叉树:");
  320. PostOrder_Nonrecursive(root);
  321. printf("\n");
  322. }
  323. else
  324. printf("二叉树为空!\n");
  325. break;
  326. case7:
  327. if(root)
  328. {
  329. printf("非递归层序遍历二叉树:");
  330. //LeverTraverse(root);
  331. LevelOrder(root);
  332. printf("\n");
  333. }
  334. else
  335. printf("二叉树为空!\n");
  336. break;
  337. case8:
  338. if(root)
  339. printf("这棵二叉树的深度为:%d\n",depth(root));
  340. else
  341. printf("二叉树为空!\n");
  342. break;
  343. case9:
  344. if(root)
  345. printf("这棵二叉树的结点个数为:%d\n",CountNode(root));
  346. else
  347. printf("二叉树为空!\n");
  348. break;
  349. default:
  350. flag=0;
  351. printf("程序运行结束,按任意键退出!\n");
  352. }
  353. }
  354. system("pause");
  355. return0;
  356. }

运行效果图如下:

分别输入:

1

2

4

#

#

5

#

#

3

6

#

#

7

#

#

就可以构造如下图所示的二叉树了。。

后序遍历非递归的另外一种写法:

 

[cpp] view plain copy
 
  1. /*
  2. 后序遍历由于遍历父节点是在遍历子节点之后,而且左节点和右节点遍历后的行为不一样,
  3. 所以需要用变量来记录前一次访问的节点,根据前一次节点和现在的节点的关系来确定具体执行什么操作
  4. */
  5. voidPostorder(BiTreeT)
  6. {
  7. if(T==NULL)
  8. return;
  9. stack<BiTree>s;
  10. BiTreeprev=NULL,curr=NULL;
  11. s.push(T);
  12. while(!s.empty())
  13. {
  14. curr=s.top();
  15. if(prev==NULL||prev->lchild==curr||prev->rchild==curr)
  16. {
  17. if(curr->lchild!=NULL)
  18. s.push(curr->lchild);
  19. elseif(curr->rchild!=NULL)
  20. s.push(curr->rchild);
  21. }
  22. elseif(curr->lchild==prev)
  23. {
  24. if(curr->rchild!=NULL)
  25. s.push(curr->rchild);
  26. }
  27. else
  28. {
  29. cout<<curr->data;
  30. s.pop();
  31. }
  32. prev=curr;
  33. }
  34. }

输入二叉树中的两个节点,输出这两个结点在数中最低的共同父节点。
思路:遍历二叉树,找到一条从根节点开始到目的节点的路径,然后在两条路径上查找共同的父节点。

[cpp] view plain copy
 
  1. //得到一条从根节点开始到目的节点的路径
  2. boolGetNodePath(TreeNode*pRoot,TreeNode*pNode,vector<TreeNode*>&path)
  3. {
  4. if(pRoot==NULL)
  5. returnfalse;
  6. if(pRoot==pNode)
  7. returntrue;
  8. elseif(GetNodePath(pRoot->lchild,pNode,path))
  9. {
  10. path.push_back(pRoot->lchild);
  11. returntrue;
  12. }
  13. elseif(GetNodePath(pRoot->rchild,pNode,path))
  14. {
  15. path.push_back(pRoot->rchild);
  16. returntrue;
  17. }
  18. returnfalse;
  19. }
  20. TreeNode*GetLastCommonNode(constvector<TreeNode*>&path1,constvector<TreeNode*>&path2)
  21. {
  22. vector<TreeNode*>::const_iteratoriter1=path1.begin();
  23. vector<TreeNode*>::const_iteratoriter2=path2.begin();
  24. TreeNode*pLast;
  25. while(iter1!=path1.end()&&iter2!=path2.end())
  26. {
  27. if(*iter1==*iter2)
  28. pLast=*iter1;
  29. else
  30. break;
  31. iter1++;
  32. iter2++;
  33. }
  34. returnpLast;
  35. }
  36. TreeNode*GetLastCommonParent(TreeNode*pRoot,TreeNode*pNode1,TreeNode*pNode2)
  37. {
  38. if(pRoot==NULL||pNode1==NULL||pNode2==NULL)
  39. returnNULL;
  40. vector<TreeNode*>path1;
  41. GetNodePath(pRoot,pNode1,path1);
  42. vector<TreeNode*>path2;
  43. GetNodePath(pRoot,pNode2,path2);
  44. returnGetLastCommonNode(path1,path2);
  45. }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值