生成树:一个连通图的生成树是一个极小连通子图,它包含图中全部顶点,但只有足以构成一棵树的n-1条边。
e<n-1 → 非连通图
e>n-1 → 有回路
e=n-1 → 不一定都是图的生成树
设E(G)为连通图G中所有边的集合,则从图中任一顶点出发遍历图时,必定将E(G)分成两个集合T(G)和B(G),其中T(G)是遍历图过程中历经的边的集合;B(G)是剩余的边的集合。
显然,T(G)和图G中所有顶点一起构成连通图G的极小连通子图,它是连通图的一棵生成树。
由深度优先搜索得到的为深度优先生成树;由广度优先搜索得到的为广度优先生成树。
树的孩子兄弟表示法:又称二叉树表示法,或二叉链表表示法。即以二叉链表作为树的存储结构。 链表中结点的两个链域分别指向该结点的第一个孩子结点和下一个兄弟结点。
typedef struct CSNode
{
ElemType data;
struct CSNode *firstchild,*nextsibling;
}CSNode, *CSTree;
void DFSForest(Graph G, CSTree &T) //建立无向图 G 的深度优先生成森林的孩子兄弟链表 T
{
T = NULL;
for (v=0; v<G.vexnum; ++v) visited[v] = FALSE;
for (v=0; v<G.vexnum; ++v)
if (!visited[v])
{ // 第v顶点为新的生成树的根结点
p= (CSTree)malloc(sizeof(CSNode));//分配根结点
p->data=GetVex(G,v); // 给该结点赋值
p->firstchild=NULL;
p->nextsibling=NULL;
if (!T) T = p; // 是第一棵生成树的根(T的根)
else // 其它生成树的根(前一棵的根的“兄弟”)
q->nextsibling = p;
q = p; // q指示当前生成树的根
DFSTree(G, v, p); // 建立以p为根的生成树
} //if
} // DFSForest
void DFSTree(Graph G, int v, CSTree &T)//第v个顶点出发深度优先遍历图G,建立以T为根的生成树
{
visited[v] = TRUE;
first =TRUE;
for (w=FirstAdjVex(G, v); w>=0; w=NextAdjVex(G, v, w))
if (!visited[w])
{ p = (CSTree) malloc (sizeof (CSNode));//分配孩子结点
p->data = GetVex(G,w);
p->firstchild=NULL;
p->nextsibling=NULL;
if (first)
{ // w是v的第一个未被访问的邻接顶点
T->firstchild = p;
first = FALSE; // 是根的左孩子结点
}
else // w是v的其它未被访问的邻接顶点
q->nextsibling = p;// 是上一邻接顶点的右兄弟结点
q = p; DFSTree(G,w,q) ;
} //if
} // DFSTree