zoukankan      html  css  js  c++  java
  • 第四章_树(遍历二叉树)

    遍历二叉树,最常用的递归实现遍历二叉树,但我们还可以用非递归和层次遍历树的方法,这里就要用到栈和队列的一些知识,现在就让我们把这两个结合起来一起用。

    这个是非递归中序遍历二叉树,非递归我们可以用栈的思想,中序遍历的时候,我们可以先一直把左子树全装栈里面,然后当装完左子树的结点后,我们就出栈并输出,然后跳到右子树,依次循环,对应的代码如下:

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

    typedef struct TNode {
        int data;
        struct TNode *lchild;//left child
        struct TNode *rchild;//right child
    }TNode,*Tree;

    typedef struct SNode {
        Tree data;
        int top;
        int maxsize;
    }SNode,*Stack;

    void InitStack (Stack *S);//初始化栈
    void CreateTree (Tree *T);//创建一个二叉树。
    void Pre (Tree T);//先序遍历二叉树。
    void Pre1 (Tree T);//非递归中序遍历二插树。
    void Push (Stack S, Tree T);//进栈。
    Tree Pop (Stack S);//出栈。
    int IsFull (Stack S);//判断是否为满。
    int IsEmpty (Stack S);//判断是否为空。

    int main ()
    {
        Tree T;
        CreateTree(&T);//传入T的地址。
        Pre(T);
        Pre1 (T);
        return 0;
    }

    void Pre1 (Tree T)
    {
        Stack S;
        InitStack(&S);
        while(T || !IsEmpty (S)) {
                while (T) {
                    Push(S,T);
                    T = T->lchild;//先装完左子树的全部结点。
                }

                if(!IsEmpty(S)) {//装完后,我们就可以出栈了。
                    T = Pop (S);
                    printf("%d ",T->data);//输出对应的结点数据。
                    T = T->rchild;//跳到右子树。
                }
        }
    }
    void InitStack (Stack *S)
    {
        *S = (SNode*) malloc(sizeof(SNode));
        (*S)->top = 0;
        (*S)->maxsize = 10;
        (*S)->data = (TNode*)malloc(sizeof(TNode)*(*S)->maxsize);
    }

    int IsFull( Stack S)
    {
        return (S->top == S->maxsize - 1);
    }

    int IsEmpty (Stack S)
    {
        return (S->top == 0);
    }

    void Push (Stack S, Tree T)
    {
        if(IsFull(S)) {
            printf("The stack is Full ");
        }else {
            TNode *temp;
            temp = T;
            S->data[S->top] = *temp;
            
            S->top++;
        }
    }

    Tree Pop (Stack S)
    {
        if(IsEmpty (S)) {
            printf("The stack is empty ");
        }else {
            Tree T;
            S->top--;
            T = &(S->data[S->top]);
            return T;
        }
    }
    void Pre (Tree T)
    {
        if (T) {
            printf("%d ",T->data);
            Pre(T->lchild);
            Pre(T->rchild);
        }
    }
    void CreateTree (Tree *T)
    {
        *T = (TNode*) malloc(sizeof(TNode));
        int data;
        scanf("%d",&data);
        if( data == -1) {
            *T = NULL;
        }else {
            (*T)->data = data;
            CreateTree(&(*T)->lchild);
            CreateTree(&(*T)->rchild);
        }
    }

    下面就是层次遍历,层次遍历就是利用队列的思想,先进先出,以树的第一个为起点,开始输出,输出后,若有左右子树,则进队,若没有,则依次出队,再入队,依次循环。直到队列为空。

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

    typedef struct TNode {
        int data;
        struct TNode *lchild;
        struct TNode *rchild;
    }TNode,*Tree;

    typedef struct QNode {
        Tree data;
        int top;
        int base;
        int maxsize;
    }QNode,*Queue;

    void InitQueue (Queue *q);//初始化队列。
    void En (Queue q, Tree T);//进队。
    Tree De (Queue q);//出队。
    int IsFull (Queue q);//判断是否为满。
    int IsEmpty (Queue q);//判断是否为空。
    void CreateTree (Tree *T);//创建一颗二插树。
    void Level (Tree T);//层次遍历二叉树。

    int main ()
    {
        Tree T;
        CreateTree(&T);
        Level(T);

        return 0;
    }


    void CreateTree (Tree *T)
    {
        *T = (Tree) malloc (sizeof(TNode));
        int data;
        scanf("%d",&data);
        if (data == -1 ) {
            *T = NULL;
        }else {
            (*T)->data = data;
            CreateTree(&(*T)->lchild);
            CreateTree(&(*T)->rchild);
        }
    }

    void Level (Tree T)
    {
        Queue q;
        InitQueue (&q);
        En(q,T);
        Tree temp;
        while(!IsEmpty(q)) {//队列为空则停止。
            temp = De(q);//出队。
            printf("%d ",temp->data);
            if(temp->lchild) En(q,temp->lchild);//依次装入左右子树。
            if(temp->rchild) En(q,temp->rchild);
        }
    }

    void InitQueue (Queue *q)
    {
        (*q) = (QNode*) malloc(sizeof(QNode));
        (*q)->top = (*q)->base = 0;
        (*q)->maxsize = 10;
        (*q)->data = (Tree) malloc(sizeof(TNode) * (*q)->maxsize);
    }

    int IsFull(Queue q)
    {
        return ((q->top + 1) % (q->maxsize - 1) == q->base);
    }

    int IsEmpty (Queue q)
    {
        return (q->base == q->top);
    }

    void En (Queue q, Tree T)
    {
        if (IsFull(q)) {
            printf("The queue is full! ");
        }else {
            TNode *temp;
            temp = T;
            q->data[q->top] = *temp;
            q->top = (q->top + 1) % (q->maxsize -1 );

        }
    }


    Tree De (Queue q)
    {
        if(IsEmpty(q)) {
            printf("The queue is empty! ");
        }else {
            Tree T;
            T = &(q->data[q->base]);
            q->base = (q->base + 1) % (q->maxsize - 1);
            return T;
        }
    }

    这就是树的一些遍历技巧,我们要能掌握并灵活的运用,若读者有不懂的,可以留言,期待下一次!

  • 相关阅读:
    AcWiing 翻硬币
    AcWing 飞行员兄弟 二进制枚举
    AcWing 费解的开关 二进制枚举
    vue发送短信逻辑
    使用celery异步发送短信
    celery配置与基本使用
    celery原理与组件
    短信验证接口
    图片验证码接口
    编写注册接口
  • 原文地址:https://www.cnblogs.com/ranyang/p/13832982.html
Copyright © 2011-2022 走看看