二叉树的基本操作(C语言)

要介绍二叉树的基本操作,首先介绍一下二叉树的结点:

typedef struct node
{
    char data;
    struct node *lchild;
    struct node *rchild;
}BiTNode;

 包括该结点的值、指向左孩子的指针和指向右孩子的指针。

1.先序构造二叉树

BiTNode *creatBiTree()
{
    char k;
    scanf("%c",&k);
    if(k=='#')
        return NULL;
    BiTNode *T=(BiTNode *)malloc(sizeof(BiTNode));
    T->data=k;
    T->lchild=creatBiTree();
    T->rchild=creatBiTree();
    return T;
}

先序构造采用递归的算法,构造完父结点再去构造父结点的左孩子,构造完父结点的左孩子再去构造父结点的右孩子,最后返回根节点的地址。这样无论哪个节点,构造的顺序都是父结点->左孩子->右孩子,保证按照先序的顺序构造二叉树。

2.二叉树的遍历

1)先序遍历

void xianxu(BiTNode *T)
{
    if(T)
    {
        printf("%2c",T->data);
        xianxu(T->lchild);
        xianxu(T->rchild);
    }
}

2)中序遍历

void zhongxu(BiTNode *T)
{
    if(T)
    {
        zhongxu(T->lchild);
        printf("%2c",T->data);
        zhongxu(T->rchild);
    }
}

3)后序遍历

void houxu(BiTNode *T)
{
    if(T)
    {
        houxu(T->lchild);
        houxu(T->rchild);
        printf("%2c",T->data);
    }
}

三种遍历算法都使用了递归,仅仅是访问结点内容这部分代码的位置不同。先序遍历肯定要先访问这个结点的内容,中序遍历肯定是在访问了该结点的左子树后再访问这个结点的内容,后序遍历肯定是左右子树都访问完再访问这个结点的内容。

3.统计叶子结点的个数

int countLeaf(BiTNode *T)
{
    if(T==NULL)
        return 0;
    else if(T->lchild==NULL&&T->rchild==NULL)
        return 1;
    else
        return countLeaf(T->lchild)+countLeaf(T->rchild);
}

 如果一棵树为空树,肯定一个叶子结点也没有,返回0;如果一个结点的左孩子为空右孩子也为空,那么这个结点一定是叶子结点,返回1;如果是其他的情况,叶子结点的个数无非是左子树叶子结点的个数+右孩子叶子结点的个数。层层递归,最后返回的就是二叉树叶子结点的个数。

4.计算二叉树的深度

int countDepth(BiTNode *T)
{
    if(T==NULL)
        return 0;
    else if(T->lchild==NULL&&T->rchild==NULL)
        return 1;
    else
    {
        int depth1=countDepth(T->lchild)+1;
        int depth2=countDepth(T->rchild)+1;
        return depth1>depth2?depth1:depth2;
    }
}

如果一棵树为空树,则没有深度可言,返回0;如果一个结点的左孩子为空右孩子也为空,则该结点肯定是叶子结点,该结点的下面不再有结点,对该结点而言深度就是1; 如果是其他情况,则要先求左子树的深度和右子树的深度,左子树的深度+1就是该结点去掉右子树时的深度,右子树的深度+1就是该结点去掉左子树时的深度,深度肯定取大的,所以返回的是左子树深度+1和右子树深度+1中大的那一个。

5.销毁一棵二叉树

void destroy(BiTNode *T)
{
    if(T)
    {
        destroy(T->lchild);
        destroy(T->rchild);
        free(T);
    }
}

对于一个结点,先销毁左子树,再销毁右子树,最后释放该结点的内存。注意一定要最后释放该结点的内存,因为左子树和右子树都是需要该结点中指向左孩子的指针和指向右孩子的指针索引的,释放了该结点的内存就找不到左子树和右子树了,就造成了内存泄漏。 

写好上述操作函数之后,下面在主函数中进行测试:

int main()
{
    printf("先序构造一棵二叉树(左/右孩子为空用'#'表示):");
    BiTNode *T=creatBiTree();
    printf("先序遍历这棵二叉树:");
    xianxu(T);
    printf("\n");
    printf("中序遍历这棵二叉树:");
    zhongxu(T);
    printf("\n");
    printf("后序遍历这棵二叉树:");
    houxu(T);
    printf("\n");
    printf("这棵树叶子结点的个数:%d\n",countLeaf(T));
    printf("这棵树的深度:%d\n",countDepth(T));
    destroy(T);
    return 0;
}

