二叉树:创建,遍历(递归、非递归、层次)

本文介绍了一种二叉树的创建及多种遍历方法,包括递归与非递归方式实现的前序、中序、后序遍历,以及层次遍历。通过具体的C语言代码示例详细展示了每种遍历的过程。

废话不多说,直接堆代码。

Tree.h

typedef struct TreeNode{
    struct TreeNode* lchild;
    struct TreeNode* rchild;
    char data;
}TreeNode;

main.cpp

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

#include"Tree.h"

TreeNode* LCreateTree();                            //创建二叉树

void FrontTraversal(TreeNode* t, int &numOfNode);   //前序遍历二叉树 递归
void MidTraversal(TreeNode* t);                     //中序遍历二叉树
void BackTraversal(TreeNode* t);                    //后序遍历二叉树

void FrontTraversal_s(TreeNode* t, int numOfNode);  //前序遍历二叉树 非递归
void MidTraversal_s(TreeNode* t, int numOfNode);    //中序遍历二叉树
void BackTraversal_s(TreeNode* t, int numOfNode);   //后序遍历二叉树

void LevelTraversal(TreeNode* t, int numOfNode);    //层次遍历二叉树



int main() {

    TreeNode* root;
    root = LCreateTree();               //前序创建二叉树

    int numOfNode = 0;                  //记录二叉树结点个数

    //递归方法
    FrontTraversal(root, numOfNode);    //前序遍历二叉树
    MidTraversal(root);                 //中序遍历二叉树
    BackTraversal(root);                //后序遍历二叉树
    printf("%d\n", numOfNode);

    //非递归方法
    FrontTraversal_s(root, numOfNode);  //前序遍历二叉树
    MidTraversal_s(root, numOfNode);    //中序遍历二叉树
    BackTraversal_s(root, numOfNode);   //后序遍历二叉树

    LevelTraversal(root,numOfNode); //层次遍历二叉树

    return 0;
}


TreeNode* LCreateTree() {           //前序遍历二叉树
    char c;
    TreeNode* t;
    c = getchar();
    if (c == '#')
        return NULL;
    else {
        t = (TreeNode*)malloc(sizeof(TreeNode));
        t->data = c;
        t->lchild = LCreateTree();
        t->rchild = LCreateTree();
    }
    return t;
}

void FrontTraversal(TreeNode* t, int &numOfNode) {
    TreeNode* p = t;
    if (p) {
        printf("%c ", p->data);
        numOfNode++;
        FrontTraversal(p->lchild, numOfNode);
        FrontTraversal(p->rchild, numOfNode);
    }
}

void MidTraversal(TreeNode* t) {
    TreeNode* p = t;
    if (p) {
        MidTraversal(p->lchild);
        printf("%c ", p->data);
        MidTraversal(p->rchild);
    }
}

void BackTraversal(TreeNode* t) {
    TreeNode* p = t;
    if (p) {
        BackTraversal(p->lchild);
        BackTraversal(p->rchild);
        printf("%c ", p->data);
    }
}

void FrontTraversal_s(TreeNode* t, int numOfNode) {     //分治,对于每一个结点,先输出它的记录
    TreeNode* stack;                                    //然后压入右孩子,最后压入左孩子
    stack = (TreeNode*)malloc(sizeof(TreeNode) * numOfNode);
    int top = -1;
    TreeNode* p;
    p = (TreeNode*)malloc(sizeof(TreeNode));
    if (t != NULL) {
        top++;
        stack[top] = *t;
        while (top > -1) {
            *p = stack[top];
            top--;
            printf("%c ", p->data);
            if (p->rchild) {                //压入右结点
                top++;
                stack[top] = *(p->rchild);
            }
            if (p->lchild) {                //压入左结点
                top++;
                stack[top] = *(p->lchild);
            }
        }
    }
    printf("\n");
    free(stack);
    free(p);
}

void MidTraversal_s(TreeNode* t, int numOfNode) {   //分治,先遍历到最左的结点,输出它的记录,出栈 ---1
    TreeNode* stack;                                //然后看它有没有右子树,有重复1,没有就再取栈顶结点。
    stack = (TreeNode*)malloc(sizeof(TreeNode) * numOfNode);
    TreeNode* p;
    p = (TreeNode*)malloc(sizeof(TreeNode) * numOfNode);
    int top = -1;
    if (t) {
        p = t;
        while (top > -1 || p) {
            while (p) {         //遍历到最左侧,同时不停压栈---1
                top++;
                stack[top] = *p;
                p = p->lchild;
            }
            if (top > -1) {
                p = &stack[top];
                top--;
                printf("%c ", p->data);
                p = (p->rchild);    //右子树重复1过程
            }
        }
    }
    printf("\n");
    free(stack);
    free(p);
}
void BackTraversal_s(TreeNode* t, int numOfNode) {  //首先要遍历到最左侧,决定一个结点是否输出的是右孩子---1
    TreeNode* stack[10];                            //如果右孩子为NULL,由于该结点是最左侧(或则它的左子树已经输出)的结点,所以直接输出
    TreeNode* p = NULL;                             //如果右孩子不为NULL,要判断右孩子是否已经输出,如果是,则输出,否,则让右孩子经历步骤1
    TreeNode* b = t;
    int top = -1;
    int sign;
    if (b) {
        do {
            while (b) {     //遍历到最左侧
                top++;
                stack[top] = b;
                b = b->lchild;
            }
            p = NULL;
            sign = 1;
            while (top != -1 && sign) {     //判断右孩子
                b = stack[top];
                if (b->rchild == p) {       //右子树已经输出
                    printf("%c ", b->data);
                    top--;
                    p = b;
                }
                else {                      //右孩子还没有遍历
                    b = b->rchild;
                    sign = 0;
                }
            }
        } while (top > -1);
    }
    printf("\n");

}

void LevelTraversal(TreeNode* t, int numOfNode) {       //借助队列层次输出二叉树
    TreeNode *queue;
    queue = (TreeNode*)malloc(sizeof(TreeNode) * numOfNode);
    int num = 1;                                        //每次加入队列的结点个数
    int count = 0;                                      //每次输出层次的起点
    int size = 0;                                       //中间记录变量
    TreeNode *p = t;
    if (p) {
        queue[count] = *p;
        while(num > 0) {
            for (int j = count; j < count + num; j++)   //从层次的起点输出num个结点的记录
                printf("%c ", queue[j].data);
            printf("\n");
            TreeNode temp;
            for (int i = count; i < count + num;) {     //输出完一层后,得压入新的一层结点
                temp = queue[i];
                if (temp.lchild) {                      //压入已输出层结点的左孩子
                    queue[count + num + size] = *temp.lchild;
                    size++;
                }
                if (temp.rchild) {                      //压入已输出层结点的右孩子
                    queue[count + num + size] = *temp.rchild;   
                    size++;
                }
                i++;    
            }
            count += num;                               //层次起点更换
            num = size;                                 //新层次的结点数更换
            size = 0;                                   //临时记录归0
        }
    }
}

这里写图片描述

这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值