图的生成树,是图的连通子图,包含了图里所有顶点,但只含有顶点数减一条边。树里任何两个顶点都有通路。但树里没有环路。
生成树的过程和图的遍历过程类似,遍历时,图里每个顶点都会出现且仅出现一次。
因为表达树的途径,是表达出树里所有的边,边用边的两个顶点表示。生成树的过程,是要考虑如何输出所有的边的两个顶点。
在DFS和BFS的程序代码基础上,修改代码,表达出生成树的过程。言虽简单,但也很巧妙。我也是看了书中代码,才明白的。自己虽然写过DFS,BFS,但跟书中代码一样简洁的思路,想不到。当然,咱们也能想出自己的思路。
全部代码如下,先是main函数所在源文件:
#include<iostream>
#include<stdio.h>
using namespace std;
#define NUMVERTEX 11
#define INFINI 65555
struct GraphAdjaMatrix {
char vertexes[NUMVERTEX];
int edges[NUMVERTEX][NUMVERTEX];
int numVertexes;
int numEdges;
};
struct AdjaListNode {
int indexOfVertex;
int weightOfEdge;
AdjaListNode* pt;
};
struct AdjListHead {
char vertex;
AdjaListNode* pt;
};
struct GraphAdjaList {
AdjListHead vertexes[NUMVERTEX];
int numVertexes;
int numEdges;
};
extern void createGraphAdjMatrix(GraphAdjaMatrix &graphAdjMatrix,
int numVertexes,int numEdges,int edges[][NUMVERTEX],char vertexes[]);
extern void createGraphAdjList(GraphAdjaList& graphAdjList,
int numVertexes, int numEdges, int edges[][NUMVERTEX], char vertexes[]);
extern void dispalyGraphAdjMatrix(GraphAdjaMatrix &graphAdjMatrix);
extern void displayGrapgAdjList(GraphAdjaList& graphAdjList);
extern void spanningTreeDFS(GraphAdjaList& graphAdjList,int start,bool visited[]);
extern void spanningTreeBFS(GraphAdjaList& graphAdjList,int start,bool visited[]);
int main() {
GraphAdjaMatrix graphAdjMatrix ;
GraphAdjaList graphAdjList;
int numEdges = 13;
int edges[][NUMVERTEX] = {
{0,1,1,1,INFINI,INFINI,INFINI,INFINI,INFINI,INFINI,INFINI},
{1,0,INFINI,INFINI,1,1,INFINI,INFINI,INFINI,INFINI,INFINI},
{1,INFINI,0,1,INFINI,1,1,INFINI,INFINI,INFINI,INFINI},
{1,INFINI,1,0,INFINI,INFINI,INFINI,1,INFINI,INFINI,INFINI},
{INFINI,1,INFINI,INFINI,0,INFINI,INFINI,INFINI,INFINI,INFINI,INFINI},
{INFINI,1,1,INFINI,INFINI,0,INFINI,INFINI,INFINI,INFINI,INFINI},
{INFINI,INFINI,1,INFINI,INFINI,INFINI,0,1,1,1,INFINI},
{INFINI,INFINI,INFINI,1,INFINI,INFINI,1,0,INFINI,INFINI,1},
{INFINI,INFINI,INFINI,INFINI,INFINI,INFINI,1,INFINI,0,INFINI,INFINI},
{INFINI,INFINI,INFINI,INFINI,INFINI,INFINI,1,INFINI,INFINI,0,INFINI},
{INFINI,INFINI,INFINI,INFINI,INFINI,INFINI,INFINI,1,INFINI,INFINI,0}
};
char vertexes[] = {'0','1','2','3','4','5','6','7','8','9','S'};
createGraphAdjMatrix(graphAdjMatrix,NUMVERTEX,numEdges,edges,vertexes);
createGraphAdjList(graphAdjList,NUMVERTEX,numEdges,edges,vertexes);
dispalyGraphAdjMatrix(graphAdjMatrix);
displayGrapgAdjList(graphAdjList);
cout << endl;
cout << "spanning tree DFS : " << endl;
bool visited[NUMVERTEX];
for (int i = 0; i < NUMVERTEX; i++)
visited[i] = false;
spanningTreeDFS(graphAdjList,3,visited);
for (int i = 0; i < NUMVERTEX; i++)
visited[i] = false;
cout << endl << "spanning tree BFS : " << endl;
spanningTreeBFS(graphAdjList,3,visited);
return 0;
}
接着是各函数所在源文件代码:
#include<iostream>
#include<stdio.h>
using namespace std;
#define NUMVERTEX 11
#define INFINI 65555
struct GraphAdjaMatrix {
char vertexes[NUMVERTEX];
int edges[NUMVERTEX][NUMVERTEX];
int numVertexes;
int numEdges;
};
struct AdjaListNode {
int indexOfVertex;
int weightOfEdge;
AdjaListNode* pt;
};
struct AdjListHead {
char vertex;
AdjaListNode* pt;
};
struct GraphAdjaList {
AdjListHead vertexes[NUMVERTEX];
int numVertexes;
int numEdges;
};
void createGraphAdjMatrix(GraphAdjaMatrix &graphAdjMatrix,
int numVertexes, int numEdges, int edges[][NUMVERTEX], char vertexes[]) {
graphAdjMatrix.numVertexes = numVertexes;
graphAdjMatrix.numEdges = numEdges;
for (int i = 0; i < numVertexes; i++)
graphAdjMatrix.vertexes[i] = vertexes[i];
for (int row = 0; row < numVertexes; row++)
for (int column = 0; column < numVertexes; column++)
graphAdjMatrix.edges[row][column] = edges[row][column];
}
void createGraphAdjList(GraphAdjaList &graphAdjList,
int numVertexes, int numEdges, int edges[][NUMVERTEX], char vertexes[]){
graphAdjList.numEdges = numEdges;
graphAdjList.numVertexes = numVertexes;
for (int i = 0; i < numVertexes; i++)
graphAdjList.vertexes[i].pt = NULL;
for (int i = 0; i < numVertexes; i++)
graphAdjList.vertexes[i].vertex = vertexes[i];
AdjaListNode* ptTail = NULL,*ptNew;
int i, j;
for ( i = 0; i < numVertexes; i++)
for (j = 0; j < numVertexes; j++)
if (edges[i][j] != 0 && edges[i][j] != INFINI) {
ptNew = new AdjaListNode;
ptNew->indexOfVertex = j;
ptNew->weightOfEdge = edges[i][j];
if (graphAdjList.vertexes[i].pt == NULL) {
ptNew->pt = NULL;
graphAdjList.vertexes[i].pt = ptNew;
ptTail = ptNew;
}
else {
ptNew->pt = ptTail->pt;
ptTail->pt = ptNew;
ptTail = ptNew;
}
}
}
void dispalyGraphAdjMatrix(GraphAdjaMatrix &graphAdjMatrix) {
cout << "adjacensy matrix :" << endl;
int row,column;
printf("%3c",' ');
for (row = 0; row < graphAdjMatrix.numVertexes; row++)
printf("%3c",graphAdjMatrix.vertexes[row]);
printf("\n");
for (row = 0; row < graphAdjMatrix.numVertexes; row++) {
printf("%-3c", graphAdjMatrix.vertexes[row]);
for (column = 0; column < graphAdjMatrix.numVertexes; column++)
if (graphAdjMatrix.edges[row][column] == INFINI)
printf("%3s", "∞");
else
printf("%3d",graphAdjMatrix.edges[row][column]);
cout << endl;
}
}
void displayGrapgAdjList(GraphAdjaList &graphAdjList) {
cout << "graph adjacency list : " << endl;
AdjaListNode* pt;
int index;
for (int i = 0; i < graphAdjList.numVertexes; i++) {
printf("%2c:",graphAdjList.vertexes[i].vertex);
pt = graphAdjList.vertexes[i].pt;
while (pt != NULL) {
index = pt->indexOfVertex;
printf("%5c(%d)",graphAdjList.vertexes[index].vertex,pt->weightOfEdge);
pt = pt->pt;
}
cout << endl;
}
}
void spanningTreeDFS(GraphAdjaList& graphAdjList,int start,bool visited[]) {
visited[start] = true;
AdjaListNode* pt = graphAdjList.vertexes[start].pt;
while (pt != NULL) {
if (visited[pt->indexOfVertex] == false) {
cout << '(' << graphAdjList.vertexes[start].vertex << ',';
cout << graphAdjList.vertexes[pt->indexOfVertex].vertex << ") ";
spanningTreeDFS(graphAdjList,pt->indexOfVertex,visited);
}
pt = pt->pt;
}
}
void spanningTreeBFS(GraphAdjaList& graphAdjList,int start,bool visited[]) {
int queue[NUMVERTEX * 2],tail = 0,head = 0;
queue[tail] = start;
visited[start] = true;
AdjaListNode* pt;
while (head <= tail) {
pt = graphAdjList.vertexes[queue[head]].pt;
while (pt != NULL) {
if (visited[pt->indexOfVertex] == false) {
cout << '(' << graphAdjList.vertexes[queue[head]].vertex << ',';
cout << graphAdjList.vertexes[pt->indexOfVertex].vertex << ')' << " ";
visited[pt->indexOfVertex] = true;
tail++;
queue[tail] = pt->indexOfVertex;
}
pt = pt->pt;
}
head++;
}
}
图和测试结果和对应的生成树如下,因为顶点用字符表示,所以以字符S代表10号顶点:
对DFS和BFS代码的改编,需要对深度优先和广度优先遍历的过程有深刻的理解。以上过程结果也是正确的。谢谢阅读。