二叉树的递归与非递归遍历

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

#define Size 100
#define False 0
#define Ture 1

/*树的存储结构*/
typedef struct Tree 
{
    char data;
    struct Tree *Lift;
    struct Tree *Right;
}Tree,*Btree;

/*栈的建立*/
typedef struct stack
{
    int top;
    Btree data[Size];
}sepstack;

/*栈的初始化*/
sepstack *init(sepstack *stack)
{
    stack = malloc(sizeof(sepstack));
    stack -> top = -1;
    return stack;
}

/*判断栈空*/
int empty(sepstack *stack)
{
    if(stack->top == -1)
    {
        return 1;
    }
    else
    {
        return 0;
    }
}

/*入栈操作*/
int push(sepstack *stack,Btree x)
{
    if(stack->top == (Size-1))
    {
        return 0;
    }
    else{
        stack->top++;
        stack->data[stack->top]=x;
        return 1;
    }
}

/*取出栈顶元素*/
void gettop(sepstack *stack,Btree *a)
{
//    Btree a;
    if(!empty(stack))
    {
        *a = stack->data[stack->top];
 //       return a;
    }
 //   else
   // {
   //     return 0;
   // }
}

/*弹出栈顶元素*/
void pop(sepstack *stack,Btree *a)
{
 //   Btree a;
    if(!empty(stack))
    {
        *a = stack->data[stack->top];
        stack->top--;
 //       return a;
    }
   // else{
     //   return 0;
    //}
}

/*一级指针建立二叉树*/
Btree create()
{
    char ch;
    Tree *p;
    ch = getchar();
    if(ch=='#')
    {
        return NULL;
    }
    else{
        p = (Tree *)malloc(sizeof(Tree));
        p->data = ch;
        p->Lift = create();
        p->Right = create();
        return (p);
    }
}

/*二级指针建立二叉树*/
void crea(Btree *root)
{
    char ch;
    ch = getchar();
    printf("%c",ch);
    if(ch=='#')
    {
        (*root) =  NULL;
    }
    else
    {
        *root=(Tree *)malloc(sizeof(Tree));
        (*root)->data = ch;
        if((*root)==NULL)
        {
            exit(0);
        }
        crea((&(*root)->Lift));
        crea((&(*root)->Right));
    }
}


/*先序递归遍历,根左右*/
void digui_front(Btree root)
{
    if(root == NULL)
    {
        return;
    }
    else
    {
        printf("%c\t",root->data);
        digui_front(root->Lift);
        digui_front(root->Right);
    }
}

/*先序递归遍历,左根右*/
void digui_inorder(Btree root)
{
    if(root)
    {
        digui_inorder(root->Lift);
        printf("%c\t",root->data);
        digui_inorder(root->Right);
    }
}

/*后序递归遍历,左右根*/
void digui_postorder(Btree root)
{
    if(root)
    {
        digui_postorder(root->Lift);
        digui_postorder(root->Right);
        printf("%c\t",root->data);
    }
}

/*非递归先序遍历*/
void undigui_front(Btree root)
{
    sepstack *stack;
    Btree p = root;
    stack = init(stack);
    while(p!=NULL || (!empty(stack)))
    {
        while(p!=NULL)
        {
            /*从根节点开始遍历,有就输出该节点,输出之后再入栈*/
            printf("%c\t",p->data);
            push(stack,p);
            p = p->Lift;
        }
        pop(stack,&p);
        p = p->Right;
    }
    printf("\n");
}
/*非递归中序遍历*/
void undigui_inorder(Btree root)
{
    sepstack *stack;
    Btree p = root;
    stack = init(stack);
    while(p!=NULL || (!empty(stack)))
    {
        while(p)
        {
            push(stack,p);
            p = p->Lift;
        }
        /*此时P处于空指针,需要从栈中拿出上一个节点*/
        pop(stack,&p);
        printf("%c\t",p->data);
        p = p->Right;
    }
    printf("\n");
}

void undigui_postorder(Btree root)
{
    sepstack *stack;
    stack = init(stack);
    Btree p = root;
    Btree q = NULL;
    while(p!=NULL || (!empty(stack)))
    {
        while(p)
        {
            push(stack,p);
            p = p->Lift;
        }
        gettop(stack,&p);
        if(p->Right==NULL || p->Right==q)
        {
            pop(stack,&p);
            printf("%c\t",p->data);
            q = p;
            p = NULL;
        }
        else{
            p = p->Right;
        }
    }
    printf("\n");
}
int main()
{
    Btree *p;
    p = (Btree *)malloc(sizeof(Tree));
    crea(p);
    printf("\n先序遍历:\n");
    undigui_front(*p);
    digui_front(*p);
    printf("\n中序遍历:\n");
    undigui_inorder(*p);
    digui_inorder(*p);
    printf("\n后序遍历:\n");
    undigui_postorder(*p);
    digui_postorder(*p);
    printf("\n");
    return 0;
}



总结

二叉树的遍历通过根节点依次找到下面的节点,递归遍历应该很好理解,先序中序后序的遍历都是一个操作,每次以左孩子和右孩子作为根节点往下遍历。
非递归遍历通过栈的操作来实现。首先先序遍历的顺序是根左右,从根开始,遇到根节点就可以访问该节点的存储值,然后依次返回左子树,并把左子树经历过的节点都压入栈中,访问左子树到底后,依次弹出栈顶元素,访问该元素的右子树,直到栈空并且下一个孩子节点为空时访问结束。中序遍历的顺序是左根右,和先序遍历一样,同样是访问左子树,依次入栈,但是此时不能访问所在节点的存储值,是要把左遍历完之后才能访问,所以依次入栈,左子树结束后,再依次弹出栈顶元素并且访问该元素的存储值,再访问该栈顶元素的右子树。后序遍历比较麻烦,因为要重复访问根节点两次,而且需要一个标记值去标记该节点所在的右孩子是否被访问过。因为后序遍历的顺序是左右根,右节点在第二次访问,所以要判断右孩子是否访问过,若访问过就访问根节点,若没有就得从右子树开始遍历。所以从根节点往下往左子树遍历的时候,遍历到底,并且入栈,然后取栈顶元素(并不出栈),来判断栈顶元素的右子树不为空,并且标值不为右孩子的时候才可以往右遍历。若果不满足以上两个条件,那么就可以输出根节点或者是右孩子节点,及弹出栈顶元素,并且访问该元素的存储值。

猜你喜欢

转载自blog.csdn.net/qq_36573828/article/details/78574164