图里顶点的关系是顶点可以有多个前驱,多个后继。对于无向图,则不区分入边与出边,顶点间只区分有无边连接。图的遍历,是指不重不漏的访问到图里每个顶点,每个顶点访问一次。
深度优先DFS的思路可以概括为:依次遍历完第一个顶点的所有子图,其每个邻接点作为子图的代表,这样就完成了整个图的遍历,这个定义是递归的。BFS的思路可以概括为,先遍历完第一个顶点的所有邻接点,再遍历完所有邻接点的所有邻接点,依次类推,直至所有顶点都被遍历一次。
因为顶点间可以有多条路径,所有要为所有顶点建立一个是否访问过的数组,visited[].
感谢bilibili懒猫老师的讲解,让学生茅塞顿开。
各函数功能如下:
函数createGraphAdjMatrix:建立邻接矩阵。
函数createGraphAdjList:建立邻接表。
函数dispalyGraphAdjMatrix:在屏幕输出邻接矩阵的二维数组形式。
函数displayGrapgAdjList : 在屏幕输出邻接表的信息。
函数DFSTraverseAdjMatrix:深度优先递归遍历邻接矩阵。
函数DFSTraverseAdjList:深度优先递归遍历邻接表。
函数BFSAdjMatrix:广度优先遍历邻接矩阵。
函数BFSAdjList:广度优先遍历邻接表。
本程序适应的图要求是连通图或强连通图,即从任意顶点出发,总有路径到达任意顶点。
main函数所在源文件代码:
#include<iostream>
#include<stdio.h>
using namespace std;
#define MAXVERTEX 15
#define INFINI 65555
struct GraphAdjaMatrix {
char vertexes[MAXVERTEX];
int edges[MAXVERTEX][MAXVERTEX];
int numVertexes;
int numEdges;
};
struct AdjaListNode {
int indexOfVertex;
int weightOfEdge;
AdjaListNode* pt;
};
struct AdjListHead {
char vertex;
AdjaListNode* pt;
};
struct GraphAdjaList {
AdjListHead vertexes[MAXVERTEX];
int numVertexes;
int numEdges;
};
extern void createGraphAdjMatrix(GraphAdjaMatrix &graphAdjMatrix,
int numVertexes,int numEdges,int edges[][6],char vertexes[]);
extern void createGraphAdjList(GraphAdjaList& graphAdjList,
int numVertexes, int numEdges, int edges[][6], char vertexes[]);
extern void dispalyGraphAdjMatrix(GraphAdjaMatrix &graphAdjMatrix);
extern void displayGrapgAdjList(GraphAdjaList& graphAdjList);
extern void DFSTraverseAdjMatrix(GraphAdjaMatrix& graphAdjMatrix,
bool visited[],int row);
extern void DFSTraverseAdjList(GraphAdjaList& graphAdjList,
bool visited[], int index);
extern void BFSAdjMatrix(GraphAdjaMatrix& graphAdjMatrix,bool visited[]);
extern void BFSAdjList(GraphAdjaList& graphAdjList,bool visited[]);
int main() {
GraphAdjaMatrix graphAdjMatrix ;
GraphAdjaList graphAdjList;
int numVertexes = 6, numEdges = 10;
int edges[][6] = { {0,5,INFINI,7,INFINI,INFINI},
{INFINI,0,4,INFINI,INFINI,INFINI},
{8,INFINI,0,INFINI,INFINI,9},
{INFINI,INFINI,5,0,INFINI,6},
{INFINI,INFINI,INFINI,5,0,INFINI},
{3,INFINI,INFINI,INFINI,1,0} };
char vertexes[] = {'a','b','c','d','e','f'};
createGraphAdjMatrix(graphAdjMatrix,numVertexes,numEdges,edges,vertexes);
createGraphAdjList(graphAdjList,numVertexes,numEdges,edges,vertexes);
dispalyGraphAdjMatrix(graphAdjMatrix);
displayGrapgAdjList(graphAdjList);
cout << endl;
bool visited[MAXVERTEX] = {false};
cout << "depth first search adjacency matrix : ";
DFSTraverseAdjMatrix(graphAdjMatrix,visited,0);
cout << endl;
for (int i = 0; i < MAXVERTEX; i++)
visited[i] = false;
cout << "depth first search adjacency list : ";
DFSTraverseAdjList(graphAdjList,visited,0);
for (int i = 0; i < MAXVERTEX; i++)
visited[i] = false;
cout << endl<<endl;
cout << "breadth first search adjacency matrix : ";
BFSAdjMatrix(graphAdjMatrix,visited);
for (int i = 0; i < MAXVERTEX; i++)
visited[i] = false;
cout << endl;
cout << "breadth first search adjacency list : ";
BFSAdjList(graphAdjList, visited);
return 0;
}
各函数所在源文件代码:
#include<iostream>
#include<stdio.h>
using namespace std;
#define MAXVERTEX 15
#define INFINI 65555
struct GraphAdjaMatrix {
char vertexes[MAXVERTEX];
int edges[MAXVERTEX][MAXVERTEX];
int numVertexes;
int numEdges;
};
struct AdjaListNode {
int indexOfVertex;
int weightOfEdge;
AdjaListNode* pt;
};
struct AdjListHead {
char vertex;
AdjaListNode* pt;
};
struct GraphAdjaList {
AdjListHead vertexes[MAXVERTEX];
int numVertexes;
int numEdges;
};
void createGraphAdjMatrix(GraphAdjaMatrix &graphAdjMatrix,
int numVertexes, int numEdges, int edges[][6], 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[][6], char vertexes[]){
graphAdjList.numEdges = numEdges;
graphAdjList.numVertexes = numVertexes;
for (int i = 0; i < MAXVERTEX; 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 DFSTraverseAdjMatrix(GraphAdjaMatrix& graphAdjMatrix,
bool visited[],int row) {
cout << graphAdjMatrix.vertexes[row]<<" ";
visited[row] = true;
int column = 0;
for (; column < graphAdjMatrix.numVertexes; column++)
if (row != column && graphAdjMatrix.edges[row][column] != INFINI &&
visited[column] == false)
DFSTraverseAdjMatrix(graphAdjMatrix,visited,column);
}
void DFSTraverseAdjList(GraphAdjaList& graphAdjList,
bool visited[], int index) {
cout << graphAdjList.vertexes[index].vertex << " ";
visited[index] = true;
AdjaListNode* pt = graphAdjList.vertexes[index].pt;
while (pt != NULL) {
index = pt->indexOfVertex;
if (visited[index] == false)
DFSTraverseAdjList(graphAdjList,visited,index);
pt = pt->pt;
}
}
void BFSAdjMatrix(GraphAdjaMatrix& graphAdjMatrix, bool visited[]) {
int queueIndex[MAXVERTEX];
int tail = 0, head = 0;
int column;
queueIndex[tail] = 0;
while (head <= tail) {
cout << graphAdjMatrix.vertexes[head] << " ";
visited[head] = true;
for (column = 0; column < graphAdjMatrix.numVertexes; column++)
if (head != column && graphAdjMatrix.edges[head][column] != INFINI &&
visited[column] == false) {
tail = (tail + 1) % MAXVERTEX;
queueIndex[tail] = column;
}
head++;
}
}
void BFSAdjList(GraphAdjaList& graphAdjList, bool visited[]) {
int queueIndex[MAXVERTEX];
int head = 0, tail = 0;
queueIndex[tail] = 0;
AdjaListNode* pt;
while (head <= tail) {
cout << graphAdjList.vertexes[head].vertex << " ";
visited[head] = true;
pt = graphAdjList.vertexes[head].pt;
while (pt != NULL) {
if (visited[pt->indexOfVertex] == false) {
tail++;
queueIndex[tail] = pt->indexOfVertex;
}
pt = pt->pt;
}
head++;
}
}
这里的思路跟树的遍历很相似,学会了树的遍历,这里不会太难。测试结果及对应图如下:
谢谢阅读。