二叉树c语言实现 bittree.h 和 bittree.h

bittree.h 文件

#ifndef _BIT_TREE_H_
#define _BIT_TREE_H_
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//树的定义是递归定义的,节点下面又拆分为左子树和右子树
//树是由节点组成,除了叶子节点,其他节点又是相对的根节点,
//相对的根节点下有相对的左右子树

//树的遍历的本质就是走一圈,每一个非叶子节点就是相对的根节点,都经过3次
//第一次访问为先序,第二次访问为中序,第三次访问为后序
#ifndef bool
#define bool int
#define true 1
#define false 0
#endif

//数的头首地址就可以用第一个节点的地址表示
typedef struct BitNode
{
    int data;
    struct BitNode *lchild,*rchild;
}BitNode,*BitTree;

#ifdef __cplusplus
extern "C"{
#endif

extern void preOrder(BitNode* root);
extern void midOrder(BitNode* root);
extern void lastOrder(BitNode* root);
extern void countLeafNodes(BitNode* root,int* sum);
extern int getDepth(BitNode* root);
extern BitNode* copyBitTree(BitNode* root);

#ifdef __cplusplus
}
#endif

#endif

bittree.c 文件

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "bittree.h"

//树的先序遍历。递归算法。
void preOrder(BitNode* root)
{
    if (root == NULL)
    {
        return;
    }
    //打印根节点的数据
    printf("先序遍历:%d \n",root->data);
    //遍历左子树
    if (root->lchild != NULL)
    {
        preOrder(root->lchild);
    }
    //遍历右子数
    if (root->rchild != NULL)
    {
        preOrder(root->rchild);
    }

}
//树的中序遍历。递归算法
void midOrder(BitNode* root)
{
    if (root == NULL)
    {
        return;
    }
    //遍历左子树
    if (root->lchild != NULL)
    {
        midOrder(root->lchild);
    }
    //打印根节点的数据
    printf("中序遍历:%d \n",root->data);
    //遍历右子数
    if (root->rchild != NULL)
    {
        midOrder(root->rchild);
    }
}
//树的后序遍历。递归算法
void lastOrder(BitNode* root)
{
    if (root == NULL)
    {
        return;
    }
    //遍历左子树
    if (root->lchild != NULL)
    {
        lastOrder(root->lchild);
    }
    //遍历右子数
    if (root->rchild != NULL)
    {
        lastOrder(root->rchild);
    }
    //打印根节点的数据
    printf("后序遍历:%d \n",root->data);
}

//统计叶子节点的个数,叶子节点就是没有孩子的节点。递归算法
void countLeafNodes(BitNode* root,int* sum)
{

    if (root)
    {
        //先统计传入节点有没有叶子节点
        if (root->lchild == NULL && root->rchild == NULL)
        {
            (*sum) = (*sum) + 1;
        }
        //统计传入节点左子树的叶子节点,存在左子树
        if (root->lchild)
        {
            countLeafNodes(root->lchild,sum);
        }

        //统计传入节点右子树的叶子节点,存在右子树
        if (root->rchild)
        {
            countLeafNodes(root->rchild,sum);
        }

    }
}

//求树的深度,递归算法
int getDepth(BitNode* root)
{
    int leftdepth ;
    int rightdepth ;
    int depth ;
    if (root == NULL)
    {
        return 0;
    }
    else
    {
        leftdepth = getDepth(root->lchild);   //左子树的深度
        rightdepth = getDepth(root->rchild);  //右子树的深度
        depth = 1 + (leftdepth > rightdepth ? leftdepth : rightdepth);  //左右子树最大深度加1(根节点)

    }
    return depth;
}
//copy树,递归
BitNode* copyBitTree(BitNode* root)
{
    BitNode* newNode = NULL;
    BitNode* newLeftChild = NULL;
    BitNode* newRightChild = NULL;
    if (root == NULL)
    {
        return NULL;
    }
    //copy左子树
    if (root->lchild != NULL)
    {
        newLeftChild = copyBitTree(root->lchild);
    }
    else newLeftChild = NULL;
    //copy右子树
    if (root->rchild != NULL)
    {
        newRightChild = copyBitTree(root->rchild);
    }
    else newRightChild = NULL;
    //为copy的节点分配内存
    newNode = (BitNode*)malloc(sizeof(BitNode));
    if (newNode == NULL)
    {
        return NULL;
    }
    //为copy的节点指针域赋值
    newNode->lchild = newLeftChild;
    newNode->rchild = newRightChild;
    //为copy的数据域赋值
    newNode->data = root->data;
    return newNode;
}
/***********************测试代码********************/

