Traversing Binary Tree - non-recursive algorithm

Construction of a binary tree

         A
        / \
       B    C
      / \  / \
     D   E F  G
    前序:ABDECFG
    中序:DBEAFCG
    后序:DEBFGCA

The above-described first embodiment may utilize a complete binary tree traversal order (recursively) input, as follows ( '#' represents an empty tree):

void CreateBiTree(BiTree *T)
{
    TElemType e;
    
    if ((e=getchar()) == '#')
    {
        *T = NULL;
    }
    else
    {
        *T = (BiTree) malloc(sizeof(BiTNode));
        if (!T)
        {
            exit(0);
        }
        (*T)->data = e;
        CreateBiTree(&(*T)->lchild);    //创建左子树
        CreateBiTree(&(*T)->rchild);    //创建右子树
    }
}

In order traversal (non-recursive algorithm)

Principle: sequentially accessing the left subtree binary tree, and a pointer to the node stored in the stack, when the pointer is empty, a left subtree access is completed, this case should be de-stacked data output node, then access right subtree ;

In the above binary tree traversal sequence, for example, following traversal (recommended control code analysis);

  1. Node A, B, D stack, the stack elements {A, B, D]
  2. The node D of the left subtree is empty, then D and outputs de-stacked, the stack of elements [A, B]
  3. D into the right subtree, right subtree D is empty, the stack elements {A, B}
  4. Continue unstack, i.e., the output of the B stack elements [A]
  5. Access right subtree B E, E push the stack of elements [A, E]
  6. Access E left subtree is empty, retired stack output stack elements E [A]
  7. Access right subtree E A within the output stack elements are empty, stack-off []
  8. Access right subtree A, C, F stack within a stack element [C, F]
  9. F left subtree are empty, de-stacked output F, the stack of element [C]
  10. C elements in the stack access right subtree G [G]
  11. G left subtree are empty, and outputs the de-stacked stack elements [G]
  12. At this time, the node pointer is NULL, and also the stack is empty, the end of traversal

Code:

void InorderTraverse(BiTree T,Stack *s)
{
    BiTree P=T;
    while(P||s->stacksize!=0)
    {
        if(P)
        {
            Push(s, P);
            P=P->lchild;
        }
        else
        {
            P=Pop(s);
            printf("%c ",P->data);
            P=P->rchild;
        }
    }
}

Preorder (non-recursive algorithm)

Thought Thought sequence preorder traversal in basically the same except that the code output at different positions on the;

void preOrderTraverse(BiTree T,Stack *s)
{
    BiTree p=T;
    while(p||s->stacksize!=0)
    {
        if(p)
        {
            printf("%c ",p->data);
            Push(s, p);
            p=p->lchild;
        }
        else
        {
            p=Pop(s);
            p=p->rchild;
        }
    }
}

Traversal:

  1. Output A, A push the stack of elements [A]

  2. Output B, B push the stack of elements [A, B]

  3. D output, push the stack elements D [A, B, D]

  4. D unstack output E, E push the stack of elements {A, B, E]

  5. E unstack, the output C, C push the stack of elements [A, B, C}

  6. Output F, F push the stack of elements [A, B, C, F]

  7. F unstack, output G, G push the stack of elements {A, B, C, G]

  8. Right subtree G, C, B, A are empty, the stack sequentially

Postorder (non-recursive algorithm)

Postorder the left and right, roots, and to more complex sequences, sequence comparison; first order because the postorder, children are left with the root node of the adjacent output, final output then requires preorder root knot point, you should first access right subtree, the following algorithm, by means of a further stack after the completion of order traversal;

void PostOrderTraverse(BiTree T,Stack *s1,Stack *s2)
{
    BiTree p=T;
    while(p||s1->stacksize!=0)
    {
        if(p)
        {
            Push(s1,p);
            Push(s2,p);
            p=p->rchild;
        }
        else
        {
            p=Pop(s1);
            p=p->lchild;
        }
    }
    while(s2->stacksize!=0)
    {
        p=Pop(s2);
        printf("%c ",p->data);
    }
}

Traversal:

  1. A, C, G stack Stack 1 [A, C, G] [2 stacks A, C, G]
  2. G retreat, F [1 push A, C, F [2] stack A, C, G, F]
  3. F, C back, B [1 push A, B [2] stack A, C, G, F, B]
  4. Push [1 E A, B, E [2] stack A, C, G, F, B, E]
  5. E retreat, D [1 push A, B, D [2] stack A, C, G, F, B, E, D]
  6. Output stack 2, i.e. subsequent sequence

