二叉树的遍历

文章作者:姜南(Slyar) 文章来源:Slyar Home (www.slyar.com) 转载请注明,谢谢合作。

上周数据结构课在讲二叉树的遍历,老师只讲递归算法,没有什么技术含量,遂自己琢磨非递归算法实现...

前序遍历:先访问根节点,再访问左子树,最后访问右子树。设置一个栈,出栈即为访问节点。先将根节点进栈,在栈不空时一直如下循环:出栈,访问,将其右孩子进栈,再将左孩子进栈。

中序遍历:先访问左子树,再访问根节点,最后访问右子树。设置一个栈,出栈即为访问节点。先将根节点的左节点全部进栈,然后出栈一个节点,访问。将该节点的右孩子节点进栈,再将右孩子节点的所有左节点全部进栈...如此这般直到栈空为止。

后序遍历:先访问左子树,再访问右子树,最后访问根节点。设置一个栈。先将根节点的左节点全部进栈。出栈一个节点,将该节点的右孩子进栈,再将右孩子的左节点全部进栈...当一个节点的左、右孩子都被访问过后再访问该节点,如此这般直到栈空为止。(判断某节点的右孩子是否被访问,需要单独设置一个指针跟踪刚刚访问的节点。在后序遍历中,某节点的右孩子节点一定刚好在该节点之前被访问)

因为代码的重点是非递归遍历,所以建立二叉树的过程我就使用了"前序递归"。对于如下一棵树,以"#"代表空节点,前序递归建立二叉树需要的输入数据和前序遍历的顺序是一样的,且每个叶子节点的左右孩子均为"#"。

输入:ABDH##I##EJ##K##CF#L##G##
前序遍历:A B D H I E J K C F L G
中序遍历:H D I B J E K A F L C G
后序遍历:H I D J K E B L F G C A

二叉树

代码如下:

[cpp]  view plain copy
  1. /* 
  2. Slyar 
  3. http://www.slyar.com 
  4. 2009.5.16 
  5. */  
  6. #include <stdio.h>  
  7. #include <stdlib.h>  
  8.    
  9. #define MAXSIZE 200  
  10.    
  11. /* 定义二叉树节点类型 */  
  12. typedef struct node  
  13. {  
  14.     char data;  
  15.     struct node *lchild, *rchild;  
  16. }BTNode;  
  17.    
  18. /* 函数声明 */  
  19. BTNode* CreatBitTree();  
  20. void PreOrder(BTNode*);  
  21. void InOrder(BTNode*);  
  22. void PostOrder(BTNode*);  
  23.    
  24. /* 主函数 */  
  25. int main()  
  26. {  
  27.     BTNode *root = NULL;  
  28.     root = CreatBitTree();  
  29.     PreOrder(root);  
  30.     InOrder(root);  
  31.     PostOrder(root);  
  32.     system("pause");  
  33.     return 0;  
  34. }  
  35.    
  36. /* 递归前序建立二叉树 */  
  37. BTNode* CreatBitTree()  
  38. {  
  39.     char ch;  
  40.     BTNode *b;  
  41.     scanf("%c", &ch);  
  42.     /* 遇到空节点停止递归 */  
  43.     if (ch == '#')  
  44.     {  
  45.         b = NULL;  
  46.     }  
  47.     else  
  48.     {  
  49.         b = (BTNode*) malloc(sizeof(BTNode));  
  50.         /* 建立根节点 */  
  51.         b->data = ch;  
  52.         /* 递归先序建立左子树 */  
  53.         b->lchild = CreatBitTree();  
  54.         /* 递归先序建立右子树 */  
  55.         b->rchild = CreatBitTree();  
  56.     }  
  57.     return b;  
  58. }  
  59.    
  60. /* 非递归前序遍历二叉树 */  
  61. void PreOrder(BTNode* b)  
  62. {  
  63.     BTNode *stack[MAXSIZE], *p;  
  64.     int top = -1;  
  65.     if (b != NULL)  
  66.     {  
  67.         /* 根节点入栈 */  
  68.         top++;  
  69.         stack[top] = b;  
  70.         /* 栈不空时循环 */  
  71.         while (top > -1)  
  72.         {  
  73.             /* 出栈并访问该节点 */  
  74.             p = stack[top];  
  75.             top--;  
  76.             printf("%c ", p->data);  
  77.             /* 右孩子入栈 */  
  78.             if (p->rchild != NULL)  
  79.             {  
  80.                 top++;  
  81.                 stack[top] = p->rchild;  
  82.             }  
  83.             /* 左孩子入栈 */  
  84.             if (p->lchild != NULL)  
  85.             {  
  86.                 top++;  
  87.                 stack[top] = p->lchild;  
  88.             }  
  89.         }  
  90.         printf("\n");  
  91.     }  
  92. }  
  93.    
  94. /* 非递归中序遍历二叉树 */  
  95. void InOrder(BTNode* b)  
  96. {  
  97.     BTNode *stack[MAXSIZE], *p;  
  98.     int top = -1;  
  99.     if (b != NULL)  
  100.     {  
  101.         p = b;  
  102.         while (top > -1 || p != NULL)  
  103.         {  
  104.             /* 扫描p的所有左节点并入栈 */  
  105.             while (p != NULL)  
  106.             {  
  107.                 top++;  
  108.                 stack[top] = p;  
  109.                 p = p->lchild;  
  110.             }  
  111.             if (top > -1)  
  112.             {  
  113.                 /* 出栈并访问该节点 */  
  114.                 p = stack[top];  
  115.                 top--;  
  116.                 printf("%c ", p->data);  
  117.                 /* 扫描p的右孩子 */  
  118.                 p = p->rchild;  
  119.             }  
  120.         }  
  121.         printf("\n");  
  122.     }  
  123. }  
  124.    
  125. /* 非递归后序遍历二叉树 */  
  126. void PostOrder(BTNode* b)  
  127. {  
  128.     BTNode *stack[MAXSIZE], *p;  
  129.     int sign, top = -1;  
  130.     if (b != NULL)  
  131.     {  
  132.         do  
  133.         {  
  134.             /* b所有左节点入栈 */  
  135.             while (b != NULL)  
  136.             {  
  137.                 top++;  
  138.                 stack[top] = b;  
  139.                 b = b->lchild;  
  140.             }  
  141.             /* p指向栈顶前一个已访问节点 */  
  142.             p = NULL;  
  143.             /* 置b为已访问 */  
  144.             sign = 1;  
  145.             while (top != -1 && sign)  
  146.             {  
  147.                 /* 取出栈顶节点 */  
  148.                 b = stack[top];  
  149.                 /* 右孩子不存在或右孩子已访问则访问b */  
  150.                 if (b->rchild == p)  
  151.                 {  
  152.                     printf("%c ", b->data);  
  153.                     top--;  
  154.                     /* p指向被访问的节点 */  
  155.                     p = b;  
  156.                 }  
  157.                 else  
  158.                 {  
  159.                     /* b指向右孩子节点 */  
  160.                     b = b->rchild;  
  161.                     /* 置未访问标记 */  
  162.                     sign = 0;  
  163.                 }  
  164.             }  
  165.         }while (top != -1);  
  166.         printf("\n");  
  167.     }  
  168. }  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值