目录
对称矩阵
定义
1.对称矩阵中的元素关于主对角线对称,aij=aji,元素个数n^2
2.压缩存储,元素个数n(n+1)/2
//以下C语言函数的功能是将一维数组a中压缩存储的下三角4×4阶对称矩阵按矩阵格式输出。
print(int a[])
{
int i,j;
for(i=0;i<4;i++)
{
for(j=0;j<4;j++)
{
if(i>=j)
printf("%4d",a[i*(i+1)/2+j]);
else
printf("%4d",a[j*(j+1)/2+i]);
}
printf("\n");
}
}
树
定义
1.树(Tree)是n(n≥0)个有限数据元素的集合
2.n=0时,树为空树
3.树的根结点没有前驱结点,除根结点之外的所有结有且只有一个前驱结点
基本术语
1.结点:表示树中的元素
2.结点的度:结点子树的个数(该结点的子结点个数)
3.叶结点:度为0的结点(没有子结点)
4.分枝结点:度不为0的结点
5.树的度:各结点度的最大值
6.子结点(孩子结点)
7.父结点(双亲结点)
8.兄弟结点
9.结点的祖先:从根到该结点所经分支上的所有结点
10.子孙:以某结点为根的子树中的任一结点都称为该结点的子孙
11.结点的层数:从该结点到树的根结点的层数
12.堂兄弟结点:父结点在同一层且双亲结点不相同的结点互为堂兄弟结点
13.树的度(高度或深度):树中所有结点的最大层数称为树的度
14.路径、路径长度:结点的层数-1
15.有序树和无序树
16.森林:任何一棵树,删去根结点就变成了森林
二叉树
二叉树的五中基本形态
两类特殊的二叉树
满二叉树
结点个数:2^k-1
完全二叉树
二叉树的存储结构
顺序存储
二叉链表存储
三叉链表存储
二叉树的基本操作
1.建立一棵空二叉树
//初始化建立二叉树bt的头结点,0表示建立失败,1表示成功
int Initiate (BiTree bt)
{
if((bt=(BiTNode *)malloc(sizeof(BiTNode)))==NULL)
return 0;
bt->lchild=NULL;
bt->rchild=NULL;
return 1;
}
2.生成一棵二叉树
//生成一棵以x为根结点的数据域信息的二叉树
BiTree Create(elemtype x)
{
BiTree p;
if ((p=(BiTNode *)malloc(sizeof(BiTNode)))==NULL)
return NULL;
p->data=x;
p->lchild=NULL;
p->rchild=NULL;
return p;
}
3.二叉树中插入一个左子树结点
//在二叉树bt的结点parent的左子树中插入结点数据元素x
BiTree InsertL(BiTree bt,elemtype x,BiTree parent)
{
BiTree p;
if (parent==NULL)
{
printf(“\n插入出错”);
return NULL;
}
if ((p=(BiTNode *)malloc(sizeof(BiTNode)))==NULL)
return NULL;
p->data=x;
p->lchild=NULL;
p->rchild=NULL;
if (parent->lchild==NULL)
parent->lchild=p;
else
{
p->lchild=parent->lchild;
parent->lchild=p;
}
return bt;
}
4.二叉树中插入一个右子树结点
//在二叉树bt的结点parent的右子树中插入结点数据元素x
BiTree InsertR(BiTree bt,elemtype x,BiTree parent)
{
BiTree p;
if (parent==NULL)
{
printf(“\n插入出错”);
return NULL;
}
if ((p=(BiTNode *)malloc(sizeof(BiTNode)))==NULL)
return NULL;
p->data=x;
p->lchild=NULL;
p->rchild=NULL;
if (parent->rchild==NULL)
parent->rchild=p;
else
{
p->rchild=parent->rchild;
parent->rchild=p;
}
return bt;
}
5.删除结点parent的左子树
//在二叉树bt中删除结点parent的左子树
BiTree DeleteL(BiTree bt,BiTree parent)
{
BiTree p;
if (parent==NULL||parent->lchild==NULL)
{
printf("\n删除出错");
return NULL;
}
p=parent->lchild;
parent->lchild=NULL;
free(p);//当p为非叶结点时,这样删除仅释放了所删子树根结点的空间
return br;//若要删除子树分支中的结点,需用后面介绍的遍历操作来实现
}
6.删除结点parent的右子树
//在二叉树bt中删除结点parent的右子树
BiTree DeleteL(BiTree bt,BiTree parent)
{
BiTree p;
if (parent==NULL||parent->rchild==NULL)
{
printf("\n删除出错");
return NULL;
}
p=parent->rchild;
parent->rchild=NULL;
free(p);//当p为非叶结点时,这样删除仅释放了所删子树根结点的空间
return br;//若要删除子树分支中的结点,需用后面介绍的遍历操作来实现
}
二叉树的遍历
DLR(根左右 称为先序遍历)
int PreOrder(BiTree bt)
{
if (bt==NULL) //递归调用结束条件
return0;
Visit(bt->data);//访问结点的数据域
PreOrder(bt->lchild);//先序递归遍历bt左子树
PreOrder(bt->rchild);//先序递归遍历bt右子树
return 1;
}
LDR(左根右 称为中序遍历)
int MidOrder(BiTree bt)
{
if (bt==NULL) //递归调用结束条件
return0;
MidOrder(bt->lchild);//中序递归遍历bt左子树
Visit(bt->data);//访问结点的数据域
MidOrder(bt->rchild);//中序递归遍历bt右子树
return 1;
}
LRD(左右根 称为后序遍历)
int PostOrder(BiTree bt)
{
if (bt==NULL) //递归调用结束条件
return0;
PostOrder(bt->lchild);//后序递归遍历bt左子树
PostOrder(bt->rchild);//后序递归遍历bt右子树
Visit(bt->data);//访问结点的数据域
return 1;
}
线索二叉树
1.当结点有左子树,即lchild域不为空时,LTag为0
2.当结点没有左子树,即lchild为空时,令lchild域指向该结点的前驱,LTag为1
3.当结点有右子树,即rchild域不为空时,RTag为0
3.当结点没有右子树,即rchild为空时,令rchild域指向该结点的后继,RTag为1
先序线索二叉树
abdce
中序线索二叉树
bdaec
后序线索二叉树
dbeca
树和森林的存储
双亲存储法
孩子链表存储法
双亲孩子存储法
左孩子右兄弟存储法
二叉树、树和森林的转换
森林转换为二叉树(使用左孩子右兄弟的方法)
二叉树转换为树和森林
最优二叉树(哈夫曼树)
定义
1.指对于一组带有确定权值的叶结点,构造的具有最小带权路径长度的二叉树
2.结点的路径长度:从根结点到该结点的路径上分支的数目
3.结点权值:附加在结点上的信息
4.结点带权路径:结点上权值与该结点到根之间的路径长度的乘积
5.二叉树的路径长度:指由根结点到所有叶结点的路径长度之和
6.二叉树的带权路径长度:WPL(T) =Σwklk (权重为wk,路径为lk)
WPL(T)=1×2 +8×2 +5×3+7×4+2×2=65
哈夫曼树的建立过程
每次选两个最小的权构造哈夫曼树
哈夫曼编码
左分支代表0,右分支代表1
{5,2,10,6,7} 每次选两个最小的权构造哈夫曼树