This algorithm requires that all nodes have binary tree into the stack, so more storage space consumed

Complete code:

#include <stdio.h>
#include<stdlib.h>

typedef char TElemType;
//树结构
typedef struct BiTNode
{
    TElemType data;
    struct BiTNode *lchild, *rchild;
}BiTNode, *BiTree;

//栈结构
typedef struct Stack
{
    BiTree  date;
    int stacksize;  //记录元素个数
    struct Stack *next;
    struct Stack *base;  //栈底指针
    struct Stack *top;  //栈顶指针
}Stack;


//栈初始化
void InitStack(Stack *s)
{
    s->stacksize=0;
    s->base=NULL;
    s->top=s->base;
}

//插入数据
void Push(Stack *s,BiTree T)
{
        Stack *p;
        p=(Stack *)malloc(sizeof(Stack));
        if(!p)
            exit(0);
        p->date=T;
        if(s->stacksize==0)  //当插入第一个元素时,指针的变化
        {
            s->base=p;    //赋给栈底指针
            s->top=p;
            p->next=NULL;
        }
        else
        {
            p->next=s->top;
            s->top=p;
            
        }
        s->stacksize++;
}


//删除并返回栈顶元素
BiTree Pop(Stack *s)
{
    BiTree t;
    Stack *p;
    p=s->top;
    t=p->date;
    s->top=p->next;
    free(p);
    s->stacksize--;
    return t;
}

/*构建二叉树*/
void CreateBiTree(BiTree *T)
{
    TElemType e;
    
    if ((e=getchar()) == '#')
    {
        *T = NULL;
    }
    else
    {
        *T = (BiTree) malloc(sizeof(BiTNode));
        if (!T)
        {
            exit(0);
        }
        (*T)->data = e;
        CreateBiTree(&(*T)->lchild);    //创建左子树
        CreateBiTree(&(*T)->rchild);    //创建右子树
    }
}

//中序遍历(非递归)
void InorderTraverse(BiTree T,Stack *s)
{
    BiTree P=T;
    while(P||s->stacksize!=0)
    {
        if(P)
        {
            Push(s, P);
            P=P->lchild;
        }
        else
        {
            P=Pop(s);
            printf("%c ",P->data);
            P=P->rchild;
        }
    }
}

//先序遍历(非递归)
void preOrderTraverse(BiTree T,Stack *s)
{
    BiTree p=T;
    while(p||s->stacksize!=0)
    {
        if(p)
        {
            printf("%c ",p->data);
            Push(s, p);
            p=p->lchild;
        }
        else
        {
            p=Pop(s);
            p=p->rchild;
        }
    }
}

//后序遍历
void PostOrderTraverse(BiTree T,Stack *s1,Stack *s2)
{
    BiTree p=T;
    while(p||s1->stacksize!=0)
    {
        if(p)
        {
            Push(s1,p);
            Push(s2,p);
            p=p->rchild;
        }
        else
        {
            p=Pop(s1);
            p=p->lchild;
        }
    }
    while(s2->stacksize!=0)
    {
        p=Pop(s2);
        printf("%c ",p->data);
    }
}

int main()
{
    printf("请输入二叉树,#代表空树:\n");
    BiTree T;
    Stack stack1,stack2,*p1,*p;
    p=&stack1;p1=&stack2;
    InitStack(p);
    InitStack(p1);
    CreateBiTree(&T);
    printf("前序遍历结果为:");
    preOrderTraverse(T, p);
    printf("\n");
    printf("中序遍历结果为:");
    InorderTraverse(T, p);
    printf("\n");
    printf("后序遍历结果为:");
    PostOrderTraverse(T, p,p1);
    printf("\n");
    return 0;
}
/* 测试
ABD##E##CF##G##
前序遍历结果为:A B D E C F G 
中序遍历结果为:D B E A F C G 
后序遍历结果为:D E B F G C A 
Program ended with exit code: 0
*/

Postscript: I do not know this blog Detailed count, in the process of writing, have a deeper understanding of the code, but also a deeper understanding of the entire traversal, hope this article you can have a little bit of help

Guess you like

Origin www.cnblogs.com/zhulmz/p/11861058.html