C语言进行二叉树的递归遍历和非递归遍历

#include <stdio.h>
#include <stdlib.h>
typedef struct{
    struct TreeNode *left;
    struct TreeNode *right;
    char val;
    int visitCount;

}TreeNode;




typedef struct {
    TreeNode *base;
    TreeNode *top;
    int size;
    int currentSize;
}Stack;



Stack* initStack(){

    Stack *stack;
    stack = (Stack*)malloc(sizeof(Stack));
    if(!stack) exit(0);
    stack->base = (TreeNode*)malloc(sizeof(TreeNode)*20);
    if(!stack->base) exit(0);
    stack->top = stack->base;
    stack->size = 20;
    stack->currentSize = 0;
    return stack;



}


TreeNode* pop(Stack *stack){
    if(stack->currentSize<=0)
        return NULL;
    else
        stack->currentSize--;
        return (--stack->top);
}


void push(Stack *stack,TreeNode node){

    if(stack->top-stack->base>=stack->size){

         stack->base = (TreeNode*)realloc(stack->base,sizeof(TreeNode)*(stack->size+20));
         if(!stack->base) exit(0);
         stack->top =stack->size+stack->base;
         stack->size +=20;
    }

    stack->currentSize++;
    *(stack->top)=node;
  ;
     stack->top++;





}


TreeNode* peek(Stack *stack){
    if(stack->base==stack->top)
        return NULL;
    else
        return (stack->top-1);


}

int size(Stack *stack){

    return stack->currentSize;
}


TreeNode* createTree(){
    TreeNode *root;

    if(!root) exit(0);
    char ch;
    printf("输入该节点的值 回车退出该节点的输入\n");
    if((ch=getchar())!='\n'){
        root = (TreeNode*)malloc(sizeof(TreeNode));
        root->val = ch;
        root->visitCount = 0;
        fflush(stdin);
        root->left = createTree();
        root->right = createTree();

    }else{
        printf("该节点作废\n");
        return NULL;
    }




    return root;


}

void work(TreeNode *node){

    printf("node's val = %c \n",node->val);

}


void visitRecursion_mid(TreeNode *root){
    if(root==NULL)
        return;
    visitRecursion_mid(root->left);
    work(root);
    visitRecursion_mid(root->right);



}


void visitRecursion_before(TreeNode *root){
    if(root==NULL)
        return;
    work(root);
    visitRecursion_before(root->left);

    visitRecursion_before(root->right);



}




void visitRecursion_after(TreeNode *root){
    if(root==NULL)
        return;
    visitRecursion_after(root->left);

    visitRecursion_after(root->right);
    work(root);


}


void visitIteration_mid(TreeNode *root){
    Stack *stack = initStack();
    push(stack,*root);
    TreeNode *temp = root->left;
    while(size(stack)>0||temp){
        while(temp){
            //向左遍历到底
            push(stack,*temp);

            temp = temp->left;

        }

        //退栈 向右遍历

        temp = pop(stack);
        work(temp);
        while(!temp->right&&size(stack)>0){
            temp = pop(stack);
            work(temp);
        }

        temp = temp->right;



    }

}


void visitIteration_before(TreeNode *root){
    if(!root)return;
    work(root);
    Stack *stack = initStack();
    push(stack,*root);
    TreeNode *temp = root->left;
    while(size(stack)>0||temp){
        while(temp){
            //向左遍历到底
            push(stack,*temp);
            work(temp);
            temp = temp->left;

        }

        //退栈 向右遍历

        temp = pop(stack);

        while(!temp->right&&size(stack)>0){
            temp = pop(stack);

        }

        temp = temp->right;



    }

}


//总体思路:
根节点先入栈 向左遍历到底 其中国条件为该节点为空并且是之前没有访问过的 (否则会造成退栈时再次左子树入栈)
然后退栈,设置个临时变量flag指向栈顶元素的右子树
如果右子树为空 则说明该栈顶元素temp节点没有子节点 可以访问 或者该节点已经在之前访问过一次了 那本次也可以访问
否则即当该栈顶元素temp存在右子树并且是第一次访问
即对把该节点temp和该节点的右子树节点flag再次入栈 并且设置访问过的标记
然后令temp指向flag的左子树再次进入循环 (就相当于把flag的节点当作了root进行了递归操作)




void visitIteration_after(TreeNode *root){

    if(!root)return;
    Stack *stack = initStack();
    push(stack,*root);

    TreeNode *temp = root->left;
    TreeNode *flag;
    while(size(stack)>0){
        while(temp&&temp->visitCount ==0){
            //向左遍历到底
            push(stack,*temp);

            temp = temp->left;

        }

        temp = pop(stack);
        flag = temp->right;


            //flag为NULL或者之前已经访问过该节点一次 则直接访问
        if(!flag||temp->visitCount == 1){
            work(temp);
            temp->visitCount = 1;//设置访问记号
        }else{//flag为真并且之前没有访问过 则取flag的左子树继续遍历 并设置访问记号
            temp->visitCount = 1;//设置访问记号
            push(stack,*temp);
            push(stack,*flag);
            temp = flag->left;
        }


    }



}





int main()
{
    TreeNode * root = createTree();
    visitIteration_before(root);
    printf("-------------\n");
    visitRecursion_before(root);
    printf("Hello world!\n");
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值