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