测试结果:

欢迎大家关注/订阅我的微信公众号Code Art Online,我会在我的公众号分享个人见闻,发现生活趣味;这里不仅有0和1,还有是诗和远方↓↓↓

  • 48
    点赞
  • 263
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
以下是二叉树基本操作的C语言实现: ```c #include <stdio.h> #include <stdlib.h> //定义二叉树结构体 typedef struct TreeNode { int data; struct TreeNode* left; struct TreeNode* right; } TreeNode; //创建二叉树节点 TreeNode* createNode(int data) { TreeNode* node = (TreeNode*)malloc(sizeof(TreeNode)); node->data = data; node->left = NULL; node->right = NULL; return node; } //创建二叉树 TreeNode* createTree() { int data; scanf("%d", &data); if (data == -1) { //输入-1表示该节点为空 return NULL; } TreeNode* root = createNode(data); printf("请输入%d的左子节点:", data); root->left = createTree(); printf("请输入%d的右子节点:", data); root->right = createTree(); return root; } //先序遍历 void preorderTraverse(TreeNode* root) { if (root == NULL) { return; } printf("%d ", root->data); preorderTraverse(root->left); preorderTraverse(root->right); } //中序遍历 void inorderTraverse(TreeNode* root) { if (root == NULL) { return; } inorderTraverse(root->left); printf("%d ", root->data); inorderTraverse(root->right); } //后序遍历 void postorderTraverse(TreeNode* root) { if (root == NULL) { return; } postorderTraverse(root->left); postorderTraverse(root->right); printf("%d ", root->data); } //层序遍历 void levelorderTraverse(TreeNode* root) { if (root == NULL) { return; } TreeNode* queue[1000]; int front = 0, rear = 0; queue[rear++] = root; while (front < rear) { TreeNode* node = queue[front++]; printf("%d ", node->data); if (node->left) { queue[rear++] = node->left; } if (node->right) { queue[rear++] = node->right; } } } //插入节点 void insertNode(TreeNode* root, int data) { if (root == NULL) { return; } if (root->left == NULL) { root->left = createNode(data); } else if (root->right == NULL) { root->right = createNode(data); } else { //如果当前节点的左右子节点都不为空,则递归插入左右子树 insertNode(root->left, data); insertNode(root->right, data); } } //删除节点 void deleteNode(TreeNode* root, int data) { if (root == NULL) { return; } if (root->left != NULL && root->left->data == data) { free(root->left); root->left = NULL; } else if (root->right != NULL && root->right->data == data) { free(root->right); root->right = NULL; } else { //如果当前节点的左右子节点都不为空,则递归删除左右子树 deleteNode(root->left, data); deleteNode(root->right, data); } } //查找节点 TreeNode* searchNode(TreeNode* root, int data) { if (root == NULL) { return NULL; } if (root->data == data) { return root; } TreeNode* left = searchNode(root->left, data); TreeNode* right = searchNode(root->right, data); if (left != NULL) { return left; } if (right != NULL) { return right; } return NULL; } //修改节点 void modifyNode(TreeNode* node, int newData) { if (node == NULL) { return; } node->data = newData; } int main() { printf("请输入二叉树的根节点:"); TreeNode* root = createTree(); printf("先序遍历:"); preorderTraverse(root); printf("\n中序遍历:"); inorderTraverse(root); printf("\n后序遍历:"); postorderTraverse(root); printf("\n层序遍历:"); levelorderTraverse(root); printf("\n插入节点5后:"); insertNode(root, 5); levelorderTraverse(root); printf("\n删除节点5后:"); deleteNode(root, 5); levelorderTraverse(root); printf("\n查找节点3:"); TreeNode* node = searchNode(root, 3); if (node != NULL) { printf("找到了,节点的值为%d\n", node->data); } else { printf("没找到\n"); } printf("修改节点3的值为10后:"); modifyNode(node, 10); levelorderTraverse(root); return 0; } ``` 这段代码实现了二叉树的创建、遍历、插入、删除、查找和修改等基本操作

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值