0
点赞
收藏
分享

微信扫一扫

数据结构——非线性结构 之 二叉树,详细解析


目录

一、树

1.1树的概念和结构

 1.2树的相关专业名词

1.3树和非树 

二、二叉树

2.1二叉树的概念的结构

三、二叉树的功能实现

3.1二叉树节点的设计

 3.2创建二叉树的新节点

3.3二叉树链式结构的遍历

3.3.1二叉树前序遍历的实现

3.3.1二叉树中序遍历的实现

 3.3.1二叉树后序遍历的实现  ​

3.4求二叉树的数据个数(节点个数)的实现

3.5求二叉树的叶子节点个数的实现

3.6销毁二叉树申请的空间的实现 

四、二叉树的层序遍历(用的多)

五、总代码

六、代码运行实例


一、树

1.1树的概念和结构


 

 1.2树的相关专业名词


 

1.3树和非树 

 


 

二、二叉树

2.1二叉树的概念的结构


 

 

三、二叉树的功能实现


3.1二叉树节点的设计

typedef char BTDataType;//类型重名名

typedef struct BinaryTreeNode
{
	struct BinaryTreeNode* left;//节点里的指针left指向这个节点的左子树
	struct BinaryTreeNode* right;//节点里的指针right指向这个节点的右子树
	BTDataType data;//这个节点存放的数据
}BTNode;

 

 3.2创建二叉树的新节点

//创建新节点
BTNode* BinaryTreeNode(BTDataType x)
{
	BTNode* newnode = (BTNode*)malloc(sizeof(BTNode));//动态开辟内存空间,大小是一个结构体类型BTnode
	if (newnode == NULL)
	{
		perror("the mistake");
	}
	newnode->data = x;//将想存放的数据放入节点里
	newnode->left = NULL;//创建的新节点里的指针left和right要先置为NULL,方便后面的修改
	newnode->right = NULL;//也是因为当这个节点作为根的时候,其左子树和右子树都为NULL

	return newnode; //用返回值返回创建的新节点,这样形参就不用创建二级指针了
}

 


 

3.3二叉树链式结构的遍历


3.3.1二叉树前序遍历的实现

//前序遍历( 根 左子树 右子树 )
void PrevOrder(BTNode* root)//指向根的指针进入
{
	if (root == NULL) //两种情况:1、二叉树无节点,直接打印NULL,并结束函数
		              //2、当递归的作为 根节点 的 左子树 或者 根节点 的 右子树 为空指针NULL的时候,
		              //这个递归结束,返回上一个递归
	{
		printf("NULL ");
		return;//结束函数
	}
	printf("%c ", root->data);//打印该节点的存放的数据
	PrevOrder(root->left);//这个节点的左子树作为根再进入
	PrevOrder(root->right);//这个节点的右子树作为根再进入
}

 

3.3.1二叉树中序遍历的实现

//中序遍历( 左子树 根 右子树 )
void InOrder(BTNode* root)//第一个根节点
{
	if (root == NULL)//两种情况:1、二叉树无节点,直接打印NULL,并结束函数
		              //2、当递归的作为 根节点 的 左子树 或者 根节点 的 右子树 为空指针NULL的时候,
		              //这个递归结束,返回上一个递归

	{
		printf("NULL ");
		return;//结束函数
	}

	InOrder(root->left);//这个节点的左子树作为根再进入
	printf("%c ", root->data);//打印该节点的存放的数据
	InOrder(root->right);//这个节点的右子树作为根再进入
}

 3.3.1二叉树后序遍历的实现  

//后序遍历( 左子树 右子树 根 )
void PostOrder(BTNode* root)//第一个根节点
{
	if (root == NULL)//两种情况:1、二叉树无节点,直接打印NULL,并结束函数
					  //2、当递归的作为 根节点 的 左子树 或者 根节点 的 右子树 为空指针NULL的时候,
					  //这个递归结束,返回上一个递归

	{
		printf("NULL ");
		return;//结束函数
	}

	PostOrder(root->left);//这个节点的左子树作为根再进入
	PostOrder(root->right);//这个节点的右子树作为根再进入
	printf("%c ", root->data);//打印该节点的存放的数据
}

