python 拓扑排序 dfs bfs_拓扑排序的DFS和BFS

博主以前有一个疑问,DFS和BFS各自的适用范围是?我想你今天看了这篇文章之后会有一个判断!

BFS

数据结构与算法分析:c语言描述(p217)

已经存在一个Indgree入度数组(indgree[v]={(u,v)的数目})

以及一个邻接矩阵,求一个拓扑排序

提示:图中出现环就会拓扑失败

代码风格被我改为了C++

void TopSort(vector> G){

//图中所有的点都要被遍历到,每次取出一个点,共执行NumVertex次

for(int counter=0;counter

int v=findVertexIndgreeZero(G);//寻找入度为0的点

if(!v){

cout<

return;

}

TopNum[v]=counter;//第counter+1个被遍历到的

for(int i;i

if(G[v][i])

indgree[i]--;

}

}

}

用一句话来概括这个算法就是依次寻找出入度为0的点,然后将其所通的所有点入度都减1。循环直至结束或者报错(有环)。

上面这个算法存在优化的余地,findVertexIndgreeZero()的复杂度为O(n),执行n次为O(N2)次,用一个队列会大大缩减复杂度

void TopSort(vector> G){

int counter=0;

queue q;

for(int i=0;i

if(indgree[i]==0);

q.push(i);

}

while(!q.empty()){

int u=q.top();q.pop();

TopNum[u]=counter++;

for(int i=0;i

if(G[u][i]){

if(--indgree[i]==0)

q.push(i);

}

}

}

if(counter!=G.size())

cout<

}

这个结果很有趣,我们可以不严谨地总结一下“拓扑排序就是在找入度0点+更新入度”。

题外话

另外TopNum[i]保存了遍历的顺序。那么能不能TopNum[counter]=i,这样呢。。也可以。因为i和counter肯定是一一映射的关系。如果学习过数据库,那么你就可以说:谁来做主键都可以。

DFS

刘汝佳 算法竞赛入门经典第二版

P167

假设有n个变量,m个二元组(u,v),分别表示u< v。那么寻找一个不等式,包含所有的变量。类似于a< b,b< c ,则输出a< b< c;

我们可以把二元组小于关系看作边关系。这一转换其实很自然。

然后,寻找一个不等式,其实就是在寻找一个拓扑顺序。那么,这个问题其实就是一个拓扑排序,完全可以用BFS完成

但是还有另外一种比较有趣的解法,就是使用dfs。

我们首先定义一个函数

bool dfs(int u);//u代表当前点,返回点u之后是否存在一个拓扑路线

有了这个定义就不难继续做下去了,我们再想到:当前点u若是想能够返回true,那么它所能到达(u->v)的所有点也应该都能。

那么,失败的具体条件是什么?就是成环!

只要之后遍历到的点和之前的点u有关系(v->u),那么就说明成环!返回false。

那么,代码应该是:

int vector> G

int c[maxn];

int TopNum[maxn];

int t;

bool dfs(int u){

c[u]=-1;

for(int i=0;i

if(G[u][i]){

if(c[i]==-1){//大水冲了龙王庙,这个i点在之前已经被遍历到了,成环!

return false;

}

if(!c[i]&&!dfs(i)) return false;

}

//经过了检验

c[u]=1;

TopNum[--t]=u;

return true;

}

bool topsort(){

int t=n;

memset(c,0.sizeof(c));

for(int i=0;i

if(!c[u])

if(!dfs(u))

return false;

return true;

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值