图的搜索算法的目的是发现从源结点s能够到达的每个顶点和相应的距离。
广度优先搜索:所有结点一开始涂上白色,第一次遇到一个结点就称该结点被发现,颜色变为黑或者灰。黑色代表所有与该结点邻接的结点都已经被发现,灰色代表的是已知和未知两个集合的边界。白->灰:结点刚被搜索到,灰->黑:结点的所有邻接结点都被搜索完。在扫描已发现结点u的邻接链表时,每当发现一个白色结点v,就将该结点v和边(u,v)同时加入广度优先树,称该结点u是结点v的前驱结点或父节点。
代码解释:
u.c表示结点u的颜色,u.father代表结点u的前驱结点,u.d代表从源结点s到目标结点u之间的距离,用一个先进先出队列Q来管理灰色结点集。
广度优先搜索的数据结构定义如下:
enum color
{
white,
gray,
black
};
struct QueueRecord
{
int capacity;
int front;
int rear;
int size;
int *array;
};
typedef struct QueueRecord *queue;
queue makeEmpty(queue q,int capac);
int succ(int value, queue q);
int isFull(queue q);
void enqueue(int x, queue q);
int dequeue(queue q);
typedef struct node* vNode;
typedef struct hNode* lNode;
typedef struct graph* graphs;
struct node
{
int vertex;
vNode next;
};
struct hNode
{
int hVertex;
color c;
int d;
int father;
int f;
vNode head;
};
struct graph
{
lNode adj;
int n;
int e;
};
void createGraph(graphs g);
void bfs(graphs g, int i);
void print(graphs g, int s, int v);
具体实现如下:
queue makeEmpty(queue q, int capac)
{
q->size = 0;
q->front = 1;
q->rear = 0;
q->capacity = capac;
q->array = (int *)malloc(sizeof(int)*q->capacity);
return q;
}
int succ(int value, queue q)
{
if (++value == q->capacity)
value = 0;
return value;
}
int isFull(queue q)
{
if (q->size == q->capacity)
return 1;
else
return 0;
}
void enqueue(int x, queue q)
{
if (isFull(q))
cout << "Queue is full!" << endl;
else
{
q->size++;
q->rear = succ(q->rear, q);
q->array[q->rear] = x;
}
}
int dequeue(queue q)
{
if (q->size == 0)
{
cout << "Queue is empty!" << endl;
return NULL;
}
else
{
q->size--;
int a = q->array[q->front];
q->front = succ(q->front, q);
return a;
}
}
void createGraph(graphs g)
{
int i, j, k;
vNode v;
cout << "Please enter the verteces of a edge:" << endl;
for (k = 0; k < g->e; k++)
{
cin >> i >> j;
v = (struct node *)malloc(sizeof(struct node));
v->vertex = j;
v->next = g->adj[i].head->next;
g->adj[i].head->next = v;
}
}
void bfs(graphs g, int s)
{
int m, n,r;
for (m = 0; m < g->n;m++)
{
if (m == s)
{
g->adj[s].c = gray;
g->adj[s].d = 0;
g->adj[s].father = INT_MIN;
}
else
{
g->adj[m].c = white;
g->adj[m].d = INT_MAX;
g->adj[m].father = INT_MIN;
}
}
queue q = (struct QueueRecord *)malloc(sizeof(struct QueueRecord));
makeEmpty(q,g->n);
enqueue(s, q);
while (q->size!=0)
{
n = dequeue(q);
vNode res = g->adj[n].head->next;
for (; res != NULL; res = res->next)
{
r = res->vertex;
if (g->adj[r].c == white)
{
g->adj[r].c = gray;
g->adj[r].d = g->adj[n].d + 1;
g->adj[r].father = n;
enqueue(r, q);
}
}
g->adj[n].c = black;
}
}
void print(graphs g, int s, int v)
{
if (v == s)
cout << s << " ";
else if (g->adj[v].father ==INT_MIN)
cout << "No path from " << s << " to " << v;
else
{
print(g, s, g->adj[v].father);
cout << "->" << v;
}
}
深度优先搜索:输入为图,输出为一个深度优先森林(广度优先搜索输出的为一棵广度优先树)。此时结点白->灰:结点被发现,灰->黑:结点的所有未被发现的邻接结点都被深度优先搜索完成。
数据结构定义如下:
<pre name="code" class="cpp">enum color
{
white,
gray,
black
};
struct QueueRecord
{
int capacity;
int front;
int rear;
int size;
int *array;
};
typedef struct QueueRecord *queue;
queue makeEmpty(queue q,int capac);
int succ(int value, queue q);
int isFull(queue q);
void enqueue(int x, queue q);
int dequeue(queue q);
typedef struct node* vNode;
typedef struct hNode* lNode;
typedef struct graph* graphs;
struct node
{
int vertex;
vNode next;
};
struct hNode
{
int hVertex;
color c;
int d;
int father;
int f;
vNode head;
};
struct graph
{
lNode adj;
int n;
int e;
};
void dfs(graphs g);
void dfsVisit(graphs g, int u);
具体实现如下:
<pre name="code" class="cpp">void dfs(graphs g)
{
int i, j;
for (i = 0; i < g->n; i++)
{
g->adj[i].c = white;
g->adj[i].father = INT_MIN;
}
time = 0;
for (i = 0; i < g->n; i++)
{
if (g->adj[i].c == white)
dfsVisit(g, i);
}
}
void dfsVisit(graphs g, int u)
{
int i;
time = time + 1;
g->adj[u].d = time;
g->adj[u].c = gray;
vNode res = g->adj[u].head->next;
for (; res != NULL; res = res->next)
{
i = res->vertex;
if (g->adj[i].c == white)
{
g->adj[i].father = u;
dfsVisit(g, i);
}
}
g->adj[u].c = black;
time = time + 1;
g->adj[u].f = time;
}