1.
树概念及结构
(1)树的概念:
树是一种
非线性
的数据结构,它是由
n
(
n>=0
)个有限结点组成一个具有层次关系的集合。
把它叫做树是因
为它看起来像一棵倒挂的树,也就是说它是根朝上,而叶朝下的
。
注意:<1>有一个特殊的结点,称为根结点,根节点没有前驱结点
<2>除根节点外,其余结点被分成M(M>0)个互不相交的集合T1、T2、……、Tm,其中每一个集合Ti(1<= i <= m)又是一棵结构与树类似的子树。每棵子树的根结点有且只有一个前驱,可以有0个或多个后继.即:树是递归进行定义的。
注意:树形结构中,子树之间不能有交集,否则就不是树形结构
![](https://i-blog.csdnimg.cn/blog_migrate/8c4b3ec21a1f4ff6d68fbdb570cb6211.png)
树的相关概念:
![](https://i-blog.csdnimg.cn/blog_migrate/687368513ac1ef0f6fa462ec6c3a3fd0.png)
节点的度
:一个节点含有的子树的个数称为该节点的度; 如上图:
A
的为
6
叶节点或终端节点
:度为
0
的节点称为叶节点; 如上图:
B
、
C
、
H
、
I...
等节点为叶节点
非终端节点或分支节点
:度不为
0
的节点; 如上图:
D
、
E
、
F
、
G...
等节点为分支节点
双亲节点或父节点
:若一个节点含有子节点,则这个节点称为其子节点的父节点; 如上图:
A
是
B
的父节点
孩子节点或子节点
:一个节点含有的子树的根节点称为该节点的子节点; 如上图:
B
是
A
的孩子节点
兄弟节点
:具有相同父节点的节点互称为兄弟节点; 如上图:
B
、
C
是兄弟节点
树的度
:一棵树中,最大的节点的度称为树的度; 如上图:树的度为
6
节点的层次
:从根开始定义起,根为第
1
层,根的子节点为第
2
层,以此类推
树的高度或深度
:树中节点的最大层次; 如上图:树的高度为
4
堂兄弟节点
:双亲在同一层的节点互为堂兄弟;如上图:
H
、
I
互为兄弟节点
堂兄弟节点
:双亲在同一层的节点互为堂兄弟;如上图:
H
、
I
互为兄弟节点
节点的祖先
:从根到该节点所经分支上的所有节点;如上图:
A
是所有节点的祖先
子孙
:以某节点为根的子树中任一节点都称为该节点的子孙。如上图:所有节点都是
A
的子孙
森林
:由
m
(
m>0
)棵互不相交的树的集合称为森林;
树的表示
树结构相对线性表就比较复杂了,要存储表示起来就比较麻烦了,
既然保存值域,也要保存结点和结点之间
的关系
,实际中树有很多种表示方式如:双亲表示法,孩子表示法、孩子双亲表示法以及孩子兄弟表示法 等。我们这里就简单的了解其中最常用的孩子兄弟表示法
。
![](https://i-blog.csdnimg.cn/blog_migrate/cbe30280a121f528a9a95a4b119ef1db.png)
2.
二叉树概念及结构
概念:
一棵二叉树是结点的一个有限集合,该集合:(1)或者为空 (2)
由一个根节点加上两棵别称为左子树和右子树的二叉树组成
![](https://i-blog.csdnimg.cn/blog_migrate/2ef8e89e8bd9b00f864ace92a6adb7df.png)
即:(1)
二叉树不存在度大于
2的结点(2)二叉树的子树有左右之分,次序不能颠倒,因此二叉树是有序树
注意:对于任意的二叉树都是由以下几种情况复合而成的:
![](https://i-blog.csdnimg.cn/blog_migrate/cc11d00db95a9e5a5ca7ce49a5407cb9.png)
特殊的二叉树:
(1)
满二叉树
:一个二叉树,如果每一个层的结点数都达到最大值,则这个二叉树就是满二叉树。也就是
说,如果一个二叉树的层数为K,且结点总数是
,则它就是满二叉树。
![](https://i-blog.csdnimg.cn/blog_migrate/c7b94f25340e49644d3f0cba77320210.png)
(2)
完全二叉树
:完全二叉树是效率很高的数据结构,完全二叉树是由满二叉树而引出来的。对于深度为
K
的,有
n
个结点的二叉树,当且仅当其每一个结点都与深度为
K
的满二叉树中编号从
1
至
n
的结点一一对
应时称之为完全二叉树。 要注意的是满二叉树是一种特殊的完全二叉树。
二叉树的性质 :
![](https://i-blog.csdnimg.cn/blog_migrate/d95f616fdae06db5d51da35a66211e34.png)
![](https://i-blog.csdnimg.cn/blog_migrate/17f9b21b6f02e5c782a989e78e92d607.png)
二叉树的存储结构 :
二叉树一般可以使用两种结构存储,一种顺序结构,一种链式结构。
(1)顺序存储:
顺序结构存储就是使用
数组来存储
,一般使用数组
只适合表示完全二叉树
,因为不是完全二叉树会有空
间的浪费。而现实中使用中只有堆才会使用数组来存储,关于堆我们后面的章节会专门讲解。
二叉树顺
序存储在物理上是一个数组,在逻辑上是一颗二叉树。
![](https://i-blog.csdnimg.cn/blog_migrate/14eb454ed8ae5e581efe0156e1e91070.png)
(2)链式存储:
二叉树的链式存储结构是指,用链表来表示一棵二叉树,即用链来指示元素的逻辑关系。 通常的方法是
链表中每个结点由三个域组成,数据域和左右指针域,左右指针分别用来给出该结点左孩子和右孩子所
在的链结点的存储地址 。
![](https://i-blog.csdnimg.cn/blog_migrate/e5d616e9db12e9b11c5e0da39cc938d7.png)
相关代码:
typedef int BTDataType;
typedef struct BinaTreeNode
{
BTDataType val;
struct BinaTreeNode* left;
struct BinaTreeNode* right;
}BTNode;
//前序遍历
void PrevOrder(BTNode* root)
{
if (root == NULL)
{
printf("NULL ");
return;
}
printf("%d ", root->val);
PrevOrder(root->left);
PrevOrder(root->right);
}
//中序遍历
void InOrder(BTNode* root)
{
if (root == NULL)
{
printf("NULL ");
return;
}
InOrder(root->left);
printf("%d ", root->val);
InOrder(root->right);
}
//后序遍历
void PostOrder(BTNode* root)
{
if (root == NULL)
{
printf("NULL ");
return;
}
PostOrder(root->left);
PostOrder(root->right);
printf("%d ", root->val);
}
//创建一个新的结点
BTNode* BuyBTNode(BTDataType x)
{
BTNode* node = (BTNode*)malloc(sizeof(BTNode));
if (node == NULL)
{
perror("malloc fail");
exit(-1);
}
node->val = x;
node->left = node->right = NULL;
return node;
}
//求二叉树的结点个数
int TreeSize(BTNode* root)
{
return root == NULL ? 0 : TreeSize(root->left) + TreeSize(root->right) + 1;
}
//求叶子结点的个数
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);
}
//求树的高度或则是深度
int TreeHight(BTNode* root)
{
if (root == NULL)
return 0;
int left_hight = TreeHight(root->left) + 1;
int right_hight = TreeHight(root->right) + 1;
return left_hight > right_hight ? left_hight : right_hight;
}
int TreeHeight(BTNode* root)
{
if (root == NULL)
{
return 0;
}
int leftHeight = TreeHeight(root->left);
int rightHeight = TreeHeight(root->right);
return leftHeight > rightHeight ? leftHeight + 1 : rightHeight + 1;
}
//求地k层的结点个数
int TreeKLevelSize(BTNode* root, int k)
{
if (root == NULL)
return 0;
if (k == 1)
return 1;
return TreeKLevelSize(root->left, k - 1) + TreeKLevelSize(root->right, k - 1);
}
//找值为X的点
BTNode* TreeFind(BTNode* root, BTDataType x)
{
if (root == NULL)
return NULL;
if (root->val == x)
return root;
BTNode* left = TreeFind(root->left, x);
if (left)
return left;
BTNode* right = TreeFind(root->right, x);
if (right)
return right;
return NULL;
}
//销毁
void TreeDestroy(BTNode* root)
{
if (root == NULL)
return;
TreeDestroy(root->left);
TreeDestroy(root->right);
free(root);
}
对于二叉树的层序遍历,需要用到队列进行解决问题:首先建立一个队列,首先入的根结点,当根结点从队列出的时候,将根的左子树和右子树入队列。后面的结点同理。
层序遍历
void LevelOrder(BTNode* root)
{
Queue q;
QueueInit(&q);
if (root)
QueuePush(&q, root);
while (!QueueEmpty(&q))
{
BTNode* front = QueueFront(&q);
printf("%d ", front->data);
QueuePop(&q);
if (front->left)
{
QueuePush(&q, front->left);
}
if (front->right)
{
QueuePush(&q, front->right);
}
}
printf("\n");
QueueDestroy(&q);
}
题:
bool isSameTree(TreeNode* p, TreeNode* q)
{
if(p == nullptr && q == nullptr)
return true;
if(p == nullptr || q == nullptr)
return false;
if(p->val != q->val)
return false;
return isSameTree(p->left,q->left) && isSameTree(p->right,q->right);
}