数据结构与算法----二叉树 (1)

目录

1. 树的相关知识

1.1 树的的定义

1.2 数的特性

1.3 树的相关概念

1.4 树的常见表示法

1.4.1 孩子兄弟表示法

 1.4.2 双亲表示法

2. 二叉树的相关知识

2.1 二叉树的概念

2.2 二叉树的特点

2.3 二叉树的前中后序

2.4 前中后序的代码实现

2.4.1 快速构建二叉树

2.4.2 通过递归来书写前序

2.4.3 完整代码 


1. 树的相关知识

1.1 树的的定义

树是一种非线性的数据结构(线性的数据结构:顺序表,链表,栈,队列),它是由n(n>=0)个有限结点,组成一个具有层次关系的集合。之所以称其为树,原因是它像一颗倒挂的树。

1.2 数的特性

·树有一个特殊的结点,称其为根结点,根结点木有前驱结点。

·除去根结点外,其余的结点被分为M(M>0)个不相交的集合,其中的每一个集合又是一颗结构与树类似的子树。每棵子树的根结点有且只有一个前驱,可以有0个或多个后继。

·因此树是由递归定义的。

1.3 树的相关概念

 

节点的度:一个节点含有的子树的个数称为该节点的度。如上图:A的为6。
叶节点或终端节点:度为0的节点称为叶节点;如上图:B、C、H、I...等节点为叶节点。
非终端节点或分支节点:度不为0的节点;如上图:D、E、F、G...等节点为分支节点。
双亲节点或父节点:若一个节点含有子节点,则这个节点称为其子节点的父节点;如上图:A是B的父节点 。

孩子节点或子节点:一个节点含有的子树的根节点称为该节点的子节点;如上图:B是A的孩子节点。
兄弟节点:具有相同父节点的节点互称为兄弟节点;如上图:B、C是兄弟节点。
树的度:一棵树中,最大的节点的度称为树的度;如上图:树的度为6。
节点的层次:从根开始定义起,根为第1层,根的子节点为第2层,以此类推。

树的高度或深度:树中节点的最大层次;如上图:树的高度为4。
节点的祖先:从根到该节点所经分支上的所有节点;如上图:A是所有节点的祖先。
子孙:以某节点为根的子树中任一节点都称为该节点的子孙。如上图:所有节点都是A的子孙
森林:由m(m>0)棵互不相交的多颗树的集合称为森林。(数据结构中的学习并查集本质就是一个森林)

注:还有一种说法认为节点的层次和树的深度是从0开始数的,那么当树为空树时其深度则为-1。

1.4 树的常见表示法

1.4.1 孩子兄弟表示法

一个数据域用来存储数据。两个指针域:一个用来指向他的孩子,另一个用来指向他的兄弟。没有孩子或兄弟指向空即可。

 1.4.2 双亲表示法

将节点信息存储在数组中,值指向双亲的下标,以此来表示各节点之间的关系。

 R的值为-1,不是一个有效的下标,代表其为根结点。

A的值为0,代表A的双亲是下标为0的节点。

F的值为3,代表F的双亲是下标为3的节点。

以此类推······

2. 二叉树的相关知识

2.1 二叉树的概念

一棵二叉树是结点的一个有限集合,该集合或者为空,或者是由一个根结点加上两棵别称为左子树和右子树的二叉树组成。

2.2 二叉树的特点

1. 每个结点最多有两棵子树,即二叉树不存在度大于2的结点。

2. 二叉树的子树有左右之分,并且顺序不能颠倒。

根据二叉树的特点,对于任何一个二叉树,都可以看成三部分:根结点,左子树,右子树。

2.3 二叉树的前中后序

在讲解该问题之前,我们得先了解一下分治算法,分治:分而治之,将大问题分成类似的子问题,子问题再分成子问题······,直到子问题不可被分割。  

例如对于上图中的二叉树,还可以进行如下分割:将B看作根结点,D为左子树,E为右子树。

将D看作根结点,他的左右子树都为NULL,即分割到此后不可再次分割。将E和C看作根结点同理。

为什么树要分前中后序? 

树的遍历十分讲究,它的遍历不同于链表(链表要么从后往前遍历,要么从前往后遍历),后续求树的节点个数,最大深度等都可能会涉及到二叉树的遍历。既然这样树的遍历分割为前序,中序, 和后序。

 

