`

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

阅读更多

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

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

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

[cpp]view plaincopy
 
  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 plaincopy
 
  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 plaincopy
 
  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. }
分享到:
评论

相关推荐

    二叉树先序遍历、中序遍历和后序遍历非递归算法 C++源码

    用C++写的二叉树先序遍历、中序遍历和后序遍历非递归算法

    中序遍历二叉树非递归算法

    ### 中序遍历二叉树非递归算法详解 #### 1. 理解中序遍历的基本概念 中序遍历是一种按照左子树、根节点、右子树的顺序访问二叉树所有节点的过程。对于每个节点,先遍历其左子树,然后访问该节点本身,最后遍历其右...

    C++ 二叉树的先序遍历、中序遍历和后序遍历非递归算法

    用C++写的,包括二叉树的构建,二叉树的先序遍历、中序遍历和后序遍历非递归算法。

    数据结构-非递归遍历二叉树

    通过以上非递归遍历方法,我们可以避免递归带来的栈溢出问题,尤其在处理深度较大的二叉树时更为有效。此外,这些方法也易于理解,可以灵活地应用于不同的场景,如构建平衡树、复制二叉树等。 在实际编程中,我们...

    二叉树递归和非递归遍历以及层次构建节点数为n的二叉树

    二种非递归实现 二叉树中序遍历: 递归实现 非递归实现 二叉树后序遍历: 递归实现 非递归实现 二叉树层次遍历 二叉树层次创建,创建方法遵循卡特兰数 http://write.blog.csdn.net/postedit/17380455

    二叉树的非递归遍历

    二叉树的非递归遍历,使用C++实现二叉树的非递归遍历,对正在学习算法的同学应该挺有帮助的

    遍历二叉树递归+非递归实验报告.doc

    实验结果展示了递归遍历和非递归遍历的遍历结果,两种方法均能正确遍历二叉树,但是递归遍历的结果输出更为直观简洁,而非递归遍历则依赖于栈的操作,相对复杂一些。 实验报告也对递归和非递归遍历方法的优缺点进行...

    c语言 二叉树应用:创建、递归非递归遍历、计算结点、分支、交换子树

    非递归先序遍历二叉树: 非递归中序遍历二叉树: 非递归后序遍历二叉树: 非递归中序遍历二叉树(算法2): 层次遍历二叉树: 递归计算单分支结点: 递归计算双分支结点: 递归计算叶子数: 二叉数的深度:...

    二叉树的创建与三种遍历的递归与非递归实现

    二叉树的创建与三种遍历的递归与非递归实现 包括二叉树的动态创建,前序遍历,中序遍历,后续遍历的递归与非递归方法的实现。

    数据结构二叉树遍历递归,非递归

    理解递归遍历后,非递归遍历的关键在于使用额外的数据结构(如栈或队列)来跟踪当前的遍历状态。非递归遍历的优势在于它避免了函数调用栈的深度限制,对于非常深的树,递归可能会导致栈溢出。 在实际编程中,根据...

    中序遍历二叉树非递归算法 栈实现代码

    //二叉树的二叉链表存储表示 typedef struct BiTNode { TElemType data; BiTNode *lchild, *rchild; //左右孩子指针 } BiTNode, *BiTree; typedef struct { BiTree *base; BiTree *top; int stacksize; //当前...

    各种遍历二叉树的算法包括非递归

    非递归遍历则避免了栈溢出的风险,但可能需要更多的空间来存储辅助数据结构。选择哪种方式取决于具体的应用场景和性能要求。 总结起来,二叉树遍历的非递归实现是通过栈或其他数据结构来模拟递归调用的过程,确保...

    按层次遍历二叉树的算法

    按层次遍历二叉树的算法思想是利用队列基本操作。队列是一种先进先出的数据结构,非常适合进行层次遍历。算法的步骤如下: 1. 初始化:将根结点入队列。 2. while(队列非空): a. 队首元素出队列。 b. 原队首...

    二叉树递归与非递归遍历

    非递归遍历通过使用辅助数据结构(如栈)避免了深度递归,更适合处理大规模的二叉树。同时,它也可以通过适当修改实现其他特定顺序的遍历,如层次遍历(Level Order Traversal),通过队列来存储节点。 在实际应用...

    先序遍历二叉树的非递归算法程序

    编写先序遍历二叉树的非递归算法程序,要求: (1)以二叉链表建立二叉树。 (2)输出遍历的结点序列。 (3)有实例验算。

    C语言实现二叉树的前序遍历(非递归)

    在深入探讨C语言实现二叉树的前序遍历(非递归)之前,我们首先应当理解何为二叉树以及前序遍历的基本概念。 ### 二叉树简介 ...在实际编程实践中,理解并掌握非递归遍历技巧对于优化算法性能至关重要。

    非递归中序遍历二叉树

    非递归中序遍历二叉树

    遍历二叉树的4个非递归算法.rar_binary tree_二叉树_二叉树 非递归 遍历_递归_遍历 CSharp

    本资源"遍历二叉树的4个非递归算法.rar"提供了C#语言实现的这四种非递归遍历方法,对于学习者来说是非常宝贵的资料。 1. **前序遍历**(Root-Left-Right): 在前序遍历中,我们首先访问根节点,然后递归地遍历左...

    二叉树递归和非递归遍历实验报告(含源码)

    本实验报告将深入探讨二叉树的递归和非递归遍历方法,并附带源代码实现,旨在帮助读者理解这两种遍历策略及其应用场景。 一、二叉树遍历 二叉树遍历主要有三种方法:前序遍历、中序遍历和后序遍历。它们是遍历...

Global site tag (gtag.js) - Google Analytics