二叉树的基本操作(一)

这篇博客介绍了二叉树的基本操作,包括创建、前序、中序、后序遍历,统计节点数、叶子节点数,打印叶子节点,计算树的深度以及按树状打印。通过示例代码详细阐述了每种操作的实现,并提供了两种计算叶子节点数和树深度的方法。此外,还展示了复制二叉树的代码以及在实际运行中可能出现的问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

二叉树的基本操作
1:创建
2:前序,中序,后序遍历
3:统计结点数
4:统计叶子结点数
5:打印叶子结点
6:计算二叉树的深度
7:按树状打印二叉树
8:复制二叉树

下面是具体代码和解析

#include <stdio.h>
#include<stdlib.h>
typedef  char Elemtype;

int countall=0; //存储结点数
int leafcount=0; //存储叶子结点数
int depth=0;  //存储二叉树深度

typedef struct node{
    Elemtype data;
    struct node *lchild,*rchild;
}BiTNode,*BiTtree;


//1:创建二叉树
void createTree(BiTNode **root)
{

    Elemtype data;
    scanf("%c",&data);
    if(data == '#')
    {
        (*root)=NULL;
    }

    else
    {
        *root = (BiTNode *)malloc(sizeof(BiTNode));
        if((*root) == NULL)
        {
            printf("分配空间失败!\n");
            exit(0);
        }
        (*root)->data = data;
        createTree(&((*root)->lchild));
        createTree(&((*root)->rchild));
    }

}
//或
//void creatBiTree(BiTtree *root){
//    Elemtype ch;
//    scanf("%c",&ch);
//    if(ch == '@'){
//        (*root)=NULL;
//    } else
//        {
//            *root = (BiTNode *)malloc(sizeof(BiTNode));
//            if((*root) == NULL)
//            {
//                printf("分配空间失败!\n");
//                exit(0);
//            }
//            (*root)->data = ch;
//            creatBiTree(&((*root)->lchild));
//            creatBiTree(&((*root)->rchild));
//        }
//}

//2:先序遍历
void preOrder(BiTtree root){
    if(root!=NULL){
        printf("%c",root->data);
        preOrder(root->lchild);
        preOrder(root->rchild);
    }
}

//2:中序遍历
void inOrder(BiTtree root){
    if(root!=NULL){
        inOrder(root->lchild);
        printf("%c",root->data);
        inOrder(root->rchild);
    }
}

//3:后序遍历
void postOrder(BiTtree root){
    if(root!=NULL){
        postOrder(root->lchild);
        postOrder(root->rchild);
        printf("%c",root->data);
    }
}

//4:统计结点数
void countAll(BiTtree root){
    if(root!=NULL){
        countall++;
        countAll(root->lchild);
        countAll(root->rchild);
    }
}

//5:统计叶子结点 方法一
void leafCount1(BiTtree root){
    if(root!=NULL){
        
        if(root->lchild==NULL&&root->rchild==NULL)leafcount++;
        leafCount1(root->lchild);
        leafCount1(root->rchild);
    }
}

//6:统计叶子节点 方法二:分治算法,空0,1个节点返回1,否则左右叶子结点相加
int leafCount2(BiTtree root){
    int hl,hr;
    if(root==NULL)
        return 0;
    else if((root->lchild==NULL)&&(root->rchild==NULL))return 1;
    else{
        hl=leafCount2(root->lchild);
        hr=leafCount2(root->rchild);
    }
    return hl+hr;
}

//7:打印叶子结点
void printLeaf(BiTtree root){
    if(root!=NULL){
        if((root->lchild==NULL)&&(root->rchild==NULL))
            printf("%c",root->data);
        printLeaf(root->lchild);
        printLeaf(root->rchild);
    }
}

//8:计算二叉树的深度(方法一):后序遍历求深度,递归
int bitreeDepth1(BiTtree root){
    int hl,hr;
    if(root==NULL)return 0;
    else if (root!=NULL){
        hl=bitreeDepth1(root->lchild);
        hr=bitreeDepth1(root->rchild);
    }
    return hl>hr?hl+1:hr+1;
}

//9:计算二叉树的深度(方法二):
//前序遍历(二叉树的深度为结点层次的最大值)设根结点为第一层的结点,所有h层结点的左右孩子结点在h+1层,故可以遍历每个节点的层次,其中最大值是二叉树的高度。
void bitreeDepth2(BiTtree root,int h){
    if(root!=NULL){
        if(h>depth) depth=h;
        bitreeDepth2(root->lchild,h+1);
        bitreeDepth2(root->rchild,h+1);
    }
}

//10:按树状打印二叉树
//二叉树的横向显示应是竖向显示的90度旋转
//采用‘逆中序’遍历,所以横向显示算法为先右子树,再根结点,再左子树的RDL结构
//输出格式里,结点的左右位置与结点的层深有关,故算法中设置了一个表示当前根结点层深的参数
//来控制输出结点的左右位置,每当递归进层时深度加1。这些操作应在访问根结点时实现
void printBitree(BiTtree root,int h){
    if(root!=NULL){
        printBitree(root->rchild, h+1);
        for(int i=0;i<h;i++)
        printf("--");
        printf("%c\n",root->data);
        printBitree(root->lchild, h+1);
    }
}

BiTtree CopyBTree(BiTtree root){
    BiTtree p,lchild,rchild;
    if(root==NULL)
        return NULL;
    lchild=CopyBTree(root->lchild);
    rchild=CopyBTree(root->rchild);
    p=(BiTtree)malloc(sizeof(BiTNode));
    p->data=root->data;
    p->lchild=root->lchild;
    p->rchild=root->rchild;
    return p;
}

int main(){
    BiTNode *root;
    printf("请输入二叉树数据:(#代表NULL)\n");
    createTree(&root);
    printf("先序遍历结果:\n");
    preOrder(root);
    printf("\n中序遍历结果:\n");
    inOrder(root);
    printf("\n后序遍历结果:\n");
    postOrder(root);
    
    countAll(root);
    printf("\n结点总数为:%d\n",countall);
    leafCount1(root);
    printf("\n叶子结点数为(法一):%d\n",leafcount);
    int a=leafCount2(root);
    printf("\n叶子结点数为(法二):%d\n",a);
    
    bitreeDepth2(root, 1);
    printf("\n树的高度(法一):%d\n",bitreeDepth1(root));
    printf("\n树的高度(法二):%d\n",depth);
    
   
    if(CopyBTree(root))
        printf("\n复制二叉树成功!\n");
    else
        printf("\n复制失败!\n");
    
    printf("\n叶子结点是:\n");
    printLeaf(root);
    printf("\n树状打印二叉树\n");
    printBitree(root, 1);
    
    
}

运行结果:
在这里插入图片描述
当听完讲解你或许懂了,但其实不自己亲手写一遍,是不会发现其中的问题的。

比如创建二叉树时为什么要用指针的指针?
递归的过程你是否能写得出来?
具体的问题我会在下篇《二叉树操作出现的问题》提到。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值