由于前面的时候就学过图了,但是现在大多都忘了,所以此篇主要于复习
一、图的储存方式
用二维数组存图(邻接矩阵)
其实用二维数组存图是一般常见的手法,但是其时间复杂度就很高,是 n^2,下面就是用二维数组实现的dijkstra算法,看图解
用邻接表存图
邻接表一般是用的链表,为什么要用链表,因为它的时间复杂度比二维数组存图用的太少了,在用二维数组时间超限的时候,就可以用邻接表,它的时间复杂度为n+e
代码实现
定义邻接矩阵
const int INF = 0x7fffffff; //最大值
const int MaxVnum = 100; //顶点最大个数
int visist[MaxVnum] = {0};
typedef char VexType;//顶点的数据类型
typedef int EdgeType;//顶点的边权;若不带权值则用0和1表示其连通性
typedef struct {
VexType Vex[MaxVnum];//顶点信息
EdgeType Edge[MaxVnum][MaxVnum];//邻接矩阵
int vexnum, edgenum; //顶点数和边数
} Gragh;
邻接矩阵的遍历
//深搜
void dfs(Gragh G, int v) { //假设已经创建了一个图的邻接矩阵G ,v是开始访问的顶点
int w;//w是邻接点
cout << G.Vex[v] << endl;
for (w = 0; w < G.vexnum; w++) { //遍历所有顶点
visist[v] = 1; //访问过了标记为真
if (G.Edge[v][w] && !visist[w]) dfs(G, w); //邻接且未被访问过,则递归访问其邻接点
}
}
//广搜
void bfs(Gragh G, int v) {
int u, w;
queue<int>Q;
visist[v] = 1;
cout << G.Vex[v] << endl;
Q.push(v);//顶点v入队
while (Q.empty() == 0) { //如果队列不空
u = Q.front(); //队列的头元素出列赋给u
Q.pop();//队列头元素出队
for (w = 0; w < G.vexnum; w++) {
if (G.Edge[u][w] && !visist[w]) { //u,w邻接且w未被访问过
cout << G.Vex[w] << endl;
visist[w] = 1;
Q.push(w);//领接点加入队列
}
}
}
}
测试
int main(){
Gragh g;
cout << "请输入此图的顶点数和边数" << endl;
cin >> g.vexnum >> g.edgenum;
getchar();
cout << "请输入此图的顶点" << endl;
for(int i = 0; i < g.vexnum; i++){
cin >> g.Vex[i];
}
cout << "请输入关于此图的边信息" << endl;
for(int i = 0; i < g.vexnum; i++){
for(int j = 0; j < g.vexnum; j++){
cin >> g.Edge[i][j];
}
}
// dfs(g,0);
// bfs(g,0);
return 0;
}
二、深度优先搜索
总结一句话,一条路走到底
代码模板
int check(所传参数)
{
if(....)return 1; //满足条件就返回1
else return 0;
}
void dfs(int step)
{
if(....) //终止条件
{
执行操作
}
遍历每一种情况
if(check(参数)) //满足条件
{
标记点位;
进行下一步搜索(如dfs(step+1))
回溯(有需要时进行回溯)
}
}
三、广度优先搜索
总结一句话,我把周围一层一层走完
代码模板
1 BFS算法:
2
3 通常用队列(先进先出,FIFO)实现
4
5 初始化队列Q;
6 Q = {起点s};
7 标记s为已访问;
8 while(Q非空)
9 {
10 取Q队首元素u;
11 u出队;
12 if(u==目标状态)
13 {
14 ……
15 }
16 else
17 {
18 所有与u相邻且未被访问的点进入队列;
19 标记u为已访问;
20 }
21 }