二叉树的各种操作

之前做过排序算法与单链表的总结(见前面的博文),现把二叉树的给补上。本文主要从二叉树的建立,二叉树结点个数统计,二叉树的遍历和二叉排序树几个方面进行介绍总结。

1、二叉树的建立

先建立二叉树的结点

// 定义二叉树的结点
typedef struct btreenode
{
	char data;   // 数据域
	struct btreenode *lchild;  // 左孩子指针
	struct btreenode *rchild;  // 右孩子指针
}btnode, *btnodePoint;
注意btnode, *btnodePoint
btnode定义的是结构体变量,btnodePoint定义的是结构体指针变量
btnode *bt与btnodePoint bt是等价的,bt都是结构体指针变量
详见 http://blog.sina.com.cn/s/blog_8bba7b400102w2qj.html

定义好二叉树结点后,开始创建二叉树

/******************************************************
* 函数名称:btnode *CtreateBinaryTree(char *str)
* 参    数:str----待创建二叉树的先序遍历字符序列
* 函数功能:根据先序遍历规则创建指定的二叉树		
* 返 回 值:创建二叉树的根结点
* 说    明:无
******************************************************/
btnode *CtreateBinaryTree(char *str)
{
	btnode *bt;
	char x;
	static int i=0;
	//scanf("%c", &x);
	x = str[i++];  // 取出结点数据域的值
	if(x=='#')  // #表示无对应结点
		bt = NULL;
	else
	{
		bt = (btnode *)malloc(sizeof(btnode));
		bt->data = x;
		bt->lchild = CtreateBinaryTree(str);
		bt->rchild = CtreateBinaryTree(str);
	}
	return bt;
}

2、二叉树结点个数统计及二叉树高度

2.1、二叉树中叶子结点个数

/**************************************************************
* 函数名称:unsigned int LeafNodeNum(btnode *bt)
* 参    数:bt----二叉树的根结点
* 函数功能:统计二叉树度为0的结点(叶子结点)个数
* 返 回 值:二叉树度为0的结点(叶子结点)个数
* 说    明:无左孩子和右孩子的结点为叶子结点
**************************************************************/
unsigned int LeafNodeNum(btnode *bt)
{
	static unsigned int num=0;
	if(bt != NULL)
	{	
		if(bt->lchild==NULL && bt->rchild==NULL)
			num++;
		num = LeafNodeNum(bt->lchild);
		num = LeafNodeNum(bt->rchild);
	}
	return num;
}

2.2、二叉树中一度结点个数

/**************************************************************
* 函数名称:unsigned int OneDegree(btnode *bt)
* 参    数:bt----二叉树的根结点
* 函数功能:统计二叉树度为1的结点个数
* 返 回 值:二叉树度为1的结点个数
* 说    明:只有一个左孩子或只有一个右孩子的结点为度为1的结点
**************************************************************/
unsigned int OneDegree(btnode *bt)
{
	static unsigned int num=0;
	if(bt != NULL)
	{	
		if((bt->lchild==NULL && bt->rchild!=NULL) || (bt->lchild!=NULL && bt->rchild==NULL))
			num++;
		num = OneDegree(bt->lchild);
		num = OneDegree(bt->rchild);
	}
	return num;
}

2.3、二叉树中二度结点个数

/**************************************************************
* 函数名称:unsigned int OneDegree(btnode *bt)
* 参    数:bt----二叉树的根结点
* 函数功能:统计二叉树度为2的结点个数
* 返 回 值:二叉树度为2的结点个数
* 说    明:既有左孩子又有右孩子的结点为度为2的结点
**************************************************************/
unsigned int TwoDegree(btnode *bt)
{
	static unsigned int num=0;
	if(bt != NULL)
	{	
		if(bt->lchild!=NULL && bt->rchild!=NULL)
			num++;
		num = TwoDegree(bt->lchild);
		num = TwoDegree(bt->rchild);
	}
	return num;
}

2.4、二叉树的高度

