二叉树的一些简单操作

二叉树的概念就不用多说了,根节点,左右孩子,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 ;
	}//if
	else {
		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);
	}//else
	return 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;
	}//if
	else {
		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;
	else
		return 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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值