图的深度和广度优先遍历
图的深度优先遍历
1、算法思想
- (1)从图中的某个初始点 v 出发,首先访问初始点 v.
- (2)选择一个与顶点 v 相邻且没被访问过的顶点 ver ,以 ver为初始顶点,再从它出发进行深度优先遍历。
- (3)当路径上被遍历完,就访问上一个顶点的第 二个相邻顶点。
- (4)直到所有与初始顶点 v联通的顶点都被访问。
2、邻接矩阵构造图
#include <iostream>
#include <vector>
using namespace std;
#define VERTEXNUM 5
void createGraph(vector<vector<int>>&edge, int start, int end);
void displayGraph(vector<vector<int>>&edge);
void DFS(vector<vector<int>>&edge , vector<int>& vertexStatusArr);
void DFScore(vector<vector<int>>&edge, int i, vector<int>& vertexStatusArr);
int main(void) {
//初始化邻接矩阵
vector<vector<int>>edge(VERTEXNUM, vector<int>(VERTEXNUM, 0));
//存放顶点的遍历状态,0:未遍历,1:已遍历
vector<int> vertexStatusArr (VERTEXNUM,0);
cout << "after init: " << endl;
displayGraph(edge);
//创建图
createGraph(edge, 0, 3);
createGraph(edge, 0, 4);
createGraph(edge, 3, 1);
createGraph(edge, 3, 2);
createGraph(edge, 4, 1);
cout << "after create: " << endl;
displayGraph(edge);
//深度优先遍历
DFS(edge, vertexStatusArr);
return 0;
}
//创建图
void createGraph(vector<vector<int>>&edge, int start, int end) {
edge[start][end] = 1;
}
//打印存储的图
void displayGraph(vector<vector<int>>&edge) {
int i, j;
for (i = 0; i<VERTEXNUM; i++) {
for (j = 0; j<VERTEXNUM; j++) {
//printf("%d ", edge[i][j]);
cout << edge[i][j] << " ";
}
cout << endl;
}
}
//深度优先遍历
void DFS(vector<vector<int>>&edge, vector<int>& vertexStatusArr) {
cout << "start BFT graph: " << endl;
for (int i = 0; i<VERTEXNUM; i++) {
DFScore(edge, i, vertexStatusArr);
}
cout << endl;
}
void DFScore(vector<vector<int>>&edge, int i, vector<int>& vertexStatusArr) {
if (vertexStatusArr[i] == 1) {
return;
}
cout << i << " ";
vertexStatusArr[i] = 1;
for (int j = 0; j<VERTEXNUM; j++) {
if (edge[i][j] == 1) {
DFScore(edge, j, vertexStatusArr);
}
}
}
设有n个点,e条边
邻接矩阵:矩阵包含n ^2
个元素,在算法中,共n个顶点,对每个顶点都要遍历n次,所以时间复杂度为O(n^2)
3、邻接表构造图
#include <stdio.h>
#include <malloc.h>
#define VERTEXNUM 5
//存放顶点的邻接表元素
typedef struct edge {
int vertex;
struct edge* next;
}st_edge;
void createGraph(st_edge** edge, int start, int end);
void displayGraph(st_edge** edge);
void delGraph(st_edge** edge);
void DFT(st_edge** edge, int* vertexStatusArr);
void DFTcore(st_edge** edge, int i, int* vertexStatusArr);
int main(void) {
//动态创建存放边的指针数组
st_edge** edge = (st_edge**)malloc(sizeof(st_edge*)*VERTEXNUM);
int i;
for (i = 0; i<VERTEXNUM; i++) {
edge[i] = NULL;
}
//存放顶点的遍历状态,0:未遍历,1:已遍历
int* vertexStatusArr = (int*)malloc(sizeof(int)*VERTEXNUM);
for (i = 0; i<VERTEXNUM; i++) {
vertexStatusArr[i] = 0;
}
printf("after init:\n");
displayGraph(edge);
//创建图
createGraph(edge, 0, 3);
createGraph(edge, 0, 4);
createGraph(edge, 3, 1);
createGraph(edge, 3, 2);
createGraph(edge, 4, 1);
printf("after create:\n");
displayGraph(edge);
//深度优先遍历
DFT(edge, vertexStatusArr);
//释放邻接表占用的内存
delGraph(edge);
edge = NULL;
free(vertexStatusArr);
vertexStatusArr = NULL;
return 0;
}
//创建图
void createGraph(st_edge** edge, int start, int end) {
st_edge* newedge = (st_edge*)malloc(sizeof(st_edge));
newedge->vertex = end;
newedge->next = NULL;
edge = edge + start;
while (*edge != NULL) {
edge = &((*edge)->next);
}
*edge = newedge;
}
//打印存储的图
void displayGraph(st_edge** edge) {
int i;
st_edge* p;
for (i = 0; i<VERTEXNUM; i++) {
printf("%d:", i);
p = *(edge + i);
while (p != NULL) {
printf("%d ", p->vertex);
p = p->next;
}
printf("\n");
}
}
//释放邻接表占用的内存
void delGraph(st_edge** edge) {
int i;
st_edge* p;
st_edge* del;
for (i = 0; i<VERTEXNUM; i++) {
p = *(edge + i);
while (p != NULL) {
del = p;
p = p->next;
free(del);
}
edge[i] = NULL;
}
free(edge);
}
//深度优先遍历
void DFT(st_edge** edge, int* vertexStatusArr) {
printf("start BFT graph:\n");
int i;
for (i = 0; i<VERTEXNUM; i++) {
DFTcore(edge, i, vertexStatusArr);
}
printf("\n");
}
void DFTcore(st_edge** edge, int i, int* vertexStatusArr) {
if (vertexStatusArr[i] == 1) {
return;
}
printf("%d ", i);
vertexStatusArr[i] = 1;
st_edge* p = *(edge + i);
while (p != NULL) {
DFTcore(edge, p->vertex, vertexStatusArr);
p = p->next;
}
}
邻接表:包含n个头结点和e个表结点,算法中对所有结点都要遍历一次,所以时间复杂度为O(n+e)
图的广度优先遍历
1、算法思想
广度优先遍历( Breadth_First_Search) ,又称为广度优先搜索,简称BFS。
它的思想是:
从图中某顶点v出发,在访问了v之后依次访问v的各个未曾访问过的邻接点,
然后分别从这些邻接点出发依次访问它们的邻接点,并使得“先被访问的顶点的邻接点先于后被访问的顶点的邻接点被访问,直至图中所有已被访问的顶点的邻接点都被访问到。
如果此时图中尚有顶点未被访问,则需要另选一个未曾被访问过的顶点作为新的起始点,重复上述过程,直至图中所有顶点都被访问到为止。
2、邻接矩阵构造图
#include <iostream>
#include <vector>
#include <queue>
using namespace std;
#define VERTEXNUM 5
void createGraph(vector<vector<int>>&edge, int start, int end);
void displayGraph(vector<vector<int>>&edge);
void DFS(vector<vector<int>>&edge, vector<int>& vertexStatusArr);
void DFScore(vector<vector<int>>&edge, int i, vector<int>& vertexStatusArr);
void BFS(vector<vector<int>>&edge, vector<int>& vertexStatusArr);
int main(void) {
//初始化邻接矩阵
vector<vector<int>>edge(VERTEXNUM, vector<int>(VERTEXNUM, 0));
//存放顶点的遍历状态,0:未遍历,1:已遍历
vector<int> vertexStatusArr(VERTEXNUM, 0);
cout << "after init: " << endl;
displayGraph(edge);
//创建图
createGraph(edge, 0, 3);
createGraph(edge, 0, 4);
createGraph(edge, 3, 1);
createGraph(edge, 3, 2);
createGraph(edge, 4, 1);
cout << "after create: " << endl;
displayGraph(edge);
//深度优先遍历
//DFS(edge, vertexStatusArr);
BFS(edge, vertexStatusArr);
return 0;
}
//创建图
void createGraph(vector<vector<int>>&edge, int start, int end) {
edge[start][end] = 1;
}
//打印存储的图
void displayGraph(vector<vector<int>>&edge) {
int i, j;
for (i = 0; i<VERTEXNUM; i++) {
for (j = 0; j<VERTEXNUM; j++) {
//printf("%d ", edge[i][j]);
cout << edge[i][j] << " ";
}
cout << endl;
}
}
//BFS
void BFS(vector<vector<int>>&edge ,vector<int>& vertexStatusArr) {
queue<int>q;
q.push(0);
vertexStatusArr[0] = 1;
int idx = 0;
while (!q.empty())
{
idx = q.front();
q.pop();
cout << idx << " ";
for (int j = 0; j< VERTEXNUM; j++) {
if (edge[idx][j] == 1 && vertexStatusArr[j] == 0)
{
q.push(j);
vertexStatusArr[j] = 1;
}
}
}
cout << endl;
}