深度优先搜索+拓扑排序

本文介绍了如何使用深度优先搜索实现拓扑排序。通过输入图G的邻接矩阵,利用DFS的完成时间进行排序,得到拓扑排序的逆序结果。

深度优先搜索可以实现拓扑排序

//深度优先搜索的完成时间进行排序就是拓扑排序的逆序。

输入图G

G的邻接矩阵存储data.txt

6
0 1 0 1 0 0
0 0 1 0 0 0
0 0 0 1 0 0
0 1 0 0 0 0
0 0 1 0 0 1
0 0 0 0 0 0

DFS程序

/*
 * @file								DFS.cpp
 * @brief								implementing DFS page117
 * @author/Univ.						taoxiaoxiao/XMU
 * @date								10-1-2014
*/

#include <iostream>
#include <fstream>
using namespace std;

#define NIL -1
#define WHITE 0
#define GRAY 1
#define BLACK 2
#define INF 0x3f3f3f3f
#define MAXN 101

int graph[MAXN][MAXN]; 
int dist[MAXN], f[MAXN];
int color[MAXN], pre[MAXN];
int N, time;

void DFSVisit(int u)
{
	color[u] = GRAY;
	time=time+1;
	dist[u] = time;
	for (int i = 0; i < N; ++i)
	{
		if (graph[u][i] != 0 && color[i] == WHITE)
		{
			pre[i] = u;
			DFSVisit(i);
		}
	}
	color[u] = BLACK;
	time ++;
	f[u] = time;
}

void DFS()
{
	int i;

	for (i = 0; i < N; ++i)
	{
		color[i] = WHITE;
		pre[i] = NIL;
	}
	time = 0;
	for (i = 0; i < N; ++i)
	{
		if (color[i] == WHITE)
			DFSVisit(i);
	}
}

int main()
{
	int i, j;
	ifstream infile("data.txt");
	if (infile.is_open())
		cout << "open file successful." << endl;
	else
	{
		cout << "open file error" << endl;
		return 0;
	}
	while (!infile.eof())
	{
		infile >> N;
		for (i = 0; i < N; ++i)
		{
			for (j = 0; j < N; ++j)
				infile >> graph[i][j];
		}
		DFS();
		for (i = 0; i < N; ++i)			//顶点访问结束时间
			cout << f[i] << " ";
		cout << endl;
	}

	return 0;
}
顶点完成时间排序的一个拓扑排序

/*
* @file								DFS.cpp
* @brief							implementing DFS+拓扑排序
* @author/Univ.						taoxiaoxiao/XMU
* @date								10-1-2014
*/

#include <iostream>
#include <fstream>
using namespace std;

#define NIL -1
#define WHITE 0
#define GRAY 1
#define BLACK 2
#define INF 0x3f3f3f3f
#define MAXN 101

int graph[MAXN][MAXN];
int dist[MAXN], f[MAXN];
int color[MAXN], pre[MAXN];
int N, time;

struct str_node
{
	int id;
	int time;
} node[10];

int cmp(const void *x, const void *y)
{
	return (*(str_node*)x).time >  (*(str_node*)y).time ? -1 : 1;
}

void DFSVisit(int u)
{
	color[u] = GRAY;
	time = time + 1;
	dist[u] = time;
	for (int i = 0; i < N; ++i)
	{
		if (graph[u][i] != 0 && color[i] == WHITE)
		{
			pre[i] = u;
			DFSVisit(i);
		}
	}
	color[u] = BLACK;
	time++;
	f[u] = time;
}

void DFS()
{
	int i;

	for (i = 0; i < N; ++i)
	{
		color[i] = WHITE;
		pre[i] = NIL;
	}
	time = 0;
	for (i = 0; i < N; ++i)
	{
		if (color[i] == WHITE)
			DFSVisit(i);
	}
}

int main()
{
	int i, j;
	ifstream infile("data.txt");
	if (infile.is_open())
		cout << "open file successful." << endl;
	else
	{
		cout << "open file error" << endl;
		return 0;
	}
	while (!infile.eof())
	{
		infile >> N;
		for (i = 0; i < N; ++i)
		{
			for (j = 0; j < N; ++j)
				infile >> graph[i][j];
		}
		DFS();
		for (i = 0; i < N; ++i)
		{
			node[i].id = i;
			node[i].time = f[i];
		}
		qsort(node, N, sizeof(node[0]), cmp);
		
		for (i = 0; i < N; ++i)
		{
			cout << node[i].id << " ";
		}
		cout << endl;
	}

	return 0;
}
输出一个拓扑排序
4 5 0 1 2 3

### 使用DFS实现拓扑排序 #### 方法概述 深度优先搜索DFS)可以用来检测有向图中的环并生成节点的一个线性序列,这个过程称为拓扑排序。当执行DFS时,每当完成对某个顶点v及其所有可到达的其他顶点的访问之后,就将该顶点加入到最终顺序列表之前的位置上。 对于每一个未被标记为已处理过的结点u调用一次递归函数dfs(u),如果在探索过程中遇到了已经存在于当前路径上的另一个结点,则说明存在回路;反之则不存在回路,并且可以通过记录每次退出子树的时间戳来构建逆序的结果集——即先退栈的是最后进入结果数组的元素[^1]。 #### 实现代码示例 下面是一个Python版本的具体实现: ```python from collections import defaultdict, deque def topological_sort_dfs(graph): visited = set() # 记录访问状态 result = [] # 存储排序后的节点 def dfs(node): if node not in visited: visited.add(node) for neighbor in graph[node]: dfs(neighbor) result.appendleft(node) # 将节点添加至队列头部 for vertex in list(graph): # 对每个可能孤立的连通分量都做一遍深搜 dfs(vertex) return list(result) if __name__ == "__main__": g = defaultdict(list) edges = [ ('A', 'C'), ('B', 'C'), ('B', 'D'), ('C', 'E'), ('D', 'F'), ('E', None), ('F', None) ] for src, dest in edges[:-2]: # 构建邻接表形式表示的图结构 g[src].append(dest) print(topological_sort_dfs(g)) # 输出拓扑排序结果 ['B', 'D', 'A', 'C', 'E'] ``` 此程序定义了一个`topological_sort_dfs()` 函数接收一个字典类型的参数graph作为输入,它代表了一张由边组成的无权有向图的数据结构。通过迭代遍历所有的顶点来进行完整的DFS操作直到获得整个图的拓扑排序结果[^3]。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值