树概念及结构
树的结构:
树是一种非线性的数据结构,它是由n个有限节点组成一个具有层次关系的集合。把它叫做树是因为它看起来像一棵倒挂的树,即根朝上,叶朝下。
有一个特殊的节点,成为根节点,根节点没有前驱节点
除根节点外,其余节点被分成M个互不相交的集合T1、T2、······Tm,其中每一个集合Ti(1<i<m)又是一棵结构与树类似的子树。每棵子树的根节点有且只有一个前驱,可以有0个或多个后继。
因此,树是递归定义的。
有关树的一些定义:
- 结点的度:一个节点含有的子树的个数称为该节点的度;如上图:A的度为6
- 叶节点或终端节点:度为0的节点称为叶节点;如上图B、C、H、I···等节点为叶节点
- 非终端节点或分支节点:度不为0的节点;如上图:D、E、F、G····等节点为分支节点
- 双亲结点或父节点:若一个节点含有子节点,则这个节点称为其子节点的父节点;如上图:A是B的父节点
- 兄弟节点:具有相同父节点的节点互称为兄弟节点;如上图B、C是兄弟节点
- 树的度:一棵树中,最大的节点的度称为树的度;如上图:树的度为6
- 节点的层次:从根开始定义起,根为第一层,跟的子节点为第二层。依此类推
- 树的高度或深度:树中节点的最大层次;如上图,树的高度为4
- 结点的祖先:从根到该节点所经分支上的所有节点,如上图:所有节点都是A的子孙
- 森林:由m棵互不相交的多棵树的集合称为森林(并查集);
树的一种表示:
左孩子右兄弟
父节点只指向第一个子节点,其他子结点由第一个子节点指向。以此类推。
二叉树的概念及结构:
概念:一棵二叉树是结点的一个有限集合,该集合或者为空,或者是由一个根结点加上两棵别称为左子树和右子树的二叉树组成。
特殊的二叉树:
完全二叉树:
假设树的高度是h
- 前n-1层都是满的
- 最后一层不满,但是最后一层从左往右都是连续的
完全二叉树中度为1的结点最多有一个(1或0)
假设完全二叉树最后一层·缺了x个,x的范围[0,2^(h-1)-1],最后一层最少有一个节点
满二叉树:
假设一棵满二叉树的高度为h
总结点的个数:2^0+2^1+2^2……+2^(h-1)=N
2^h-1=N
搜索二叉树:
任何一棵树左子树都比根要小,右子树都比根要大 ,搜索中查找一个数,最多查找高度次
时间复杂度为O(N)
特点:
1. 每个结点最多有两棵子树,即二叉树不存在度大于2的结点
2. 二叉树的子树有左右之分,其子树的次序不能颠倒。
任何一棵二叉树由三个部分构成:
1. 根节点
2. 左子树
3.右子树
分治算法:分而治之,大问题分成类似子问题,子问题再分成子问题,直到子问题不可再分割
前序(先根):根 左子树 右子树
中序(中根):左子树 根 右子树
后序(后根):左子树 右子树 根
二叉树的性质:
- 若规定根节点的层数为1,则一棵非空二叉树的第i层上最多有2^(i-1)个结点
- 若规定根节点的层数为1,则深度为h的二叉树的最大节点数为2^h-1
- 对任何一棵二叉树,如果度为0其叶结点个数为n0,度为2的分支节点个数为n2,则n0=n2+1
- 若规定根节点的层数为1,具有n个结点的满二叉树的深度,h=log以2为底的N。
前序的实现:
先访问根结点,后访问左子树,访问左子树直到访问到空,再访问右子树,用递归即可实现。
typedef int BTDataType;
typedef struct BinaryTreeNode
{
struct BinaryTreeNode* left;
struct BinaryTreeNode* right;
BTDataType data;
}BTNode;
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 = 'E';
E->left = NULL;
E->right = NULL;
A->left = B;
A->right = C;
B->left = D;
B->right = E;
PrevOrder(A);
return 0;
}
中序:
void InOrder(BTNode* root)
{
if (root == NULL)
{
printf("NULL ");
return;
}
PrevOrder(root->left);
printf("%c ", root->data);
PrevOrder(root->right);
}
后序:
void PostOrder(BTNode* root)
{
if (root == NULL)
{
printf("NULL ");
return;
}
PrevOrder(root->left);
PrevOrder(root->right);
printf("%c ", root->data);
}
计算二叉树的结点个数
1.注意传size的地址
void TreeSize(BTNode* root,int* psize)
{
if (root == NULL)
return;
(*psize)++;
TreeSize(root->left,psize);
TreeSize(root->right,psize);
}
2.用递归思想直接解决:
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 && root->right == NULL)
return 1;
return TreeLeafSize(root->left) + TreeLeafSize(root->right);
}