图的遍历和回溯

递归,回溯, DFS的区别

	递归本身是一种思想。 在编写过程中主要遇到如下三种递归:
	1, 一种是斐波拉契这种,有着明确的递归表达式和递归边界
	2, 第二种则是像八皇后这种经典回溯问题。 采用回溯的方式枚举所有可能的
	解空间。本质上也是一种递归。这种问题还有如DFS遍历地图。
	3, 第三种就是递归和数据结构结合在一起。 如图的遍历, 树的遍历。

图的遍历(对每个顶点有且遍历一次)

void dfs(int u, int vex){
	visit[u]=true;
	for(int v=1;v<=vex;++v){
		if(visit[v]==false&&G[u][v]!=inf){
			dfs(v, vex);
		}
	}	
} 

求图中任意两点长度是L的所有路径


void dfs(int u, int des, int L, int height){
	if(L+1==height){
		if(u==des){
			path.push_back(u);
			result.push_back(path);
			path.pop_back();
		}
		return;
	}
	visit[u]=true;	// u加入path中
	path.push_back(u);
	for(int v=1;v<=vex;++v){
		if(G[u][v]!=inf&&visit[v]==false){
			dfs(v, des,L, height+1);
		}
	}
	visit[u]=false;
	path.pop_back();
}

知乎上的回溯模版

result = []
def backtrack(路径, 选择列表):
    if 满足结束条件:
        result.add(路径)
        returnfor 选择 in 选择列表:
        做选择
        backtrack(路径, 选择列表)
        撤销选择
	注:求图中任意两点所有路径本质上就是回溯,而非图的遍历。
	并且为了将起点囊括进去且访问u的代码不变。 所以和模版有些不一样。

DFS判环

bool dfs(int u){			 		
	visit[u]=0;
	path.push_back(u);
	bool flag=false; 
	for(int v=1;v<=vex;++v){
		if(G[u][v]!=inf){
			if(visit[v]==0){
				path.push_back(v);
				return true;
			}else{
				// 只有存在边并且没被访问的可以dfs 
				flag=dfs(v); 
				if(flag) break;		
				// 之前已经找到了环, 那么直接返回。 接下来不用在dfs			
			}
		}
	}
	visit[u]=1;
	return flag;
}
// visit[u]=-1, 表示尚未访问。 0表示在堆栈中。1表示在已经访问结束。

拓扑排序判环

int vex, edge;
int G[1010][1010];
int indegree[1010];
bool topSort(){
	// 为讨论方便假设顶点编号从1...vex
	queue<int> q;
	for(int i=1;i<=vex;++i){
		if(indegree[i]==0){
			q.push(i);
		}
	}
	int cnt=0;  // 记录出队列次数 
	while(!q.empty()){
		int u = q.front();
		q.pop();
		for(int v=1;v<=vex;++v){
			if(G[u][v]!=inf){
				--indegree[v];
				if(indegree[v]==0){
					q.push(v);
				}
			}
		}
		++cnt; 
	}
	if(cnt<vex) return true;
	return false;
}

小结

	目前遇到的算法题, 最怕的还是关键路径, AVL树, 堆,Floyd算法。
	其次在求两点任意路径时我们得出: 求图中任意两点所有路径用的是图的回溯
	。而且两点之间最优路径用的是迪杰特斯拉或者Floyd算法
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值