/**************************************************************
* 函数名称:unsigned int BinaryTreeHigh(btnode *bt)
* 参    数:bt----二叉树的根结点
* 函数功能:计算二叉树的高度
* 返 回 值:二叉树的高度值
* 说    明:二叉树的高度为二叉树中结点层次的最大值。
		    若一棵二叉树为空,则其高度为0;否则其高度等于左子树
			和右子树的最大高度加1,即:
			h(bt) = 0    (bt=NULL)
			h(bt) = max{h(bt->lchild), h(bt->rchild)}+1  (其他)
**************************************************************/
unsigned int BinaryTreeHigh(btnode *bt)
{
	unsigned int h, lh, rh;
	if(bt == NULL)
		h = 0;
	else
	{	
		lh = BinaryTreeHigh(bt->lchild);
		rh = BinaryTreeHigh(bt->rchild);
		h = lh>rh ? lh+1 : rh+1;
	}
	return h;
}

3、二叉树的遍历

3.1、二叉树的先序遍历

/**************************************************************
* 函数名称:void PreOrder(btnode *bt)
* 参    数:bt----二叉树的根结点
* 函数功能:二叉树的先序遍历
* 返 回 值:无
* 说    明:根结点---左孩子---右孩子
**************************************************************/
void PreOrder(btnode *bt)
{
	if(bt != NULL)
	{
		printf("%-2c", bt->data);
		PreOrder(bt->lchild);
		PreOrder(bt->rchild);
	}
}

3.2、二叉树的中序遍历

/**************************************************************
* 函数名称:void InOrder(btnode *bt)
* 参    数:bt----二叉树的根结点
* 函数功能:二叉树的中序遍历
* 返 回 值:无
* 说    明:左孩子---根结点---右孩子
**************************************************************/
void InOrder(btnode *bt)
{
	if(bt != NULL)
	{
		InOrder(bt->lchild);
		printf("%-2c", bt->data);
		InOrder(bt->rchild);
	}
}

3.3、二叉树的后序遍历

/**************************************************************
* 函数名称:void PostOrder(btnode *bt)
* 参    数:bt----二叉树的根结点
* 函数功能:二叉树的后序遍历
* 返 回 值:无
* 说    明:左孩子---右孩子---根结点
**************************************************************/
void PostOrder(btnode *bt)
{
	if(bt != NULL)
	{		
		PostOrder(bt->lchild);
		PostOrder(bt->rchild);
		printf("%-2c", bt->data);
	}
}

3.4、二叉树的层次遍历

/**************************************************************
* 函数名称:void PreOrder(btnode *bt)
* 参    数:bt----二叉树的根结点
* 函数功能:二叉树的层次遍历
* 返 回 值:无
* 说    明:将层次遍历的各结点依次存入数组中,之后依次取出
**************************************************************/
void LeverlOrder(btnode *bt)
{
	//btnodePoint queue[20], p; // 队列大小需根据结点个数来调整,p为临时结点指针
	btnode *queue[20], *p;
	int front=0, rear=0; // 设置队头与队尾
	if(bt)
	{
		queue[rear++] = bt; // 先将二叉树的根结点入队
		while(front!=rear)  // 如果相等,则表示二叉树遍历完成
		{
			p = queue[front++]; // 顺序将层次遍历得到的结点出队
			printf("%-2c", p->data); 
			// 如果左子树不为空,将左孩子结点存入队列中
			if(p->lchild!=NULL)
				queue[rear++] = p->lchild;  // 先放左孩子
			// 如果右子树不为空,将右孩子结点存入队列中
			if(p->rchild!=NULL)
				queue[rear++] = p->rchild;  // 再放右孩子
		}
	}
}

3.5、二叉树的深度优先遍历

/**************************************************************
* 函数名称:void DeepOrder(btnode *bt)
* 参    数:bt----二叉树的根结点
* 函数功能:二叉树的深度优先遍历
* 返 回 值:无
* 说    明:将深度优先遍历的各结点依次存入数组中,之后依次取出
**************************************************************/
void DeepOrder(btnode *bt)
{
	btnodePoint queue[10], p;
	int front=0, rear=0;
	if(bt)
	{
		queue[rear++] = bt;
		while(front!=rear)
		{
			p = queue[front++];
			printf("%-2c", p->data);
			if(p->rchild!=NULL)
				queue[rear++] = p->rchild;
			if(p->lchild!=NULL)
				queue[rear++] = p->lchild;
		}
	}
}

