文章作者:姜南(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
代码如下:
- /*
- 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");
- }
- }