数据结构:树的基本概念、二叉树、二叉搜索树、大小顶堆

树的基本概念

树是一种非线性的数据结构!学过图论的小伙伴可以跳过以下环节

树的定义:
①如果树的结点个数为0,则树为空树
②如果树的结点个数为1,则该结点是被称为根结点的结点
③如果树的结点个数大于1,则必存在一个称为根的结点,它的分支下是几个互不相交的有限集合,并且这些互不相交的有限集合本身又是一棵树。
(1)结点(node)
树的结点由数据元素及其若干分支组成,结点不仅包含数据元素,而且包含指向左右子树的分支
(2)结点的度(degree of node)
结点的度指的是结点分支的个数
(3)树的度
选取所有结点中最大的度,就是树的度
(4)叶子结点(leaf node)
度为0的结点就是叶子结点,它位于树最深层,并且树只要非空,就一定存在叶子结点
(5)非终端结点(分支结点
度大于0的结点为分支结点,显然除了叶子结点之外的结点都为分支结点。
(6)树的深度
1、结点的深度是从根节点到该结点路径上的结点个数
2、从某结点往下走尽可能到达多个叶子结点,对应多条通往这些叶子结点的路径,其中最长的就是该节点所在树的高度
3、根节点的高度就是树的高度
(7)有序树:树中结点的子树从左往右是有次序的,不能交换
无序树:子树无顺序,可以交换
丰满树:理想平衡树、除了最底层外,其他都是满的
(8)孩子、双亲、兄弟、祖先、子孙、堂兄弟结点,就是字面的意思了,这里就不一一解释了

树的存储结构

1、顺序存储结构
一般用数组表示父节点的索引,每个节点中只保存指向哪个结点是双亲结点的信息。
2、链式存储结构
事实上树是一种特殊的图,只是图是多对多的关系、树是一对多的关系
一般二叉树链式存储的ADT如下,这里就不细讲了。

struct TNode{
   
	ElementType Data;
	Tree Left;
	Tree Right;
};

二叉树

二叉树是每个节点最多有两个子树的树结构。它有五种基本形态:二叉树可以是空集;根可以有空的左子树或右子树;或者左、右子树皆为空。如下图所示
二叉树a:空二叉树
b:只有根节点
c:只有左子树的二叉树
d:只有右子树
e:有左右子树的二叉树
几种特殊的二叉树
1、斜二叉树
斜二叉树满二叉树
满二叉树
完全二叉树
完全二叉树只要按从大到小的顺序删除满二叉树,得到的就是完全二叉树
但是不能跳着删除

二叉树特有的性质

1、一个二叉树第 i 层的最大结点数为: 2^(i-1),i >= 1。
2、深度为k的二叉树有最大结点总数为: (2^k)-1,k >= 1。
3、对任何非空二叉树 T,若n0表示叶结点的个数、n1是度为1的非叶结点个数,n2是度为2的非叶结点个数,那么满足关系总结点n=n0+n1+n2,总分支为n1+2n2,总分支=n-1,
由这三个公式就能推出n0 = n2 +1
4、具有n(n>=1)个结点的完全二叉树的高度(深度)为 ⌈ log2(n+1) ⌉

二叉树的遍历

1、先序遍历
顺序:根->左子树->右子树
程序代码如下

/*先序遍历*/
void PreorderTraversal( BinTree BT ){
   
	if(BT == nullptr){
   
		return;
	}
	printf("%d ",BT->Data);
	PreorderTraversal(BT->Left);
	PreorderTraversal(BT->Right);
} 

2、 中序遍历
顺序:左子树->根->右子树

/*中序遍历*/
void PreorderTraversal( BinTree BT ){
   
	if(BT == nullptr){
   
		return;
	}
	PreorderTraversal(BT->Left);
	printf("%d ",BT->Data);
	PreorderTraversal(BT->Right);
} 

3、后序遍历
顺序:左子树->右子树->根

/*后序遍历*/
void PreorderTraversal( BinTree BT ){
   
	if(BT == nullptr){
   
		return;
	}
	PreorderTraversal(BT->Left);
	PreorderTraversal(BT->Right);
	printf("%d ",BT->Data);
} 

4、层序遍历
从上往下,从左往右读出结点的值。后面找叶子的时候会用到该方法,先空着,后期补上

二叉树的大多操作都会跟递归打交道,其实堆的底层实质就是一个模拟的完全二叉树!所以递归一般都能够实现,关于树的遍历也可以用非递归实现,这里就不贴源码了。

树的同构

(题目源于PAT)给定结点的数据,左右子树对应的索引,判断两颗树是否同构
图片源于PAT

输入格式:
输入给出2棵二叉树树的信息。对于每棵树,首先在一行中给出一个非负整数N (≤10),即该树的结点数(此时假设结点从0到N−1编号);随后N行,第i行对应编号第i个结点,给出该结点中存储的1个英文大写字母、其左孩子结点的编号、右孩子结点的编号。如果孩子结点为空,则在相应位置上给出“-”。给出的数据间用一个空格分隔。注意:题目保证每个结点中存储的字母是不同的。

输出格式:
如果两棵树是同构的,输出“Yes”,否则输出“No”。

 输入样例:
8
B 5 7
F - -
A 0 3
C 6 -
H - -
D - -
G 4 -
E 1 -
8
D 6 -
B 5 -
E - -
H - -
C 0 2
G - 3
F - -
A 1 4
输出案例:
No

结点和常量值定义如下

#define MaxTree 10
#define ElementType char
#define Tree int 
#define Null -1
struct TreeNode{
   
	ElementType Element;
	Tree left;
	Tree right;
}T1[MaxTree],T2[MaxTree];

建树

Tree BuildTree(struct TreeNode T[]){
   
	int num;
	char cL,cR,c;
	Tree Root = Null;
	cin >> num;
	Tree check[MaxTree] = {
   0};
	if(num){
   
		for(int i = 0;i < num;i++){
   
			
			cin >> T[i].Element >> cL >> cR;
			if(cL != '-'){
   
				T[i].left = cL- '0';
				check[T[i].left] = 1;
			}else{
   
				T[i].left = Null;
			}
			if(cR != '-'){
   
				T[i].right = cR- '0';
				check[T[i].right] = 1;
			}else{
   
				T[i].right = Null;
			}
		}
		for(int i = 0;i < num ; i++){
   
			if(check[i] == 0){
   
				Root =
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值