4、二叉排序树

4.1、二叉排序树的建立

/**************************************************************
* 函数名称:btnode *CreateSortBinaryTree(char str[])
* 参    数:str----待创建二叉树的先序遍历字符序列
* 函数功能:创建一个二叉排序树
* 返 回 值:创建的二叉排序树的根结点
* 说    明:先创建一个空树,之后将每个结点值插入二叉排序树中,
			逐步建立二叉排序树
**************************************************************/
btnode *CreateSortBinaryTree(char str[])
{
	btnode *SortBinaryTreeRoot=(btnode *)malloc(sizeof(btnode)); // 申请结点空间
	static int i=0;
	SortBinaryTreeRoot = NULL; // 创建一个空二叉树
	while(str[i]!='\0')
	{
		if(str[i]!='#')  // '#'表示按照先序遍历创建二叉树的空结点
			// 依次将每个结点插入二叉排序树中,逐步建立完整的二叉排序树
			SortBinaryTreeRoot = InsertNodeToSortTree(SortBinaryTreeRoot, str[i]);
		i++;
	}
	return SortBinaryTreeRoot;  // 返回建立的二叉排序树的根结点
}

4.2、判断二叉树是否为二叉排序树

/**************************************************************
* 函数名称:unsigned int IsSortBinaryTree(btnode *bt)
* 参    数:bt----二叉树的根结点
* 函数功能:判断给定的二叉树是否为二叉排序树
* 返 回 值:是,返回1;否,返回0
* 说    明:利用二叉排序树的性质及层次遍历的思想进行判断
**************************************************************/
unsigned int IsSortBinaryTree(btnode *bt)
{
	int front=0, rear=0;  // 设置队头与队尾
	btnodePoint queue[20], p; // 队列大小需根据结点个数来调整,p为临时结点指针
	if(bt!=NULL)
	{
		queue[rear++] = bt;  // 先将二叉树的根结点入队
		while(front!=rear)  // 如果相等,则表示二叉树遍历完成
		{
			p = queue[front++]; // 顺序将层次遍历得到的结点出队
			// 如果左子树不为空,且父结点的值大于等于左孩子结点的值,
			// 那么符合二叉排序树规则,将左孩子结点存入队列中
			if(p->lchild!=NULL && p->data >= p->lchild->data)  
				queue[rear++] = p->lchild;  // 先放左孩子
			// 如果右子树不为空,且父结点的值小于等于右孩子结点的值,
			// 那么符合二叉排序树规则,将右孩子结点存入队列中
			if(p->rchild!=NULL && p->data <= p->rchild->data)
				queue[rear++] = p->rchild;  // 再放右孩子
			// 不符合二叉排序规则,则返回0
			if((p->lchild!=NULL&&p->data < p->lchild->data) || (p->rchild!=NULL&&p->data > p->rchild->data))
				return 0;
		}
		return 1;  // 二叉树遍历完成,且都符合二叉排序树规则,则返回1
	}
	else  // 二叉树为空
		return 0;
}

4.3、二叉排序树的插入

/**************************************************************
* 函数名称:btnode *InsertNodeToSortTree(btnode *bt, char val)
* 参    数:bt----二叉排序树的根结点
			val---待插入结点的数据域值
* 函数功能:二叉排序树的插入结点操作
* 返 回 值:插入结点后的二叉排序树的根结点
* 说    明:利用二叉排序树的性质(二分查找的思想)进行插入结点
**************************************************************/
btnode *InsertNodeToSortTree(btnode *bt, char val)
{
	if(bt==NULL)  // 二叉排序树为空,直接将新结点赋值给根结点
	{
		// 初始化新插入的结点
		btnode *newnode=(btnode *)malloc(sizeof(btnode));
		newnode->data = val;
		newnode->lchild = NULL;
		newnode->rchild = NULL;
		bt = newnode;
	}
	else // 如果二叉排序树不为空
	{
		if(bt->data >= val) // 需要在父结点的左边插入新结点
			bt->lchild = InsertNodeToSortTree(bt->lchild, val);
		else  // 需要在父结点的右边插入新结点
			bt->rchild = InsertNodeToSortTree(bt->rchild, val);
	}
	return bt;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值