图的遍历是指从图中的任一顶点出发,对图中的所有顶点访问一次且访问一次。图的搜索分为深度优先搜索和广度优先搜索。
1.图的深度优先搜索算法如下:
(1)从图中选取一顶点v,标记顶点v并访问该顶点。
(2)选取顶点v的一个邻结顶点w进行访问,从w开始深度优先搜索。
(3)若从w出发能够访问所有的顶点,则返回到顶点v.
(4)若仍有邻结于v且没有被访问的的顶点,则从该顶点出发搜索其它的路径。否则由顶点v出发的一次搜索过程结束。
从图的深度优先搜索算法中,可以看出图的深度优先搜索是一个递归的过程,简而言之,就是从图的一个顶点出发向下搜索,直到搜索的顶点没有邻结顶点时,然后返回上一层,判断一下有没有顶点没被访问,如果有,就沿之这个顶点向下搜索。否则的话,再返回上一层重复上述的过程。直到所有的顶点都被搜索完为止。所以图的深度优先搜索算法可以用递归来实现。
2.图的广度优先搜索算法如下:
访问某个顶点v,接着依次访问它们的邻结顶点w1,w2,....,再访问w1,w2,....的没被访问的邻结顶点。直到所有的顶点都被访问完为止。
图的广度优先搜索算法可用队列来实现,首先让访问顶点v,再让顶点v的所有邻结结点入队列,依次访问它们。然后再让这些邻结结点出队列,访问这些邻结结点的邻结结点。直到队列为空,那么所有结点都被访问了。
3.图的深度优先搜索与广度优先搜索的JAVA实现
package Graph;
/**
*
* 建立无向图 用一个数组来存储图节点
*
* @author Administrator
*
*/
public class graph {
int max;// 图中最大节点数
int n = 0;// 图中当前节点数
VexNode[] adjlist;
boolean visit[];/* 记录节点有没有被访问过 */
/**
* 利用邻结矩阵生成邻结表
*
* @param vex
* 顶点数组
* @param arc
* 边的一维排列
* @param n
* 顶点个数
*/
public graph(int vex[], int arc[][], int n) {
this.n = max = n;
visit = new boolean[n];
adjlist = new VexNode[n];
for (int k = 0; k < n; k++) {
adjlist[k] = new VexNode();
adjlist[k].Vexdata = vex[k];
}
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
if (arc[i][j] == 1) {
ArcNode p = new ArcNode();
p.next = adjlist[vex[i]].firstarc;
adjlist[vex[i]].firstarc = p;
p.Arcdata = vex[j];
}
}
}
}
public graph(int num) {
max = num;
adjlist = new VexNode[num];
visit = new boolean[num];
}
/**
* 建立图节点
*/
public void createNode(int data) {
if (n < max) {
VexNode v = new VexNode();
v.Vexdata = data;
adjlist[n] = v;
n++;
}
}
/**
* 建立有向图的边,建立一条从data1到data2的弧
*
* @param data1
* @param data2
*/
public void createDirectionArc(int data1, int data2) {
ArcNode p = new ArcNode();
p.next = adjlist[data1].firstarc;
adjlist[data1].firstarc = p;
p.Arcdata = data2;
adjlist[data2].indegree++;
}
/**
* 建立无向图中的边 即建立邻节表
*/
public void createArc(int data1, int data2) {
ArcNode p1;
ArcNode p2;
p1 = new ArcNode();
p2 = new ArcNode();
p1.next = adjlist[data1].firstarc;
p2.next = adjlist[data2].firstarc;
adjlist[data1].firstarc = p1;
adjlist[data2].firstarc = p2;
p1.Arcdata = data2;
p2.Arcdata = data1;
}
/**
* 建立一个有向图逆邻结表
*
* @param data1
* @param data2
*/
public void createInverseArc(int data1, int data2) {
ArcNode p = new ArcNode();
p.next = adjlist[data2].firstarc;
adjlist[data2].firstarc = p;
p.Arcdata = data1;
}
/**
* 逆邻结表计算有向图中顶点的入度
*
* @param v0
*/
public void InVex(int v0) {
ArcNode p = adjlist[v0].firstarc;
int indegree = 0;
while (p != null) {
indegree++;
p = p.next;
}
System.out.println("顶点" + v0 + "的入度为:" + indegree);
}
/**
*
* 逆邻结表计算顶点的出度
*
* @param v0
*/
public void outVex(int v0) {
int m = 0;
for (int i = 0; i < n; i++) {
ArcNode p = adjlist[i].firstarc;
if (v0 != i) {
while (p != null) {
if (p.Arcdata == v0) {
m++;
break;
} else {
p = p.next;
}
}
}
}
System.out.println("节点" + v0 + "的出度为:" + m);
}
/**
*
* 邻结表计算有向图中顶点的入度
*
*/
public void IndVex(int v0) {
int m = 0;
for (int i = 0; i < n; i++) {
ArcNode p = adjlist[i].firstarc;
if (v0 != i) {
while (p != null) {
if (p.Arcdata == v0) {
m++;
break;
} else {
p = p.next;
}
}
}
}
System.out.println("节点" + v0 + "的入度为:" + m);
}
/**
* 邻结表计算顶点的出度
*
*/
public void odvex(int v0) {
ArcNode p = adjlist[v0].firstarc;
int m = 0;
while (p != null) {
m++;
p = p.next;
}
System.out.println("顶点" + v0 + "的出度为:" + m);
}
/**
*
* 无向图中求顶点的度
*/
public void degree(int v0) {
int m = 0;
ArcNode p = adjlist[v0].firstarc;
while (p != null)
{
m++;
p = p.next;
}
System.out.println("顶点" + v0 + "的度为:" + m);
}
/**
* 图的深度遍历 即从第一个节点出发,直接节点的next为空时,返回上一层进行遍历 因此它是一个递归算法 从v0出发开始遍历
*/
public void visitdepth(int v0) {
ArcNode v = adjlist[v0].firstarc;
System.out.print(adjlist[v0].Vexdata + " ");
visit[v0] = true;
while (v != null) {
if (!visit[v.Arcdata]) {
visitdepth(v.Arcdata);
}
v = v.next;
}
}
public void dfs(int v0) {
for (int i = 0; i < visit.length; i++)
visit[i] = false;
for (int j = 0; j < 4; j++)
if (!visit[j])
visitdepth(j);
}
/**
*
* 图的广度遍历,又称为层次遍历 把预先遍历的结点放入到队列中,然后出队节点进行遍历,直到队列为空
*
* @param v0
*/
public void bfs1(int v0) {
int[] queue = new int[max + 10];
ArcNode p;
int front = 1;
int rear = 1;
int v;
System.out.print(v0 + " ");
visit[v0] = true;
queue[rear] = v0;
rear = rear + 1;
while (front != rear) {
v = queue[front];
front = front + 1;
p = adjlist[v].firstarc;
while (p != null) {
if (!visit[p.Arcdata]) {
System.out.print(p.Arcdata + " ");
queue[rear] = p.Arcdata;
visit[p.Arcdata] = true;
rear = rear + 1;
}
p = p.next;
}
}
}
public void bfs(int v0) {
for (int i = 0; i < visit.length; i++)
visit[i] = false;
for (int j = 0; j < max; j++)
if (!visit[j])
bfs1(j);
}
}
以上就是图的深度优先遍历与广度优先遍历的实现算法。深度优先搜索算法是用递归来实现的,广度优先搜索是用队列来实现的。
关于深度优先搜索与广度优先搜索的实例请参考http://sjjg.js.zwu.edu.cn/SFXX/tu/tu5.3.2.html。