標籤:
圖是由頂點和邊串連而成,如果邊是沒有方向的是就是之前文章中說的無向圖,關於無向圖可以參考本人之前的文章,如果邊是有方向的,則稱之為有向圖。從頂點A→B,我們可以理解為A到B可達,有向圖和無向圖一樣通過鄰接表儲存每一條邊,由於邊是有方向的,因此在添加邊的過程中只需要添加一條邊即可。關於可達性一個節點數組的可達性,採用的方法是之前的深度優先搜尋一樣的代碼,通過遞迴將標記位Bool標記位判斷數組中每個頂點的可達性。為了測試,選擇下面一張有向圖:
有向圖基礎
通過圖片我們可以發現圖中有13個節點,22條邊,頂點0指出的節點有1,5,指入的節點有2,6,我們先實現所有頂點指出的節點,之後可以通過反轉判斷所有節點的指入節點:
@interface Digraph : NSObject//頂點的總數@property (assign,nonatomic) NSInteger vertexs;//邊的數總數@property (assign,nonatomic) NSInteger edges;//連接點的邊@property (strong,nonatomic) NSMutableArray *adjDataSource;-(instancetype)initWithVertex:(NSInteger)vertexs;//添加一條有向邊 startVertex→endVertex-(void)addEdges:(NSInteger)startVertex endVertex:(NSInteger)endVertex;-(Digraph *)reverse;//該圖的反向圖@end
實現代碼:
@implementation Digraph-(instancetype)initWithVertex:(NSInteger)vertexs{ self=[super init]; if (self) { self.vertexs=vertexs; for (NSInteger i=0; i<vertexs; i++) { NSMutableArray *neighbourVertex=[[NSMutableArray alloc]initWithCapacity:1]; [self.adjDataSource addObject:neighbourVertex];//建立鄰接表,將所有鏈表初始化為空白 } } return self;}//http://www.cnblogs.com/xiaofeixiang-(void)addEdges:(NSInteger)startVertex endVertex:(NSInteger)endVertex{ //將endVertex添加到startVertex的鏈表中 [self.adjDataSource[startVertex] insertObject:[NSNumber numberWithInteger:endVertex] atIndex:0]; self.edges=self.edges+1;}-(Digraph *)reverse{ Digraph *digraph=[[Digraph alloc]initWithVertex:self.vertexs]; for (NSInteger i=0; i<self.vertexs; i++) { NSMutableArray *tempArr=self.adjDataSource[i]; for (NSInteger j=0; j<[tempArr count]; j++) { [digraph addEdges:[tempArr[j] integerValue] endVertex:i]; } } return digraph;}#pragma mark getter and setter-(NSMutableArray *)adjDataSource{ if (!_adjDataSource) { _adjDataSource=[[NSMutableArray alloc]initWithCapacity:1]; } return _adjDataSource;}@end
測試代碼:
Digraph *graph=[[Digraph alloc]initWithVertex:13]; [graph addEdges:4 endVertex:2]; [graph addEdges:2 endVertex:3]; [graph addEdges:3 endVertex:2]; [graph addEdges:6 endVertex:0]; [graph addEdges:0 endVertex:1]; [graph addEdges:2 endVertex:0]; [graph addEdges:11 endVertex:12]; [graph addEdges:12 endVertex:9]; [graph addEdges:9 endVertex:10]; [graph addEdges:9 endVertex:11]; [graph addEdges:8 endVertex:9]; [graph addEdges:10 endVertex:12]; [graph addEdges:11 endVertex:4]; [graph addEdges:4 endVertex:3]; [graph addEdges:3 endVertex:5]; [graph addEdges:7 endVertex:8]; [graph addEdges:8 endVertex:7]; [graph addEdges:5 endVertex:4]; [graph addEdges:0 endVertex:5]; [graph addEdges:6 endVertex:4]; [graph addEdges:6 endVertex:9]; [graph addEdges:7 endVertex:6]; for (NSInteger i=0; i<[graph.adjDataSource count]; i++) { NSLog(@"節點%ld指出→的節點:%@",i,[graph.adjDataSource[i] componentsJoinedByString:@"--"]); } NSLog(@"技術交流群:%@",@"228407086"); NSLog(@"原文地址:http://www.cnblogs.com/xiaofeixiang");
測試效果:
現在可以判斷出頂點的指出節點,實現檔案中有一個reverse方法將圖反轉,求出頂點的轉入節點:
Digraph *digraph=[graph reverse]; for (NSInteger i=0; i<[digraph.adjDataSource count]; i++) { NSLog(@"指入%ld??的節點:%@",i,[digraph.adjDataSource[i] componentsJoinedByString:@"--"]); } NSLog(@"技術交流群:%@",@"228407086"); NSLog(@"原文地址:http://www.cnblogs.com/xiaofeixiang");
測試效果:
可達性
可達性的判斷和之前的深度優先搜尋基本沒變化,先來看一下需要實現的方法:
@interface DirectedDFS : NSObject//標記數組@property (strong,nonatomic) NSMutableArray *marked;//找到arr中頂點可達的所有頂點-(instancetype)initDirectedDFSWithVertex:(Digraph *)graph vertexArr:(NSArray *)arr;//在graph中找到從vertex可達的所有頂點-(void)directedDFS:(Digraph *)graph vertex:(NSInteger)vertex;//vertex是否可達-(Boolean)isMarked:(NSInteger)vertex;@end
實現代碼:
@implementation DirectedDFS#pragma mark getter and setter-(NSMutableArray *)marked{ if (!_marked) { _marked=[[NSMutableArray alloc]initWithCapacity:1]; } return _marked;}-(instancetype)initDirectedDFSWithVertex:(Digraph *)graph vertexArr:(NSArray *)arr{ self=[super init]; if (self) { for (NSInteger i=0; i<graph.vertexs;i++) { [self.marked addObject:[NSNull null]]; } //遍曆有向圖中的頂點 for (NSInteger j=0; j<[arr count]; j++) { if (![self isMarked:[arr[j] integerValue]]) { [self directedDFS:graph vertex:[arr[j] integerValue]]; } } } return self;}//部落格園-FlyElephant:http://www.cnblogs.com/xiaofeixiang/-(void)directedDFS:(Digraph *)graph vertex:(NSInteger)vertex{ self.marked[vertex]=[NSNumber numberWithBool:true]; for (NSInteger i=0; i<[graph.adjDataSource[vertex] count]; i++) { NSInteger temp=[[graph.adjDataSource[vertex] objectAtIndex:i] integerValue]; if (![self isMarked:temp]) { [self directedDFS:graph vertex:temp]; } }}-(Boolean)isMarked:(NSInteger)vertex{ return self.marked[vertex]==[NSNull null]?false:[self.marked[vertex] boolValue];}@end
測試代碼:
NSArray *sources=[NSArray arrayWithObjects:@"2", nil]; DirectedDFS *directedDFS=[[DirectedDFS alloc]initDirectedDFSWithVertex:graph vertexArr:sources]; NSMutableArray *reachableArr=[[NSMutableArray alloc]initWithCapacity:1]; for (NSInteger i=0; i<graph.vertexs; i++) { if (directedDFS.marked[i]&&directedDFS.marked[i]!=[NSNull null]) { [reachableArr addObject:[NSNumber numberWithInteger:i]]; } } NSLog(@"可達的節點:%@",[reachableArr componentsJoinedByString:@"--"]); NSLog(@"技術交流群:%@",@"228407086"); NSLog(@"部落格園-FlyElephant:http://www.cnblogs.com/xiaofeixiang");
測試效果:
演算法-有向圖及可達性