二叉树的一些方法

//LinkBinTree.h

#ifndef _LINKBINTREE_H_
#define _LINKBINTREE_H_

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


//此处不能使用typedef去"定义"数据的类型,提供一个typedef会传递此数据结构支持多种类型的信息,而创建二叉树节点的函数,却明确指定以固定%x的方式去
//格式化存储输入,这种声明与实现的不一致可能会带来不必要的烦恼
//typedef char Element;         禁止!!!

//二叉树节点类型结构
typedef struct _BinTreeNode
{
    char data;
    struct _BinTreeNode *leftChild;         //左孩子
    struct _BinTreeNode *rightChild;        //右孩子
}BinTreeNode;

//二叉树管理结构,flag参数用于标记空节点,当数据等于flag的值时,节点为空
typedef struct _BinTree
{
    BinTreeNode *root;
    char		 flag;
}BinTree;


//初始化函数,用于初始化二叉树管理变量
void InitBinTree(BinTree *tree, char flag);

//创建函数,以输入字符方式创建
void CreateBinTree_input(BinTree *tree);


//一些方法
//全部节点数
int Count(BinTree tree);

//叶子节点数
int CountOfLeaves(BinTree tree);

//度为2的节点个数
int CountOfN2(BinTree tree);

//第k层节点数,整个树根为第0层(与二叉树性质的公式保持一致)
int CountOfKLevel(BinTree tree, int k);

//树高度
int Height(BinTree tree);

//查找e
BinTreeNode *Search(BinTree tree, char e);

//p的双亲
BinTreeNode *Parent(BinTree tree, BinTreeNode *p);

//树为空
bool BinTreeEmpty(BinTree tree);

//树比较
bool BinTreeCmp(BinTree tree1, BinTree tree2);

//将树tree1拷贝到tree2
void BinTreeCopy(BinTree *tree1, BinTree *tree2);

//摧毁
void BinTreeDestroy(BinTree *tree);


#endif // _LINKBINTREE_H_




//LinkBinTree.c

#include "LinkBinTree.h"

void InitBinTree(BinTree *tree, char flag)
{
    tree->root = NULL;
    tree->flag = flag;
}

static void Create_1(BinTree *tree, BinTreeNode **node)    //创建方式的先序的
{
    char item;
    if( 1 != scanf("%c", &item) || item == tree->flag ) //如果输入字符与空节点标记值相等,则将节点置NULL并立即返回
    {
        *node = NULL;
         return ;
    }
    //输入值不为标记,创建节点并创建左右孩子
    *node = (BinTreeNode *)malloc(sizeof(BinTreeNode));
    if( NULL == *node )
    {
        *node = NULL;
        return ;
    }
    (*node)->data = item;
    Create_1(tree, &(*node)->leftChild);
    Create_1(tree, &(*node)->rightChild);
}

static BinTreeNode *Create_2(BinTree *tree)
{
    char item;
    if( 1 != scanf("%c", &item) || item == tree->flag )
        return NULL;

    BinTreeNode * p = (BinTreeNode *)malloc(sizeof(BinTreeNode));
    if( NULL == p )
        return NULL;
    p->data = item;
    p->leftChild = Create_2(tree);
    p->rightChild = Create_2(tree);

    return p;
}

void CreateBinTree_input(BinTree *tree)
{
    printf("请输入各节点元素,#表示该节点为空节点\n");
    Create_1(tree, &(tree->root));
    //tree->root = Create_2(tree);
}

//利用递归将问题分解,一个二叉树由一个个子二叉树组成
static int Count_(BinTreeNode *node)
{
    if( NULL == node )      //树为空节点数为0
        return 0;

    return Count_(node->leftChild) + Count_(node->rightChild) + 1;    //不为空则是根节点数加上左子树与右子树的节点个数
}

int Count(BinTree tree)
{
    return Count_(tree.root);
}

static int CountOfLeaves_(BinTreeNode *node)
{
    if( NULL == node )
        return 0;
    if( NULL == node->leftChild && NULL == node->rightChild )                   //根节点为叶子节点
        return 1;

    return CountOfLeaves_(node->leftChild) + CountOfLeaves_(node->rightChild);  //不是叶子节点则叶子节点数为其左右子树叶子结点之和
}

int CountOfLeaves(BinTree tree)
{
    return CountOfLeaves_(tree.root);
}

static int CountOfN2_(BinTreeNode *node)
{
    if( NULL == node )
        return 0;
    if( NULL != node->leftChild && NULL != node->rightChild )                   //度为2的节点下还可能有度为2的节点,继续查找
        return 1 + CountOfN2_(node->leftChild) + CountOfN2_(node->leftChild);

    return CountOfN2_(node->leftChild) + CountOfN2_(node->leftChild);           //只要有一个以上的子树就可能在其子树存在度为2的节点,继续查找
}

int CountOfN2(BinTree tree)
{
    return CountOfN2_(tree.root);
}

/*这个比起其他的递归稍微难理解一些,我是这样理解的
 * 从整个二叉树的根开始往下递归,设根为第0层,目标层为k层,位于第0层时,目标层与当前层差k - 0层,到了第1层时,目标层与当前层差了k - 1层,第2层,差了k - 2层
 *于是,当差值为0时,即到了目标层,便可统计该层所有不为空的节点数目
 */
