二叉树的一些方法

来源:互联网 发布:阿里云服务器端口映射 编辑:程序博客网 时间:2024/05/17 14:28

//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);//查找eBinTreeNode *Search(BinTree tree, char e);//p的双亲BinTreeNode *Parent(BinTree tree, BinTreeNode *p);//树为空bool BinTreeEmpty(BinTree tree);//树比较bool BinTreeCmp(BinTree tree1, BinTree tree2);//将树tree1拷贝到tree2void 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;}



0 0
原创粉丝点击