/*
void main()
{
    //BitNode t1;
    //memset(&t1,0,sizeof(BitNode));

    BitNode *t1,*t2,*t3,*t4,*t5;
    int sumleafnode = 0;
    int depth = 0;
    t1 = NULL;t2 = NULL; t3 = NULL; t4 = NULL; t5 = NULL;
    t1 = (BitNode *)malloc(sizeof(BitNode));
    t2 = (BitNode *)malloc(sizeof(BitNode));
    t3 = (BitNode *)malloc(sizeof(BitNode));
    t4 = (BitNode *)malloc(sizeof(BitNode));
    t5 = (BitNode *)malloc(sizeof(BitNode));
    memset(t1,0,sizeof(BitNode));
    memset(t2,0,sizeof(BitNode));
    memset(t3,0,sizeof(BitNode));
    memset(t4,0,sizeof(BitNode));
    memset(t5,0,sizeof(BitNode));
    t1->data = 1;
    t2->data = 2;
    t3->data = 3;
    t4->data = 4;
    t5->data = 5;

    t1->lchild = t2;
    t1->rchild = t3;
    t2->lchild = t4;
    t3->lchild = t5;

    preOrder(t1);
    midOrder(t1);
    lastOrder(t1);
    countLeafNodes(t1,&sumleafnode);
    printf("叶子的节点个数是:%d \n",sumleafnode);
    depth = getDepth(t1);
    printf("树的深度是:%d \n",depth);

    {
        BitNode* copytree = copyBitTree(t1);
        preOrder(copytree);
    }
    if (t1 != NULL)
    {
        free(t1);
        t1 = NULL;
    }
    if (t2 != NULL)
    {
        free(t2);
        t2 = NULL;
    }
    if (t3 != NULL)
    {
        free(t3);
        t3 = NULL;
    }
    if (t4 != NULL)
    {
        free(t4);
        t4 = NULL;
    }
    if (t5 != NULL)
    {
        free(t5);
        t5 = NULL;
    }
    system("pause");
}

*/
#include <iostream>
#include <stack>
#include "bittree.h"
using namespace std;
/********二叉树的中序非递归遍历,采用栈的方式*****************/
/*
步骤1:如果结点没有左子树,该结点入栈;
        如果结点没有左子树,访问该结点;
步骤2:如果结点有右子树,重复步骤1;
        如果结点没有右子树(结点访问完毕),
        根据栈顶指示回退,访问栈顶元素,
        并访问右子树,重复步骤1;如果栈为空,表示遍历完毕。
注意:入栈的结点表示,本身没有被访问过,同时右子树也没有被访问过。
*/
//一直往左走,找到中序遍历的起点
BitNode* goleft(BitNode* root, stack<BitNode*>& s)
{
    if (root == NULL)
    {
        return NULL;
    }
    //如果该结点有左子树,该结点入栈,指针下移
    while(root->lchild != NULL)
    {
        s.push(root);
        root = root->lchild;
    }
    //如果没有左子树,返回该结点 
    return root;
}
void stlmidOrder(BitNode* root)
{
    BitNode* t = NULL;
    stack<BitNode*> s;
    t  = goleft(root,s);
    while(t)
    {
        printf("中序非递归遍历:%d \n",t->data);

        //如果t有右子树,重复步骤1
        if (t->rchild != NULL)
        {
            t = goleft(t->rchild,s);//右子树中中序遍历起点
        }
        else if(!s.empty())  //如果t没有右子树,根据栈顶指示回退
        {
            t = s.top();
            s.pop();
        }
        else  //如果t没有右子树,并且栈为空
        {
            t = NULL;
        }

    }
}
void main()
{
    BitNode *t1,*t2,*t3,*t4,*t5;
    int sumleafnode = 0;
    int depth = 0;
    t1 = NULL;t2 = NULL; t3 = NULL; t4 = NULL; t5 = NULL;
    t1 = (BitNode *)malloc(sizeof(BitNode));
    t2 = (BitNode *)malloc(sizeof(BitNode));
    t3 = (BitNode *)malloc(sizeof(BitNode));
    t4 = (BitNode *)malloc(sizeof(BitNode));
    t5 = (BitNode *)malloc(sizeof(BitNode));
    memset(t1,0,sizeof(BitNode));
    memset(t2,0,sizeof(BitNode));
    memset(t3,0,sizeof(BitNode));
    memset(t4,0,sizeof(BitNode));
    memset(t5,0,sizeof(BitNode));
    t1->data = 1;
    t2->data = 2;
    t3->data = 3;
    t4->data = 4;
    t5->data = 5;

    t1->lchild = t2;
    t1->rchild = t3;
    t2->lchild = t4;
    t3->lchild = t5;

    //preOrder(t1);
    midOrder(t1);
    stlmidOrder(t1);
    //lastOrder(t1);
    countLeafNodes(t1,&sumleafnode);
    printf("叶子的节点个数是:%d \n",sumleafnode);
    depth = getDepth(t1);
    printf("树的深度是:%d \n",depth);

    {
        BitNode* copytree = copyBitTree(t1);
        preOrder(copytree);
    }
    if (t1 != NULL)
    {
        free(t1);
        t1 = NULL;
    }
    if (t2 != NULL)
    {
        free(t2);
        t2 = NULL;
    }
    if (t3 != NULL)
    {
        free(t3);
        t3 = NULL;
    }
    if (t4 != NULL)
    {
        free(t4);
        t4 = NULL;
    }
    if (t5 != NULL)
    {
        free(t5);
        t5 = NULL;
    }
    system("pause");
}