static int CountOfKLevel_(BinTreeNode *node, int k)
{
    if( NULL == node )                              //节点为空不计入数量
        return 0;
    if( 0 == k )                                    //到达目标层,且node不是空,对其计1
        return 1;

    return CountOfKLevel_(node->leftChild, k - 1) + CountOfKLevel_(node->rightChild, k - 1);    //往目标层靠近逼近
}

int CountOfKLevel(BinTree tree, int k)
{
    return k < 0 ? 0 : CountOfKLevel_(tree.root, k);                            //非法输入返回0
}

static int Height_(BinTreeNode *node)
{
    if( NULL == node )
        return 0;
    int LHeight = Height_(node->leftChild);
    int RHeight = Height_(node->rightChild);

    return LHeight > RHeight ? (LHeight + 1) : (RHeight + 1);       //二叉树的高度为左右子树中较高者加上根节点的高度
}

int Height(BinTree tree)
{
    return Height_(tree.root);
}

static BinTreeNode *Search_(BinTreeNode *node, char e)
{
    if( NULL == node )
        return NULL;
    if( node->data == e )                                           //找到节点,返回节点
        return node;
    BinTreeNode *p = Search_(node->leftChild, e);                   //在左子树中寻找
    if( NULL != p )                                                 //找到,无需在右子树中查找
        return p;

    return Search_(node->rightChild, e);
}

BinTreeNode *Search(BinTree tree, char e)
{
    return Search_(tree.root, e);
}

static BinTreeNode *Parent_(BinTreeNode *node, BinTreeNode *p)
{
    if( NULL == node || NULL == p )
        return NULL;
    if( node->leftChild == p || node->rightChild == p )
        return node;
    BinTreeNode *parent = Parent_(node->leftChild, p);                   //在左子树中寻找
    if( NULL != parent )                                                 //找到,无需在右子树中查找
        return parent;

    return Parent_(node->rightChild, p);
}

BinTreeNode *Parent(BinTree tree, BinTreeNode *p)
{
    return Parent_(tree.root, p);
}

bool BinTreeEmpty(BinTree tree)
{
    return NULL == tree.root;
}

static bool BinTreeCmp_(BinTreeNode *node1, BinTreeNode *node2)
{
    if( NULL == node1 && NULL == node2 )                                //同为空则相等
        return true;
    if( NULL != node1 && NULL != node2 && node1->data == node2->data )  //都不为空且节点数据域值相等,判断其子树是否相等
        return BinTreeCmp_(node1->leftChild, node2->leftChild) && BinTreeCmp_(node1->rightChild, node2->rightChild);

    return false;           //其余情况不等
}

bool BinTreeCmp(BinTree tree1, BinTree tree2)
{
    return BinTreeCmp_(tree1.root, tree2.root);
}

static void BinTreeCopy_(BinTreeNode *node1, BinTreeNode **node2)
{
    if( NULL == node1 )
    {
        *node2 = NULL;
        return ;
    }
    *node2 = (BinTreeNode *)malloc(sizeof(BinTreeNode));
    if( NULL == node2 )
        return ;
    (*node2)->data = node1->data;

    BinTreeCopy_(node1->leftChild, &(*node2)->leftChild);
    BinTreeCopy_(node1->rightChild, &(*node2)->rightChild);
}

void BinTreeCopy(BinTree *tree1, BinTree *tree2)
{
    BinTreeCopy_(tree1->root, &tree2->root);
}

static void BinTreeDestroy_(BinTreeNode **node)
{
    if( NULL == *node )
        return;
    BinTreeDestroy_(&(*node)->leftChild);
    BinTreeDestroy_(&(*node)->rightChild);
    free(*node);
    *node = NULL;
}

void BinTreeDestroy(BinTree *tree)
{
    BinTreeDestroy_(&tree->root);
}





//main.c
#include <stdio.h>
#include "LinkBinTree.h"

int main(int argc, char *argv[])
{
    BinTree tree;
    InitBinTree(&tree, '#');
    CreateBinTree_input(&tree);

    printf("二叉树的节点个数为 %d\n", Count(tree));
    printf("叶子节点个数为 %d\n", CountOfLeaves(tree));
    printf("度为2的节点个数为 %d\n", CountOfN2(tree));
    printf("第k层的节点个数为 %d\n", CountOfKLevel(tree, 1));
    printf("第k层的节点个数为 %d\n", CountOfKLevel(tree, 2));
    printf("树的高度为 %d\n", Height(tree));
    BinTreeNode *p = Search(tree, 'G');
    if( NULL != p )
        printf("查找的节点的值为 %c\n", p->data);
    BinTreeNode *parent = Parent(tree, p);
    if( NULL != parent )
        printf("父节点的值为 %c\n", parent->data);
    BinTreeEmpty(tree) ? printf("树是空的\n") : printf("树不是空的\n");

    BinTree tree2;
    BinTreeCopy(&tree, &tree2);
    BinTreeCmp(tree, tree2) ? printf("树相等\n") : printf("树不等\n");
    BinTreeDestroy(&tree2);
    BinTreeDestroy(&tree);

    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值