一. 二叉树的性质
1. 满二叉树
在一棵二叉树上,如果所有分支结点都存在左子树和右子树,并且所有叶子都在一层上,这样的二叉树称为满二叉树。
特点:
- 叶子只能出现在最下一层,出现在其它层就不可能达到平衡
- 非叶子结点的度一定为2
- 在同样深度的二叉树中,满二叉树结点个数最多,叶子数最多
2. 完全二叉树
对一棵具有n个结点的二叉树按层序编号,如果编号为i(1<=i<=n)的结点与同样深度的满二叉树中编号为 i 的结点在二叉树中的位置完全相同,则称这棵二叉树为完全二叉树。
特点:
- 叶子节点只能出现在最下两层
- 最下层的叶子一定集中在左部连续位置
- 倒数两层,若有叶子结点,一定都在右部连续位置
- 如果结点度为 1 ,则该结点只有左孩子,即不存在只有右子树的情况
- 同样结点的二叉树,完全二叉树深度最小
3. 二叉树的性质
- 在二叉树的第i(i>=1)层最多有
2^(i - 1)
个结点。 - 深度为k(k>=0)的二叉树最少有k个结点,最多有
2^k-1
个结点。 - 对于任一棵非空二叉树,若其叶结点数为n0,度为2的非叶结点数为n2,则
n0 = n2 +1
。 - 具有n个结点的完全二叉树的深度为
int_UP(log(2,n+1))
。 - 如果将一棵有n个结点的完全二叉树自顶向下,同一层自左向右连续给结点编号1,2,3,......,n,然后按此结点编号将树中各结点顺序的存放于一个一维数组,并简称编号为i的结点为结点i( i>=1 && i<=n),则有以下关系:
(1)若 i= 1,则结点 i 为根,无父结点;若 i> 1,则结点 i 的父结点为结点int_DOWN(i / 2)
;
(2)若 2*i <= n,则结点 i 的左子女为结点2*i
;
(3)若2*i<=n,则结点i的右子女为结点2*i+1
;
(4)若结点编号i为奇数,且i!=1,它处于右兄弟位置,则它的左兄弟为结点i-1
;
(5)若结点编号i为偶数,且i!=n,它处于左兄弟位置,则它的右兄弟为结点i+1
;
(6)结点i所在的层次为int_DOWN(log(2,i))+1
。
二. 二叉链表
1. 二叉树的结构
typedef char TElemType;
typedef struct BiTNode
{
TElemType data;
struct BiTNode* lchild, * rchild; //左右孩子指针
}BiTNode,*BiTree;
2. 二叉树的遍历
采用函数递归的思想
前序遍历:
若二叉树为空,则空操作返回,
否则: 根结点->左子树->右子树
void Preorder(BiTree T)
{
if (T == NULL)
{
return;
}
printf("%c",T->data);
Preorder(T->lchild);
Preorder(T->rchild);
}
中序遍历:
若二叉树为空,则空操作返回,
否则:左子树->根结点->右子树
void Inorder(BiTree T)
{
if (T == NULL)
{
return;
}
Inorder(T->lchild);
printf("%c",T->data);
Inorder(T->rchild);
}
后序遍历:
若二叉树为空,则空操作返回,
否则:左子树->右子树->根结点
void Postorder(BiTree T)
{
if (T == NULL)
{
return;
}
Postorder(T->lchild);
Postorder(T->rchild);
printf("%c", T->data);
}
3. 二叉树的建立
为了确定每个结点是否有左右孩子,我们将二叉树中每个结点的空指针引出一个虚结点,其值为一特定值如 “#”
//按前序输入
void CreatBiTree(BiTree *T) //二级指针
{
TElemType ch;
scanf("%c",&ch);
if (ch == '#')
{
*T = NULL;
}
else
{
*T = (BiTree)malloc(sizeof(BiTNode));
if (!*T)
{
return;
}
(*T)->data = ch; //生成根结点
CreatBiTree(&(*T)->lchild);//构造左子树
CreatBiTree(&(*T)->rchild);//构造右子树
}
}
利用字符串建立二叉树:
//T:二级指针; str:传入的字符串; n:当前字符串的位数
int CreatBiTree2(BiTree* T,char *str,int n)
{
char ch = str[n];
n++;
if (str[n] != '\0') //字符串末尾
{
if (ch == '#')
{
*T = NULL;
}
else
{
*T = (BiTree)malloc(sizeof(BiTree));
if (!*T)
{
return;
}
(*T)->data = ch; //生成根结点
n = CreatBiTree2(&(*T)->lchild,str,n);//构造左子树
n = CreatBiTree2(&(*T)->rchild,str,n);//构造右子树
}
}
return n;
}
若要按照后序或中序输入,只需调整构造根结点与左右子树的顺序即可
4. 求二叉树叶子结点
int num = 0;
void CalculateTree(BiTree T)
{
if(!T)
{
return ;
}
//若为叶子
if(!T->lchild && !T->rchild)
{
num++;
}
//左子树叶子结点数目
CalculateTree(T->lchild);
//右子树叶子结点数目
CalculateTree(T->rchild);
}
或
int Num(BiTree T)
{
int num,num1,num2;
if(T==NULL)
{
num=0;
}
else
{
if(T->lchild==NULL&&T->rchild==NULL)
{
num=1;
}
else
{
num1=Num(T->lchild);
num2=Num(T->rchild);
num=num1+num2;
}
}
return num;
}
5. 求二叉树的高度
int CaculateTreDepth(BiTree T){
if(T == NULL)
{
return 0;
}
int depth = 0;
int leftDepth = CaculateTreDepth(root->lchild);
int rightDepth = CaculateTreDepth(root->rchild);
depth = leftDepth > rightDepth ? leftDepth + 1 : rightDepth + 1;
return depth;
}