可能会调用其它头文件或源文件,如果调用,请翻看我的其它博客,对其头文件或源文件的实现方式。
good luck !

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,以下是用C语言实现的代码: ```c #include<stdio.h> #include<stdlib.h> #include<stdbool.h> // 定义二叉树节点的结构体 struct TreeNode { char data; // 数据域 struct TreeNode* leftChild; // 左孩子指针 struct TreeNode* rightChild; // 右孩子指针 bool leftTag; // 左线索标志 bool rightTag; // 右线索标志 }; // 先序遍历创建二叉树 struct TreeNode* createBinaryTree() { char c; scanf("%c", &c); getchar(); // 读取输入字符后需要跳过回车符 if (c == '#') { // 如果输入#,表示该节点为空指针 return NULL; } struct TreeNode* root = (struct TreeNode*)malloc(sizeof(struct TreeNode)); // 创建根节点 root->data = c; root->leftChild = createBinaryTree(); // 递归创建左子树 root->rightChild = createBinaryTree(); // 递归创建右子树 return root; } // 中序线索化二叉树 void inOrderThreading(struct TreeNode* root, struct TreeNode** pre) { if (root == NULL) { // 如果是空树,直接返回 return; } inOrderThreading(root->leftChild, pre); // 递归线索化左子树 if (root->leftChild == NULL) { // 如果左孩子为空,将左孩子指针指向前驱节点 root->leftChild = *pre; root->leftTag = true; } if (*pre != NULL && (*pre)->rightChild == NULL) { // 如果前驱节点的右孩子为空,将前驱节点的右孩子指针指向当前节点 (*pre)->rightChild = root; (*pre)->rightTag = true; } *pre = root; // 更新前驱节点 inOrderThreading(root->rightChild, pre); // 递归线索化右子树 } // 获取中序线索二叉树的第一个节点 struct TreeNode* firstNode(struct TreeNode* root) { while (root->leftTag == false) { root = root->leftChild; } return root; } // 获取中序线索二叉树中节点的后继节点 struct TreeNode* nextNode(struct TreeNode* root) { if (root->rightTag == false) { // 如果右线索标志为false,表示有右孩子 return firstNode(root->rightChild); } else { // 如果右线索标志为true,表示没有右孩子,返回右线索指向的后继节点 return root->rightChild; } } // 通过找前驱的方式遍历中序线索二叉树 void inOrderTraverseByPredecessor(struct TreeNode* root) { while (root != NULL) { while (root->leftTag == false) { // 如果左线索标志为false,说明有左孩子,继续向左走 root = root->leftChild; } printf("%c ", root->data); // 输出当前节点 root = root->leftChild; // 向左孩子继续遍历 } printf("\n"); } // 通过找后继的方式遍历中序线索二叉树 void inOrderTraverseBySuccessor(struct TreeNode* root) { struct TreeNode* p = firstNode(root); // 获取第一个节点 while (p != NULL) { printf("%c ", p->data); // 输出当前节点 p = nextNode(p); // 获取当前节点的后继节点 } printf("\n"); } int main() { struct TreeNode* root = createBinaryTree(); // 创建二叉树 struct TreeNode* pre = NULL; inOrderThreading(root, &pre); // 中序线索化二叉树 printf("通过找前驱的方式遍历中序线索二叉树:"); inOrderTraverseByPredecessor(root); // 通过找前驱的方式遍历中序线索二叉树 printf("通过找后继的方式遍历中序线索二叉树:"); inOrderTraverseBySuccessor(root); // 通过找后继的方式遍历中序线索二叉树 return 0; } ``` 以上代码中,`createBinaryTree`函数用于创建二叉树,`inOrderThreading`函数用于中序线索化二叉树,`firstNode`函数用于获取中序线索二叉树的第一个节点,`nextNode`函数用于获取中序线索二叉树中节点的后继节点,`inOrderTraverseByPredecessor`函数用于通过找前驱的方式遍历中序线索二叉树,`inOrderTraverseBySuccessor`函数用于通过找后继的方式遍历中序线索二叉树

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值