算法-无向图(深度优先搜索和广度优先搜索)
图中最常用到的两种搜索深度优先搜索和广度优先搜索,深度优先搜索是一种在开发爬虫早期使用较多的方法它的目的是要达到被搜索结构的叶结点(即那些不包含任何超链接的Html文件) ,广度搜索属于一种盲目搜寻法,目的是系统地展开并检查图中的所有节点,以找寻结果。换句话说,它并不考虑结果的可能位置,彻底地搜索整张图,直到找到结果为止。
深度优先搜索
图中我们经常会遇到一个问题就是图的连通性,比如说从一个顶点到另外一个顶点,判断顶点和其他顶点之间的连通性,以下图为例:
搜索API定义:
@interface DepthFirstSearch : NSObject
//记录顶点是否被标记
@property (strong,nonatomic) NSMutableArray *marked;@property (assign,nonatomic) NSInteger count;
//找到与七点vertex所有连通的节点
-(instancetype)initWithGraphAndVertex:(Graph *)graph vertex:(NSInteger)vertex;-(void)depthSearch:(Graph *)graph vertex:(NSInteger)vertex;//节点是否被标记
-(Boolean)isMarked:(NSInteger)vertex;@end
实现:
@implementation DepthFirstSearch#pragma mark getter and setter
-(NSMutableArray *)marked{if (!_marked) {_marked=[[NSMutableArray alloc]initWithCapacity:1];}return _marked;
}-(instancetype)initWithGraphAndVertex:(Graph *)graph vertex:(NSInteger)vertex{self=[super init];if (self) {for (NSInteger i=0; i<graph.vertexs;i++) {[self.marked addObject:[NSNull null]];}[self depthSearch:graph vertex:vertex];}return self;
}
//http://www.cnblogs.com/xiaofeixiang/
-(void)depthSearch:(Graph *)graph vertex:(NSInteger)vertex{self.marked[vertex]=[NSNumber numberWithBool:true];self.count++;for (NSInteger i=0; i<[graph.adjDataSource[vertex] count]; i++) {NSInteger temp=[[graph.adjDataSource[vertex] objectAtIndex:i] integerValue];if (![self isMarked:temp]) {[self depthSearch:graph vertex:temp];}}
}-(Boolean)isMarked:(NSInteger)vertex{return self.marked[vertex]==[NSNull null]?false:[self.marked[vertex] boolValue];
}@end
代码测试:
Graph *graph=[[Graph alloc]initWithVertex:6];[graph addEdges:0 endVertex:5];[graph addEdges:2 endVertex:4];[graph addEdges:2 endVertex:3];[graph addEdges:1 endVertex:2];[graph addEdges:0 endVertex:1];[graph addEdges:3 endVertex:4];[graph addEdges:5 endVertex:3];[graph addEdges:0 endVertex:2];DepthFirstSearch *search=[[DepthFirstSearch alloc]initWithGraphAndVertex:graph vertex:0];for (NSInteger i=0; i<graph.vertexs; i++) {NSLog(@"节点%ld--值为:%@",i,search.marked[i]);}NSLog(@"技术交流群:%@",@"228407086");NSLog(@"原文地址:http://www.cnblogs.com/xiaofeixiang");
测试效果:
1表示连通,节点0和其他节点直接都可以直接连通,我们通过递归的方式成功的判断亮点之间的连通性,顶点直接的连通性是通过边链接的,深度搜索将在此方法上改动然后给出单点之间的路径,注意是路径不是最短路径,我们会发现代码变动很小。
//深度优先
@interface DepthFirstPath : NSObject//记录顶点是否被标记
@property (strong,nonatomic) NSMutableArray *marked;
//起点
@property (assign,nonatomic) NSInteger beginVertex;
//从起点到一个顶点的已知路径上的最后一个顶点
@property (strong,nonatomic) NSMutableArray *edgeTo;@property (assign,nonatomic) NSInteger count;
//找到与七点vertex所有连通的节点
-(instancetype)initWithGraphAndVertex:(Graph *)graph vertex:(NSInteger)vertex;-(void)depthSearch:(Graph *)graph vertex:(NSInteger)vertex;-(NSMutableArray *)pathTo:(NSInteger)vertex;//节点是否被标记
-(Boolean)hasPathTo:(NSInteger)vertex;@end
实现代码:
@implementation DepthFirstPath#pragma mark getter and setter
-(NSMutableArray *)marked{if (!_marked) {_marked=[[NSMutableArray alloc]initWithCapacity:1];}return _marked;
}-(NSMutableArray *)edgeTo{if (!_edgeTo) {_edgeTo=[[NSMutableArray alloc]initWithCapacity:1];}return _edgeTo;
}-(instancetype)initWithGraphAndVertex:(Graph *)graph vertex:(NSInteger)vertex{self=[super init];if (self) {for (NSInteger i=0; i<graph.vertexs;i++) {[self.marked addObject:[NSNull null]];[self.edgeTo addObject:[NSNull null]];}self.beginVertex=vertex;[self depthSearch:graph vertex:vertex];}return self;
}
//http://www.cnblogs.com/xiaofeixiang
-(void)depthSearch:(Graph *)graph vertex:(NSInteger)vertex{self.marked[vertex]=[NSNumber numberWithBool:true];self.count++;for (NSInteger i=0; i<[graph.adjDataSource[vertex] count]; i++) {NSInteger temp=[[graph.adjDataSource[vertex] objectAtIndex:i] integerValue];if (![self hasPathTo:temp]) {self.edgeTo[temp]=[NSNumber numberWithInteger:vertex];[self depthSearch:graph vertex:temp];}}
}-(Boolean)hasPathTo:(NSInteger)vertex{return self.marked[vertex]==[NSNull null]?false:[self.marked[vertex] boolValue];
}-(NSMutableArray *)pathTo:(NSInteger)vertex{if (![self hasPathTo:vertex]) {return NULL;}NSMutableArray *path=[[NSMutableArray alloc]initWithCapacity:1];for (NSInteger i=vertex; i!=self.beginVertex; i=[self.edgeTo[i] integerValue]) {[path insertObject:[NSNumber numberWithInteger:i] atIndex:0];}[path insertObject:[NSNumber numberWithInteger:self.beginVertex] atIndex:0];return path;
}@end
代码中我们多了一个edgeTo数组记录当前索引顶点的最后一个顶点,当edgeTo[1]=2表示顶点1和顶点2之间是直接相连,最后输出路径的时候利用栈的特性,先进后出,输出正确路径,测试代码如下:
NSInteger beginVertex=0;DepthFirstPath *path=[[DepthFirstPath alloc]initWithGraphAndVertex:graph vertex:beginVertex];for (NSInteger i=0; i<[path.edgeTo count]; i++) {NSLog(@"节点%ld--值为:%@",i,path.edgeTo[i]);}for (NSInteger i=0; i<graph.vertexs;i++) {NSMutableArray *data=[path pathTo:i];NSLog(@"%ld到%ld路径为:%@",beginVertex,i,[data componentsJoinedByString:@"--"]);}NSLog(@"技术交流群:%@",@"228407086");NSLog(@"原文地址:http://www.cnblogs.com/xiaofeixiang");
测试效果:
广度优先搜索
如果我们仔细观察会发现一个现象,图片中我们很明显看到顶点0可以直接到5,我们确发现广度搜索的路径给出的是0-2-3-5,如果想要获取最短路径,界限来一起看一下广度优先搜索,代码与上面的代码也是改动了一部分,比较好懂,代码如下:
@interface BreadthFirstPath : NSObject//记录顶点是否被标记
@property (strong,nonatomic) NSMutableArray *marked;
//起点
@property (assign,nonatomic) NSInteger beginVertex;
//从起点到一个顶点的已知路径上的最后一个顶点
@property (strong,nonatomic) NSMutableArray *edgeTo;//找到与七点vertex所有连通的节点
-(instancetype)initWithGraphAndVertex:(Graph *)graph vertex:(NSInteger)vertex;-(void)breadthSearch:(Graph *)graph vertex:(NSInteger)vertex;-(NSMutableArray *)pathTo:(NSInteger)vertex;//节点是否被标记
-(Boolean)hasPathTo:(NSInteger)vertex;@end
实现代码:
@implementation BreadthFirstPath#pragma mark getter and setter
-(NSMutableArray *)marked{if (!_marked) {_marked=[[NSMutableArray alloc]initWithCapacity:1];}return _marked;
}-(NSMutableArray *)edgeTo{if (!_edgeTo) {_edgeTo=[[NSMutableArray alloc]initWithCapacity:1];}return _edgeTo;
}-(instancetype)initWithGraphAndVertex:(Graph *)graph vertex:(NSInteger)vertex{self=[super init];if (self) {for (NSInteger i=0; i<graph.vertexs;i++) {[self.marked addObject:[NSNull null]];[self.edgeTo addObject:[NSNull null]];}self.beginVertex=vertex;[self breadthSearch:graph vertex:vertex];}return self;
}
//http://www.cnblogs.com/xiaofeixiang
-(void)breadthSearch:(Graph *)graph vertex:(NSInteger)vertex{NSMutableArray *queue=[[NSMutableArray alloc]initWithCapacity:1];self.marked[vertex]=[NSNumber numberWithBool:true];[queue addObject:[NSNumber numberWithInteger:vertex]];while ([queue count]>0) {NSInteger header=[[queue objectAtIndex:0] integerValue];[queue removeObjectAtIndex:0];for (NSInteger i=0; i<[graph.adjDataSource[header] count]; i++) {NSInteger temp=[[graph.adjDataSource[header] objectAtIndex:i] integerValue];if (![self isMarked:temp]) {self.marked[temp]=[NSNumber numberWithBool:true];self.edgeTo[temp]=[NSNumber numberWithInteger:header];[queue addObject:[NSNumber numberWithInteger:temp]];}}}}-(Boolean)isMarked:(NSInteger)vertex{return self.marked[vertex]==[NSNull null]?false:[self.marked[vertex] boolValue];
}-(Boolean)hasPathTo:(NSInteger)vertex{return self.marked[vertex]==[NSNull null]?false:[self.marked[vertex] boolValue];
}-(NSMutableArray *)pathTo:(NSInteger)vertex{if (![self hasPathTo:vertex]) {return NULL;}NSMutableArray *path=[[NSMutableArray alloc]initWithCapacity:1];for (NSInteger i=vertex; i!=self.beginVertex; i=[self.edgeTo[i] integerValue]) {[path insertObject:[NSNumber numberWithInteger:i] atIndex:0];}[path insertObject:[NSNumber numberWithInteger:self.beginVertex] atIndex:0];return path;
}
@end
测试代码:
NSInteger beginVertex=0;BreadthFirstPath *breadthPath=[[BreadthFirstPath alloc]initWithGraphAndVertex:graph vertex:beginVertex];for (NSInteger i=0; i<[breadthPath.edgeTo count]; i++) {NSLog(@"节点%ld--值为:%@",i,breadthPath.edgeTo[i]);}for (NSInteger i=0; i<graph.vertexs;i++) {NSMutableArray *data=[breadthPath pathTo:i];NSLog(@"%ld到%ld路径为:%@",beginVertex,i,[data componentsJoinedByString:@"--"]);}NSLog(@"技术交流群:%@",@"228407086");NSLog(@"原文地址:http://www.cnblogs.com/xiaofeixiang");
测试效果:
转载于:https://www.cnblogs.com/xiaofeixiang/p/4696971.html
算法-无向图(深度优先搜索和广度优先搜索)相关推荐
- Java实现算法导论中图的广度优先搜索(BFS)和深度优先搜索(DFS)
对算法导论中图的广度优先搜索(BFS)和深度优先搜索(DFS)用Java实现其中的伪代码算法,案例也采用算法导论中的图. import java.util.ArrayList; import java ...
- 算法十——深度优先搜索和广度优先搜索
文章出处:极客时间<数据结构和算法之美>-作者:王争.该系列文章是本人的学习笔记. 搜索算法 算法是作用于数据结构之上的.深度优先搜索.广度优先搜索是作用于图这种数据结构之上的.图上的搜索 ...
- 数据结构学习笔记——图的遍历算法(深度优先搜索和广度优先搜索)
目录 一.图的遍历概念 二.深度优先搜索(DFS) (一)DFS算法步骤 1.邻接表DFS算法步骤 2.邻接矩阵DFS算法步骤 (二)深度优先生成树.森林 (三)DFS的空间复杂度和时间复杂度 三.广 ...
- 八数码深度优先搜索_深度优先搜索和广度优先搜索
深度优先搜索和广度优先搜索 关于搜索&遍历 对于搜索来说,我们绝大多数情况下处理的都是叫 "所谓的暴力搜索" ,或者是说比较简单朴素的搜索,也就是说你在搜索的时候没有任何所 ...
- 深度优先遍历和广度优先遍历_图与深度优先搜索和广度优先搜索
什么是图? 图是一种复杂的非线性表结构.由若干给定的点一级任意两点间的连线所构成.图通常用来描述事物之间的特定关系, 代表的就是事物, 线就是事物之间所具有的关系.例如社交网络就是一种典型的图关系, ...
- 深度优先搜索和广度优先搜索
深度优先搜索和广度优先搜索 在人工智能的运筹学的领域中求解与图相关的应用中,这两个算法被证明是非常有用的,而且,如需高效地研究图的基本性质,例如图的连通性以及图是否存在环,这些算法也是必不可少的. ...
- 学会二叉树不知道干啥?二叉树的深度优先搜索和广度优先搜索,我要打十个乃至二十个(打开你的LeetCode撸起来)学练并举
目录 一. 图解二叉树的深度优先搜索 二. 二叉树的广度优先搜索 (层序遍历) 三. 打开LeetCode 撸起来 至此, 咱多少被刚刚的后序非递归搞得可能有点小晕晕的, 没事,层序简单呀.... ...
- 迷宫问题:深度优先搜索和广度优先搜索
迷宫问题:深度优先搜索和广度优先搜索 1.深度优先搜索可以使用栈实现,栈顶元素为当前节点 2.当前节点搜索下一节点,判断节点是否走得通,如果走得通任意方向走一步,走不通一直弹出栈内元素,直到走得通 3 ...
- 深度优先搜索与广度优先搜索区别和案例
今天周末,心血来潮打开LeetCode做一道题: https://leetcode-cn.com/problems/number-of-enclaves/ 看到题,我的第一想法是: 从边缘的陆地开始, ...
- 数据结构与算法(python):广度优先搜索(Breadth First Search,BFS)和深度优先算法(Depth First Search,DFS)
参考自 MOOC数据结构与算法Python版 目录 一.广度优先搜索 1.1 BFS算法过程 1.2 广度优先搜索算法分析 二.深度优先搜索 2.1 骑士周游 2.1.1 问题定义 2.1.2 构建骑 ...
最新文章
- Git 简介1-常用术语
- 数据治理在业务中台的实践
- 重磅!监管再升级!微信、淘宝、抖音或将纳入“超级平台”监管
- 公益性岗位计算机考试内容,公益性岗位公共基础知识:计算机概述-计算机硬件系统(1)...
- linux查看和关闭后台执行程序
- 前端学习(631):字符串类型
- STM32F7xx —— Timer
- 2019百度之星 	Polynomial
- linux进程线程协程的区别,进程和线程、协程的区别
- SVG实现loading
- DataSet和ListT 泛型之间互相转换 (转载, 作者写的很好)
- python获取动态更新的数据_python3+beautifulsoup动态数据获取想要的内容
- 微软集成开发者工具到 Visual Studio 中,Web 工具迎来“大换血”?
- Android ExpandableListView示例教程
- 【目标检测】目标检测中的多尺度检测(Multi-Scale),FPN,RPN
- perl软件使用报错总结
- 120个常用货源网站,赶紧收藏!
- PR短视频转场预设 60个摇晃抖动效果过渡合集
- php返回结果,后端继续执行
- linux 手机当显示器,[原创]平板/手机/笔记本作为显示器使用