二叉树

本文介绍了二叉树的基本概念,包括节点的度、深度/高度,以及二叉树的定义和基本性质。深入讨论了完全二叉树的特性,并列举了二叉树的前序、中序和后序遍历算法。最后提到了二叉树的建立过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一.关于树的几个重要概念

       1). :是指节点拥有的子树数。
       2). 深度/高度:从根节点到目的节点x的一条简单路径的长度称为x的深度/高度。国内一般把根节点的高度算为1,而国外有些把根节点的高度算为0,因此计算起来会有差异。

     

     对于4这个节点,度为1,深度/高度为2或3,整个树的高度/深度为3或4。

二.二叉树基本性质

      二叉树定义由n个节点组成(n>=0),构成空树,或者由两棵互不相交的称为左子树和右子树构成。

      二叉树基本性质: 

            1> 在二叉树第i层最多有2^(i-1)个节点(i>=1)。
            2> 深度为k的二叉树最多有2^k-1个节点(k>=1)。
            3> 对于任何一棵二叉树T,终端节点数为n0,度为2的节点数为n2则n0=n2 + 1。
            4> 具有n个节点的完全二叉树的深度为[log2n] + 1,
            5> 如果对一棵有n个节点的完全二叉树(深度为[log2n] + 1)的节点按层序编号,对任一节点i(1<=i<=n)有:
              (1). 如果i=1,则i是根节点,无双亲;否则其双亲是[i/2].
              (2). 如果2i>n,则节点i无左孩子(节点i为叶节点);否则左孩子为2i.
              (3). 如果2i+1>n,则节点i无右孩子(节点i为叶子节点);否则右孩子为2i+1.

三.二叉树基本操作

     1>数据结构定义

typedef struct tagBinTreeNode
{
     void* value;
     struct tagTreeNode * left_child;
     struct tagTreeNode * right_child;	
}BinTreeNode;
       2>二叉树的遍历是指从根节点出发,按造一定次序,访问二叉树的所有节点,使得每个节点被访问一次。D代表根节点,L代表左孩子,R代表右孩子。
       (1).前序遍历,DLR,即先访问根节点,再前序遍历左子树和右子树。
         (2).中序遍历,LDR,即从根节点开始,中序遍历根节点的左子树然后访问根节点,最后中序遍历根节点的右子树。
         (3).后序遍历,LRD,从左到右先子叶后节点的方式遍历访问左右子树,最后是根节点。
         (4).层序遍历,从根节点开始逐层向下遍历,同一层从左到右逐个访问。

前序遍历算法:

void PreOrderTraverse(BinTreeNode *pstNode)
{
	if(pstNode == NULL)
	{
		return;
	}
	printf("%c", (char)(pstNode->value));
	PreOrderTraverse(pstNode->left_child);
	PreOrderTraverse(pstNode->right_child);
}

中序遍历算法:

void InOrderTraverse(BinTreeNode *pstNode)
{
	if(pstNode == NULL)
	{
		return;
	}
		
	PreOrderTraverse(pstNode->left_child);
	printf("%c", (char)(pstNode->value));
	PreOrderTraverse(pstNode->right_child);
}

后序遍历算法:

void PostOrderTraverse(BinTreeNode *ppstNode)
{
	if(pstNode == NULL)
	{
		return;
	}
		
	PreOrderTraverse(pstNode->left_child);
	PreOrderTraverse(pstNode->right_child);
	printf("%c", (char)(pstNode->value));
}
层序遍历:
void LerverOrderTraverse(BinTreeNode *pstNode)
{
	if(pstNode == NULL)
	{
		return;
	}
	printf("%c", (char)(pstNode->value));
	
	PreOrderTraverse(pstNode->right_child);
	PreOrderTraverse(pstNode->left_child);

}

3>二叉树的建立

    假设有这样一个二叉树:

 

     我们可以根据前序中序和后序的方式建立一个二叉树,约定输入*表示空节点。假设一个二叉树的前序遍历输出为:AB*D**C**,中序为:*B*D*A*C*,可以得出中序建立二叉树:
void InOrderCreateBinTree(struct tagBinTreeNode **ppstNode)
{
	char chr;
	
	scanf("%c", &chr);
	if(chr == '*')
	{
		*ppstNode = NULL;
	}
	else
	{	
		(*ppstNode) = (struct tagBinTreeNode*)malloc(sizeof(struct tagBinTreeNode));
		if((*ppstNode) == NULL)
		{
			exit(-1);
		}
		memset((*ppstNode), 0x00, sizeof(struct tagBinTreeNode));
		InOrderCreateBinTree(&(*ppstNode)->left_child);	 //创建左子树
		(*ppstNode)->value = chr;			 //构造根节点
		InOrderCreateBinTree(&(*ppstNode)->right_child); //创建右子树
	}
}
*注意, 虽然说是中序建立二叉树,但是字符的输入顺序应该按照前序列输入方式,设想如果先构造了左子树那么是无法退回父节点的。

四:测试

int main(int arrc, char* argv[])
{
	struct tagBinTreeNode *pstNode = NULL;

	InOrderCreateBinTree(&pstNode);

	printf("\n前序输出:");
	PreOrderTraverse(pstNode);
	printf("\n中序输出:");
	InOrderTraverse(pstNode);
	printf("\n后序输出:");
	PostOrderTraverse(pstNode);
	printf("\n层序输出:");
	LevelOrderTraverse(pstNode);
	printf("\n");
	return (0);
}
输出:
lc@lc-Lenovo:~/work/ProgramTrain$ ./a.out 
AB*D**C**

前序输出:ABDC
中序输出:BDAC
后序输出:BDCA
层序输出:ACBD

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值