前序:遍历二叉树时先是根结点,再是左子树,最后是右子树。上图二叉树的前序为:A  B  D  NULL  NULL  E  NULL  NULL  C  NULL  NULL 。(不写NULL也行,但写NULL更能解释其本质)

就是用分治算法来分析得到结果的。A为根结点,A的左下为A的左子树,A的右下为A的右子树。

对A左子树进行同样的操作,B为根结点,B的左下为B的左子树,B的右下为B的右子树。以此类推,根据前序的特点,就可写出该二叉树的前序。

中序:遍历二叉树时先是左子树,再是根结点,最后是右子树。原理同上,中序:NULL  D  NULL  B  NULL  E  NULL  A  NULL  C  NULL。

后序:遍历二叉树时先是左子树,再是右子树,最后是根结点。这个就交给你们咯。

2.4 前中后序的代码实现

2.4.1 快速构建二叉树

定义一个结构体类型,成员包括一个存放数据的变量,一个指向左边的孩子的结构体指针,一个指向右边的孩子的结构体指针。通过动态开辟内存的方式创建结点,最后再进行结点之间的连接。

typedef char B_T_DATA_TYPE;
typedef struct BinaryTreeNode BTNode;

struct BinaryTreeNode
{
	B_T_DATA_TYPE data;
	//根结点的左孩子
	struct BinaryTreeNode* left;
	//根结点的右孩子
	struct BinaryTreeNode* right;
};

int main()
{
	//创建结点
	BTNode* A = (BTNode*)malloc(sizeof(BTNode));
	A->data = 'A';
	A->left = NULL;
	A->right = NULL;

	BTNode* B = (BTNode*)malloc(sizeof(BTNode));
	B->data = 'B';
	B->left = NULL;
	B->right = NULL;

	BTNode* C = (BTNode*)malloc(sizeof(BTNode));
	C->data = 'C';
	C->left = NULL;
	C->right = NULL;

	BTNode* D = (BTNode*)malloc(sizeof(BTNode));
	D->data = 'D';
	D->left = NULL;
	D->right = NULL;	
	
	BTNode* E = (BTNode*)malloc(sizeof(BTNode));
	E->data = 'A';
	E->left = NULL;
    E->right = NULL;

	//连接结点
	A->left = B;
	A->right = C;

	B->left = D;
	B->right = E;

2.4.2 通过递归来书写前序

void PrevOrder(BTNode* root)
{
	//递归结束条件
	if (root == NULL)
	{
		printf("NULL ");
		return;
	}
		
	printf("%c ", root->data);

	//左子树
	PrevOrder(root->left);
	//右子树
	PrevOrder(root->right);
}

2.4.3 完整代码 

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>


typedef char B_T_DATA_TYPE;
typedef struct BinaryTreeNode BTNode;

struct BinaryTreeNode
{
	B_T_DATA_TYPE data;
	//根结点的左孩子
	struct BinaryTreeNode* left;
	//根结点的右孩子
	struct BinaryTreeNode* right;
};

void PrevOrder(BTNode* root)
{
	//递归结束条件
	if (root == NULL)
	{
		printf("NULL ");
		return;
	}
		
	printf("%c ", root->data);

	//左子树
	PrevOrder(root->left);
	//右子树
	PrevOrder(root->right);
}

int main()
{
	//创建结点
	BTNode* A = (BTNode*)malloc(sizeof(BTNode));
	A->data = 'A';
	A->left = NULL;
	A->right = NULL;

	BTNode* B = (BTNode*)malloc(sizeof(BTNode));
	B->data = 'B';
	B->left = NULL;
	B->right = NULL;

	BTNode* C = (BTNode*)malloc(sizeof(BTNode));
	C->data = 'C';
	C->left = NULL;
	C->right = NULL;

	BTNode* D = (BTNode*)malloc(sizeof(BTNode));
	D->data = 'D';
	D->left = NULL;
	D->right = NULL;	
	
	BTNode* E = (BTNode*)malloc(sizeof(BTNode));
	E->data = 'A';
	E->left = NULL;
    E->right = NULL;

	//连接结点
	A->left = B;
	A->right = C;

	B->left = D;
	B->right = E;

	PrevOrder(A);
	printf("\n");

	return 0;
}

中序以及后序只需要改变递归时代码的顺序即可。 

                     

 

  • 8
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

姬如祎

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值