分享

算法2(递归和非递归俩种方法实现二叉树的前序遍历)

 白雪~~~ 2012-03-10

题目:

递归和非递归俩种方法实现二叉树的前序遍历。

思路一:

对二叉树的递归遍历我相信大家只要学了数据结构后应当都很容易就能写出,这里主要是讨论二叉树的非递归写法。按照二叉树前序遍历的定义,无论是访问整棵树还是其子树,均应该遵循先访问根结点,然后访问根结点的左子树,最后访问根结点的右子树的。在整个二叉树前序遍历的过程中,程序始终要做的工作分成俩个部分:(借用辅助栈来实现)
1. 当前正在处理的树(子树)
2. 保存在栈中等待处理的部分。

当栈中元素位于栈顶即将出栈时,意味着其根结点和左子树已访问完成,出栈后,进入其右子树进行访问。

代码如下:

  1. /*-------------------------------
  2. Copyright by yuucyf. 2011.09.06
  3. --------------------------------*/
  4. #include "stdafx.h"
  5. #include <assert.h>
  6. #include <iostream>
  7. #include <stack>
  8. using namespace std;
  9. typedef struct tagBSTreeNode
  10. {
  11. int nValue;
  12. tagBSTreeNode *psLeft;
  13. tagBSTreeNode *psRight;
  14. tagBSTreeNode()
  15. {
  16. psLeft = psRight = 0;
  17. nValue = 0;
  18. }
  19. }S_BSTreeNode;
  20. void AddBSTreeNode(S_BSTreeNode *&psRoot, int nValue)
  21. {
  22. if (NULL == psRoot)
  23. {
  24. psRoot = new S_BSTreeNode;
  25. assert(psRoot);
  26. psRoot->nValue = nValue;
  27. return;
  28. }
  29. if (psRoot->nValue < nValue)
  30. AddBSTreeNode(psRoot->psRight, nValue);
  31. else
  32. AddBSTreeNode(psRoot->psLeft, nValue);
  33. }
  34. void PreOrder_Recursion(const S_BSTreeNode *psRoot)
  35. {
  36. if (NULL == psRoot)
  37. return;
  38. cout << psRoot->nValue << " ";
  39. PreOrder_Recursion(psRoot->psLeft);
  40. PreOrder_Recursion(psRoot->psRight);
  41. }
  42. void PreOrder_Not_Recursion(S_BSTreeNode *psRoot)
  43. {
  44. stack<S_BSTreeNode *> stackNode;
  45. S_BSTreeNode *psCurNode = psRoot;
  46. while ((!stackNode.empty()) || (psCurNode != NULL))
  47. {
  48. if (psCurNode != NULL)
  49. {
  50. while (psCurNode)
  51. {
  52. cout << psCurNode->nValue << " ";
  53. stackNode.push(psCurNode);
  54. psCurNode = psCurNode->psLeft;
  55. }
  56. }
  57. else
  58. {
  59. psCurNode = stackNode.top();
  60. stackNode.pop();
  61. psCurNode = psCurNode->psRight;
  62. }
  63. }
  64. }
  65. int _tmain(int argc, _TCHAR* argv[])
  66. {
  67. S_BSTreeNode *psRoot = NULL;
  68. AddBSTreeNode(psRoot, 8);
  69. AddBSTreeNode(psRoot, 6);
  70. AddBSTreeNode(psRoot, 4);
  71. AddBSTreeNode(psRoot, 5);
  72. AddBSTreeNode(psRoot, 12);
  73. AddBSTreeNode(psRoot, 10);
  74. AddBSTreeNode(psRoot, 15);
  75. AddBSTreeNode(psRoot, 13);
  76. AddBSTreeNode(psRoot, 14);
  77. cout << "递归遍历的结果为:" << endl;
  78. PreOrder_Recursion(psRoot);
  79. cout << endl;
  80. cout << "非递归遍历的结果为:" << endl;
  81. PreOrder_Not_Recursion(psRoot);
  82. cout << endl;
  83. //Don't forget to free memory.
  84. return 0;
  85. }

扩展:

如果要求是非递归后序遍历呢?非递归后序稍微有点复杂。按照二叉树后序遍历的定义,无论是访问整棵树还是起子树,均应该遵循先访问根结点左子树,然后访问根结点的右子树,最后访问根结点。值得注意的是,当一个元素位于栈顶即将处理的是,其左子树的访问一定完成,如果其右子树不为空,接下来应该进入其右子树访问,但此时该栈顶元素时不能出栈的,因为它作为根结点,其本身的值还未被访问。只有等到其右子树也访问完成后,该栈顶元素才能出栈,并输出它的值。 因此,在二叉树后序遍历的算法中,必须每个节点维护一个类型为int的整数nTag,
其每个元素(节点)的nTag取值为0 或1,用于标识栈中每个元素的状态。
1. 当一个元素刚进栈时,其对应的nTag 值置为0;
2. 当它位于栈顶即将被处理时,其nTag 值为0.意味着应该访问其右子树,于是将右子树作为当前处理的对象,此时该栈顶元素仍应该保留在栈中,并将其对应的nTag 值改为1.
3. 当其右子树访问完成后,该元素又一次位于栈顶,而此时其nTag 值为1,意味着其右子树已访问完成,接下来,应该直接访问的就是它,将其出栈。

代码如下:

  1. void PostOrder_Not_Recursion(S_BSTreeNode *psRoot)
  2. {
  3. stack<S_BSTreeNode *> stackNode;
  4. S_BSTreeNode *psCurNode = psRoot;
  5. while ((!stackNode.empty()) || (psCurNode != NULL))
  6. {
  7. if (psCurNode != NULL)
  8. {
  9. while (psCurNode /*&& psCurNode->nTag != 1*/)
  10. {
  11. stackNode.push(psCurNode);
  12. psCurNode = psCurNode->psLeft;
  13. }
  14. }
  15. psCurNode = stackNode.top();
  16. while ((!stackNode.empty()) && (psCurNode->nTag == 1))
  17. {
  18. cout << psCurNode->nValue << " ";
  19. stackNode.pop();
  20. if (stackNode.empty())
  21. psCurNode = NULL;
  22. else
  23. psCurNode = stackNode.top();
  24. }
  25. if (!stackNode.empty())
  26. {
  27. psCurNode->nTag = 1;
  28. psCurNode = psCurNode->psRight;
  29. }
  30. else
  31. psCurNode = NULL;
  32. }
  33. }

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多