ranyang

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

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

#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\n");
    }else {
        TNode *temp;
        temp = T;
        S->data[S->top] = *temp;
        
        S->top++;
    }
}

Tree Pop (Stack S)
{
    if(IsEmpty (S)) {
        printf("The stack is empty\n");
    }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!\n");
    }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!\n");
    }else {
        Tree T;
        T = &(q->data[q->base]);
        q->base = (q->base + 1) % (q->maxsize - 1);
        return T;
    }
}

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

相关文章: