深度搜索和广度搜索 - 图的遍历
来源:互联网 发布:路径优化tsp的发展 编辑:程序博客网 时间:2024/06/08 13:33
一. 图的连接表示
一种表示图的直接方法是使用二维数组,也称为邻接矩阵。通过邻接矩阵表示顶点 i 和 j 之间是否存在一条边(检查邻接矩阵中行 i 和 j 处是否为非零值)。定义数组visited[N] 标记节点是否被访问过。
以下程序:如果在图中顶点 i 和顶点 j 或者顶点 j 和顶点 i 之间存在一条边,就把关联矩阵 G->edges[i][j] 和 G->edges[j][i] 设置为 1 ;如果不存在这样的边,则设置为 0 。
创建图的程序如下:
typedef struct Graph{ int edges[MAX][MAX]; //连接矩阵 int e; //边数 int n; //顶点数}Graph;void CreatGraph(Graph* G){ for(int i = 0; i < G->n; i++) { for(int j = 0; j < G->n; j++) { G->edges[i][j] = 0; //初始化连接矩阵 } visited[i] = 0; //初始化访问标记 } //输入相连的顶点 for(int k = 0; k < G->e; k++) { int s, t, v; v = 1;//权重,非0即连接 printf("Please enter two connected vertices\n"); scanf("%d%d", &s, &t); G->edges[s][t] = v; }}
二. 图的遍历
1. 深度优先搜索算法(Depth-First-Search)
沿着树的深度遍历树的节点,尽可能深的搜索树的分支。当节点v的所有边都己被探寻过,搜索将回溯到发现节点v的那条边的起始节点。这一过程一直进行到已发现从源节点可达的所有节点为止。如果还存在未被发现的节点,则选择其中一个作为源节点并重复以上过程,整个进程反复进行直到所有节点都被访问为止。属于盲目搜索。
如上图所示的无向图,从0 节点开始遍历的顺序:0 -> 1 -> 3 -> 5 -> 4 -> 2
DFS的实现方式一般有两种:递归实现和非递归实现:
递归实现
实现程序简单,比较常用
void DFS(Graph* G, int i){ printf("Visiting %d\n", i); visited[i] = 1; for(int j = 0; j < G->n; j++) { if(G->edges[i][j] != 0 && visited[j] == 0) DFS(G, j); }}
非递归实现:
使用栈压入每一个没有被访问过的节点,由于栈的后进先出的原理,我们总是以最后访问的那一节点(栈顶节点)为起始节点,访问下一个未被访问过的节点,当当前栈顶节点没有后续连接节点要访问时,从栈中弹出。
例如上图从节点 0 开始访问的过程为:
访问 0,压入 0 ,访问 1 压入 1,访问 3 压入 3,访问 5 压入 5, 弹出 5(无与 5 相连且未访问的节点),弹出 3 ,访问 4 (此时栈顶为 1),压入 4,弹出 4,访问 2,弹出 2,弹出 0, 栈空。
遍历的顺序:0 -> 1 -> 3 -> 5 -> 4 -> 2
void DFS1(Graph* G, int i){ printf("Visiting %d\n", i); visited[i] = 1; Stack s = NULL; s = StackInit(s); StackPush(s, i); while (!StackIsEmpty(s)) { i = StackTop(s); int j; for (j = 0; j < G->n; j++) { if (G->edges[i][j] != 0 && visited[j] == 0) { printf("Visiting %d\n", j); visited[j] = 1; StackPush(s, j); break; } } if (j == G->n) //已无与i相连且未访问的节点 { StackPop(s); } }}
2. 广度优先搜索算法(Breadth-First-Search)
又译作宽度优先搜索,或横向优先搜索,简称BFS,是一种图形搜索算法。简单的说,BFS是从根节点开始,沿着树的宽度遍历树的节点。如果所有节点均被访问,则算法中止。
使用FIFO队列压入每一个没有被访问过的节点, 由于队列的先进先出的原理,我们总是以最开始访问的那一节点(队列顶节点)为起始节点,访问所有与之相连且未被访问过的节点,当当前队列顶节点没有后续连接节点要访问时,从队列中弹出。
访问顺序为:0 -> 1 -> 2 -> 3 -> 4 -> 5
遍历过程为: 访问 0 ,压入 0, (队列顶一直为 0 )<访问 1 压入 1,访问 2 压入 2 >,弹出 0 ,(队列顶一直为 1 )<访问 3 压入 3,访问 4 压入 4>,弹出 1,(队顶为2),弹出 2,(队顶为3)访问 5 ,弹出 3,(队顶为4)弹出 4,访问压入5,弹出 5.
void BFS(Graph *G, int i){ printf("Visiting %d\n", i); visited[i] = 1; Queue q = NULL; q = (Queue)malloc(sizeof(q)); QueueInit(q); //上一句分配内存后,应该初始化后才能正常使用 QueuePut(q, i); while(!QueueIsEmpty(q)) { i = QueueGet(q); for(int j = 0; j < G->n; j++) { if(G->edges[i][j] != 0 && visited[j] == 0) { printf("Visiting %d\n", j); visited[j] = 1; QueuePut(q, j); } } }}
三.测试主程序
#include<stdio.h>#include "stack.h"#include "queue.h"#define MAX 100typedef struct Graph Graph;int visited[MAX];struct Graph{ int edges[MAX][MAX]; //连接矩阵 int e; //边数 int n; //顶点数};//将visited[]全部设为0void visitedInit(Graph* G, int visited[]){ for (int i = 0; i < G->n; i++) { visited[i] = 0; }}//创建图(矩阵连接)void CreatGraph(Graph* G){ for(int i = 0; i < G->n; i++) { for(int j = 0; j < G->n; j++) { G->edges[i][j] = 0; //初始化连接矩阵 } visited[i] = 0; //初始化访问标记 } //输入相连的顶点 for(int k = 0; k < G->e; k++) { int s, t, v; v = 1;//权重,非0即连接 printf("Please enter the two connected vertices\n"); scanf("%d%d", &s, &t); G->edges[s][t] = v; }}//递归深度优先搜索void DFS(Graph* G, int i){ printf("Visiting %d\n", i); visited[i] = 1; for(int j = 0; j < G->n; j++) { if(G->edges[i][j] != 0 && visited[j] == 0) DFS(G, j); }}//非递归深度优先搜索,栈void DFS1(Graph* G, int i){ printf("Visiting %d\n", i); visited[i] = 1; Stack s = NULL; s = StackInit(s); StackPush(s, i); while (!StackIsEmpty(s)) { i = StackTop(s); int j; for (j = 0; j < G->n; j++) { if (G->edges[i][j] != 0 && visited[j] == 0) { printf("Visiting %d\n", j); visited[j] = 1; StackPush(s, j); break; } } if (j == G->n) { StackPop(s); } }}//广度优先搜索void BFS(Graph *G, int i){ printf("Visiting %d\n", i); visited[i] = 1; Queue q = NULL; q = (Queue)malloc(sizeof(q)); QueueInit(q); //上一句分配内存后,应该初始化后才能正常使用 QueuePut(q, i); while(!QueueIsEmpty(q)) { i = QueueGet(q); for(int j = 0; j < G->n; j++) { if(G->edges[i][j] != 0 && visited[j] == 0) { printf("Visiting %d\n", j); visited[j] = 1; QueuePut(q, j); } } }}int main(){ int n, e; Graph* G = (Graph*)malloc(sizeof(*G)); printf("Please enter the number of vertices and edges\n"); scanf("%d %d", &n, &e); //输入图的顶点数和边数 G->n = n; G->e = e; CreatGraph(G); printf("\nDepth-First-Search-1:\n"); DFS(G, 0); visitedInit(G, visited); //将visited[]全部设为0 printf("\nDepth-First-Search-2:\n"); DFS1(G, 0); visitedInit(G, visited); //将visited[]全部设为0 printf("\nBreadth-First-Search:\n"); BFS(G, 0); system("pause"); return 0;}
结果如下:
四. 源代码下载
http://pan.baidu.com/s/1DAD6u
- 深度搜索和广度搜索 - 图的遍历
- 图的深度搜索和广度搜索
- 图的深度搜索和广度搜索
- 数据结构--图--图的数组存储表示,深度优先搜索遍历和广度优先搜索遍历
- 图的遍历 深度优先搜索 广度优先搜索
- 图的遍历之广度优先搜索和深度优先搜索
- 图的遍历之 深度优先搜索和广度优先搜索
- 图的遍历之 深度优先搜索和广度优先搜索
- 图的遍历之 深度优先搜索和广度优先搜索
- 图的遍历之 深度优先搜索和广度优先搜索
- 图的遍历之广度优先搜索和深度优先搜索
- 图的遍历之 深度优先搜索和广度优先搜索
- 图的遍历之 深度优先搜索和广度优先搜索
- 图的遍历之深度优先搜索和广度优先搜索
- 图的遍历之 深度优先搜索和广度优先搜索
- dom结点的深度优先遍历和广度优先搜索
- 无向图的深度搜索和广度搜索
- 无向图的深度搜索和广度搜索
- 传输层TCP协议——TCP连接的建立和终止
- Maven 构建 Struts2 实现 基本 CURD Controller层代码
- javascript基础之CSS基础
- SQL 表格连接的用法
- 如何实现Android中悬浮窗口
- 深度搜索和广度搜索 - 图的遍历
- javascript基础之html基础
- 控件容器如何点击后改变背景颜色(如LinearLayout...)
- 记录下关于读取文件的东西
- git笔记--(3) --分支管理
- javascript基础一
- JAVA Synchronize问题
- Linux Note
- OC-static和extern、递归、对象与函数参数的内存分配