1. 用二叉树表示树和森林
1.1 二叉树表示树
使用“孩子——兄弟”存储结构将一棵树转换为二叉树。该二叉树的结点结构有3个域:
1)数据域data,存放结点数据。
2)左链域child, 指向该结点的第一个孩子结点。
3)右链域brother,指向该结点的下一个兄弟结点。
给定一棵树,有唯一的二叉树与之对应。根结点的右链域为空。
1.2 二叉树表示森林
转换过程为:
1)将森林中的每棵树转换为二叉树。
2)用每棵树的根结点的brother链将若干树的二叉树表示式连接成一棵完整的二叉树,如下图所示。
1.3 二叉树还原为树
1) 删除原二叉树中所有父亲结点与右孩子的连线。
2) 若某个结点是其父结点的左孩子,则把该结点的右孩子、右孩子的右孩子等等都与该结点的父结点用线连起来。
2. 最小代价生成树
2.1 最小代价生成树的性质
最小代价生成树(minimum cost spanning tree, MCST):连通图(图中任意两个不同的结点之间都是连通的)的生成树中代价最小的树,具有4个性质:
1) 包含图中的n个结点;
2) 包含且仅包含图中的n-1条边;
3) 不包含产生回路的边;
4) 最小生成树是权值之和最小的生成树。
2.2 构造最小代价生成树的算法
2.2.1 克鲁斯卡尔(Kruskal)算法
Kruskal算法的基本思想:
1)最初先构造一个包含全部n个结点、但无边的森林T={T1,T2,T3,…,Tn};
2)然后依照边的权值从小到大的顺序,逐边将它们放回到所关联的结点上,但删除会生成回路的边;
3)由于边的加入,使得T中的某两棵树合并为一棵,所以森林中的树减少1棵,经过n-1步,最终得到一棵包含n-1条边的最小代价生成树。
Kruskal算法描述为:
1)构造n个结点和0条边的森林:依照边权值大小从小到大对边进行排序;
2)进入循环,依次选择权值最小、但其加入不产生回路的边加入森林,直到森林变成一棵树为止,如下图所示。
注意:并非每一条当前权值最小的边都可以选择,需要判断是否形成环。
2.2.2 普里姆(Prim)算法
Prim算法从带权连通图的某个结点开始逐步扩张成一棵生成树,算法如下:
1)生成树T初始仅仅包含初始结点V0;
2)进入循环,算法的每一步都是选择与T相关的具有最小权值的边(u,v),其中u在树上,但是v不在树上。直到产生一个n-1条边的生成树,如下图所示:
注意:树中不能有环。