3.4求二叉树的数据个数(节点个数)的实现

//求二叉树的数据个数,二叉树每个节点只存放一个数据,
//所以也可以说求二叉树的节点个数(用的遍历后序的思维)
int TreeSize(BTNode* root)
{
	//三目操作符:exp1?exp2:exp3
	//如果 表达式exp1 为真,则 整个表达式 的结果为 表达式exp2;如果为假,则 整个表达式 的结果为 表达式exp3
	return root == NULL ? 0 : TreeSize(root->left) + TreeSize(root->right) + 1;
}

3.5求二叉树的叶子节点个数的实现

//求二叉树叶子节点(度为0的节点)的个数
int TreeLeafSize(BTNode* root)
{
	if (root == NULL)//二叉树里没有节点
		return 0;

	if (root->left == NULL && root->right == NULL)//二叉树里只有一个节点,那么这个节点就是叶子节点
		return 1;

	//进入递归,找左子树的叶子节点+找右子树的叶子节点
	return TreeLeafSize(root->left) + TreeLeafSize(root->right);
}

 

3.6销毁二叉树申请的空间的实现 

void DestroyTree(BTNode* root)
{
	if (root == NULL)
	{
		return;
	}

	DestroyTree(root->left);//将当前节点的左子树作为根节点递归
	DestroyTree(root->right);//将当前节点的左子树作为根节点递归

	free(root);//释放点节点的空间
	//root = NULL;//这里将root置为空指针没有意义,因为这个函数的参数是 值传递 ,
	//是将指针root存放的地址拷贝了一份给函数内部创建的指针root,我们是想将函数外的指针root置为空指针,
	//这里因为是值传递,所以只是将函数内部创建的临时指针root置为空,值传递形参的改变不影响实参,
	//所以函数外部的指针root依旧存放的是动态开辟的 大小是结构体类型 的空间的地址,并没有变为空指针NULL。
	//这里如果非要改变,那么就用二级指针,或者不用管,因为整个程序结束后,申请的所有空间都会销毁(返还)
}

 

四、二叉树的层序遍历(用的多)

//层序遍历二叉树的节点的数据(需要用到队列)
void LevelOrder(BTNode* root)//传指向二叉树根节点的指针
{
	// 核心思路:上一层出的时候带下一层节点进;
	//队列里的元素是指向二叉树节点的指针

	Queue q;//创建一个结构体类型Queue的变量,这个结构体里放的是
	        //一个指向第一个节点的指针head和一个指向尾节点的指针tail

	QueueInit(&q);//初始化这个结构体,地址传递,可以改变实参

	if (root)//判断二叉树是否有节点
		QueuePush(&q, root);//将 指向二叉树根节点的指针 作为元素 队尾入队列里
	                 //此时队列里 只有 指向二叉树根节点的指针这一个元素

	while (!QueueEmpty(&q))//队列里非空,就继续;队列空,就跳出循环
	{
		BTNode* front = QueueFront(&q);//将对头的元素由临时变量存放
		QueuePop(&q);//对头出 队列对头的元素
		printf("%c ", front->data);//打印 对头的元素 里存放的元素
		                           //即打印的二叉树节点里存放的数据

		if (front->left)//该节点的左子树不为空指针,则将左子树队尾入队列里
		{
			QueuePush(&q, front->left);
		}

		if (front->right)//该节点的右子树不为空指针,则将右子树队尾入队列里
		{
			QueuePush(&q, front->right);
		}
	}
	
	printf("\n");

	QueueDestory(&q);//销毁队列的空间
}


 

 

五、总代码


 

 

六、代码运行实例

前序遍历的顺序:A B D NULL NULL E NULL NULL C NULL NULL
中序遍历的顺序:NULL D NULL B NULL E NULL A NULL C NULL
后序遍历的顺序:NULL NULL D NULL NULL E B NULL NULL C A
节点A作为第一个根节点的二叉树元素个数:5
节点B作为第一个根节点的二叉树元素个数:3
节点A作为第一个根节点的二叉树叶子节点的个数:3
节点B作为第一个根节点的二叉树叶子节点的个数:2
举报

相关推荐

0 条评论