算法导论-图的搜索算法之深度优先搜索和广度优先搜索

图的搜索算法的目的是发现从源结点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;
}

点赞