二叉树的一些简单操作

来源:互联网 发布:大数据分析师就业形势 编辑:程序博客网 时间:2024/06/06 03:16

二叉树的概念就不用多说了,根节点,左右孩子,blablabla。二叉树的定义就是一个递归的定义,所以很多二叉树问题我们都可以用递归来轻松的解决。递归有时候真的太神奇了。然后粘贴书上的一些二叉树的必要的知识点吧。

二叉树分为完全二叉树(满二叉树的基础上节点从左往右有序排列),满二叉树(除了叶子节点,每个节点都有左右孩子);

一般二叉树的重要性质:

1 在二叉树的第i层上最多有2i-1个节点

2 深度为k的二叉树最多有2k-1个节点

3 对于任何一颗二叉树T,如果其终端节点数为n0度为2的节点数为n2则n0=n2+1

完全二叉树的重要性质:

1 具有n个节点的完全二叉树的深度为[log2n]+1(向下取整)

2 如果对一颗有n个节点的完全二叉树的节点按层序编号,则对任一节点有:

         如果i= 1;则i为根节点,如果i>1则双亲是第[i/2]个节点

         如果2i>n 则节点i无左孩子 (即i为叶子节点),否则双亲是第[i/2]个节点

         如果2i+1 > n则节点无右孩子,否则其右孩子是第2i+1个节点

我感觉我每次背完要不了多久就又忘记,真不知道当初高中怎么记得那么多公式的,汗。

好了,贴上结构体:

//二叉树
typedef struct ErNode
    int data;//数据域
    struct ErNode *lchild, *rchild;//左右孩子
}ErNode, *pErNode;

然后说如何建立一二叉树,当然递归很简单,下面代码写的就是。还有我看到一写法很一板一眼,不过最容易理解,我说一下吧,就是一个一个的建立节点,然后谁要做谁的左孩子,就把set成左孩子,感觉像java了,蛮好理解的,不过我就不写出来了,太死板了。

二叉树是灰常重要的,以后很多的知识都是基于二叉树的,所以最基本的二叉树知识是必须透彻侧理解的,尤其其中递归的道理。

#include <stdio.h>#include <stdlib.h >#include <malloc.h >//二叉树typedef struct ErNode {int data;//数据域struct ErNode *lchild, *rchild;//左右孩子}ErNode, *pErNode;//======================================//创建一棵树pErNode Create() {pErNode tree;int item;//数据域printf("请输入节点值:\n");scanf("%d",&item);if(0 == item) {//当输入为0时,节点或孩子为空,//其实应该输入一个较不好的数比如65535之类的,不过我嫌太长了,测的时候烦tree = NULL ;}//ifelse {tree = (pErNode )malloc(sizeof(ErNode ));if(!tree)exit(-1);tree->data = item;//树的节点赋值printf("创建%d的左孩子:",item);tree->lchild = Create();printf("创建%d的右孩子:",item);tree->rchild = Create();printf("%d节点创建完毕\n",item);}//elsereturn tree;}//Create//===================================================//清空树void ClearTree(pErNode tree) {if(tree) {if(tree->lchild)ClearTree(tree->lchild);//递归清空左孩子if(tree->rchild)ClearTree(tree->rchild );//递归清空右孩子free(tree);//左右都被清了之后}}//ClearTree//=======================================================//树的深度int GetDepth(pErNode tree) {int depth = 0;//树深int ld = 0;//左树深度int rd = 0;//右树深度if(!tree) {return 0;}//ifelse {if(tree->lchild)ld = GetDepth(tree->lchild);//获取左树深度if(tree->rchild)rd = GetDepth(tree->rchild);//获取右树深度depth = (ld > rd) ? ld : rd;//取较大的那个return depth + 1;//根节点也要算进去}}//GetDepth//========================================================//节点数int GetNodeNum(pErNode tree) {if(!tree) return 0;elsereturn GetNodeNum(tree->lchild ) + GetNodeNum(tree->rchild ) + 1;//左孩子节点数+右孩子节点数+根节点}//GetNodeNum//==========================================================//第k层节点数int GetKLevelNodeNum(pErNode tree, int k) {if(!tree || k < 1) return 0;//空树或没层if(1 == k)return 1;//就一个根节点/*想想我们要找k层的节点数,是不是就是要找上一层k-1层的左右孩子孩子节点数。*/int ld = GetKLevelNodeNum(tree->lchild,k-1);//左孩子节点int rd = GetKLevelNodeNum(tree->rchild , k-1);//右孩子节点return ld + rd;}//GetKLevelNodeNum//==============================================================//获取叶子节点int GetLeafNode(pErNode tree) {if(!tree)return 0;if(!tree->lchild && !tree->rchild)return 1;//只有根节点return GetLeafNode(tree->lchild) + GetLeafNode(tree->rchild);}//GetLeafNode//========================================================//先序遍历void PreTraverse(pErNode tree) {if(tree) {printf("%d ",tree->data );PreTraverse(tree->lchild );PreTraverse(tree->rchild );}}//PreTraverse//主函数int main() {pErNode p = Create();printf("先序遍历:\n");PreTraverse(p);printf("\n");printf("\n树的深度=%d\n",GetDepth(p));printf("\n树的节点数=%d\n",GetNodeNum(p));printf("\n树的叶子节点数=%d\n",GetLeafNode(p));for(int i = 1; i <= GetDepth(p); i++) {printf("第%d层有节点数%d个\n",i,GetKLevelNodeNum(p,i));}ClearTree(p);return 0;}


0 0
原创粉丝点击