树
概念:树(Tree)是(n>=0)个节点的有限集合T,它满足两个条件 :
有且仅有一个特定的称为根(Root)的节点;其余的节点可以分为m(m≥0)个互不相交的有限集合T1、T2、……、Tm,其中每一个集合又是一棵树,并称为其根的子树(Subtree)。
特征:一对多,每个节点最多有一个前驱,但可以有多个后继(根节点无前驱,叶节点无后继)
关于树的一些基本概念:
(1)度数:一个节点的子树的个数
(2)树度数:树中节点的最大度数
(3)叶节点或终端节点: 度数为零的节点
(4)分支节点:度数不为零的节点
(5)内部节点:除根节点以外的分支节点 (去掉根和叶子)
(6)节点层次: 根节点的层次为1,根节点子树的根为第2层,以此类推
(7)树的深度或高度: 树中所有节点层次的最大值
二叉树
1.概念:
二叉树(Binary Tree)是n(n≥0)个节点的有限集合,它或者是空集(n=0),或者是由一个根节点以及两棵互不相交的、分别称为左子树和右子树的二叉树组成。
二叉树与普通有序树不同,二叉树严格区分左孩子和右孩子,即使只有一个子节点也要区分左右。
2.满二叉树:出来叶子节点,每一个节点都有两个孩子
3.完全二叉树:最后两层节点可以有小于2的孩子
从下往上,从右往左删除的树
4.如果根节点编号为1:
左孩子节点编号为上一个节点k的关系 :2k
右孩子节点编号为上一个节点k的关系:2k+1
5.有一颗k层的树:最多有多少个节点:2^k -1 ;最少有多少个节点 :2^(k-1)
6.第k层最多有多少个节点 :2^(k-1)
7.任意一颗二叉树,度数0比度数2节点 多 1 : n0 = n2 + 1
最优二叉树
1. 赫夫曼(Huffman)树,又称最优树,是带权路径长度最短的树
2.WPL=树的带权*树的长度(层) 的和 ;WPL最小的二叉树就是最有二叉树
注意:(1)赫夫曼树的左右子树可以互换,因为这并不影响树的带权路径长度。
(2)带权值的节点都是叶子节点,不带权值的节点都是某棵子二叉树的根节点。
(3)权值越大的节点越靠近赫夫曼树的根节点,权值越小的节点越远离赫夫曼树的根节点。
(4)赫夫曼树中只有叶子节点和度为2的节点,没有度为1的节点
二叉树的存储:
顺序存储:非常浪费空间
链式存储:一般采用链式存储
二叉树的遍历:
前序遍历(根左右)
中序遍历(左根右)
后序遍历(左右根)
层次遍历
巧解:前序再节点左边画圆,中序的时候再节点正中下方画,后序再右边画
练习:
可以将子节点看为那一部分的根节点进行分析
二叉树的链式存储
结构体声明和一些宏
typedef char data_t;
typedef struct tree_node{
data_t data; //数据域
struct tree_node *lchild; //左子节点指针
struct tree_node *rchild; //右子节点指针
}bitree,*Pbitree;
创建二叉树
使用递归函数注意:递归函数容易造成死循环,一定要注意递归函数的结束条件
Pbitree createTree(int i,int n) //i为节点号,n为创建的个数
{
Pbitree root=(Pbitree)malloc(sizeof(bitree)); //根节点
if(NULL==root) return NULL;
root->data = i;
if(2*i<=n) //判断是否有左孩子
root->lchild=createTree(2*i,n); //有左孩子,递归创建一个
else
root->lchild=NULL; //没有左孩子
if(2*i+1<=n) //判断是否有有孩子
root->rchild = createTree(2*i+1,n); //有右孩子,递归创建一个
else
root->rchild=NULL; //没有右孩子
return root;
}
创建二叉树
Pbitree create_bittree()
{
Pbitree r=NULL;
char ch;
scanf("%c",&ch);
if('#'==ch) return NULL;
r=(Pbitree)malloc(sizeof(bitree));
if(NULL==r)
{
perror("malloc");
return NULL;
}
r->data=ch;
r->lchild=create_bitree();
r->rchild=create_bitree();
return r;
}
前序遍历
void front_tree(Pbitree root)
{
if(NULL==root) //递归结束条件
return ;
printf("%c" ,root->data); //根
front_tree(root->lchild); //左
front_tree(root->rchild); //右
}
中序遍历
void middle_tree(Pbitree root)
{
if(NULL==root) //递归结束条件
return ;
middle_tree(root->lchild); //左
printf("%c" ,root->data); //根
middle_tree(root->rchild); //右
}
后序遍历
void rear_tree(Pbitree root)
{
if(NULL==root) //递归结束条件
return ;
rear_tree(root->lchild); //左
rear_tree(root->rchild); //右
printf("%c" ,root->data); //根
}