Algorithm-A forward loop and a topological sort

Source: Internet
Author: User

The direction graph includes the direction of the loop and the direction of the loop graph, the direction of the task scheduling priority limit is very useful, the most common is the university scheduling system, such as computer operating system priority higher than advanced mathematics, we can be represented as computer operating system → advanced mathematics, higher mathematics higher than linear algebra, If this time the linear algebra priority is higher than the computer operating system, then produced a forward ring, unable to arrange classes, the course is generally more, if the diagram to determine whether there is a loop is a troublesome thing, so it is often necessary to determine whether the direction of the graph has a ring.

Forward Loop detection

If a node in a directed graph can start from a node in the direction of the path and return itself, a closed loop is formed to determine that the graph contains a forward loop. The decision in the forward loop is similar to a deep search in the previous graph, if a→b, the secondary data structure of the previous diagram we store is so that the value corresponding to a contains B, if index B contains a value A, that contains a forward loop.

The API with the forward loop detection has an array that holds the middle node of the forward loop, and the recursive array that needs to be called, with the previous depth search:

@interface directedcycle:nsobject//Tag Array @property  (strong,nonatomic)  Nsmutablearray  *marked;@ The property  (strong,nonatomic)  Nsmutablearray  *cycle;//has all the vertices in the ring (where there is a forward loop) @property  (Strong, nonatomic)  Nsmutablearray  *onstack;//all vertices on the stack of the recursive call//from the beginning to the last vertex on the known path of a vertex @property  (Strong, nonatomic)  Nsmutablearray *edgeto; @property (assign,nonatomic)  Boolean hascycle;//Initialization-(instancetype) Initwithgraph: (Digraph *) graph;-(void) Depthsearch: (Digraph *) Graph  vertex: (nsinteger) vertex; @end

Implementation code:

@implementation Directedcycle#pragma Mark Getter and setter-(Nsmutablearray *) marked{if (!_marked) {_marked=[    [Nsmutablearray alloc]initwithcapacity:1]; } return _marked;}    -(Nsmutablearray *) onstack{if (!_onstack) {_onstack=[[nsmutablearray alloc]initwithcapacity:1]; } return _onstack;}    -(Nsmutablearray *) edgeto{if (!_edgeto) {_edgeto=[[nsmutablearray alloc]initwithcapacity:1]; } return _edgeto;}    -(Instancetype) Initwithgraph: (Digraph *) graph{self=[super init];            if (self) {for (Nsinteger i=0; i<graph.vertexs;i++) {[Self.onstack addobject:[nsnull null]];            [Self.edgeto addobject:[nsnull Null]];        [self.marked addobject:[nsnull Null]]; }//Traverse the graph's vertex for (Nsinteger s=0; s<graph.vertexs; s++) {if (![            Self ismarked:s]) {[self depthsearch:graph vertex:s]; }}} return self;} http://www.cnblogs.com/xiaofeixiang/-(void) DepthseArch: (Digraph *) graph vertex: (nsinteger) vertex{Self.onstack[vertex]=[nsnumber numberwithbool:true];        Self.marked[vertex]=[nsnumber Numberwithbool:true]; for (Nsinteger i=0; I<[graph.adjdatasource[vertex] count]; i++) {Nsinteger Temp=[[graph.adjdatasource[vertex] o        BJECTATINDEX:I] IntegerValue];        if ([self hascycle]) return; else if (![            Self ismarked:temp]) {self.edgeto[temp]=[nsnumber Numberwithinteger:vertex];        [Self depthsearch:graph vertex:temp];            }else if ([self isstack:temp]) {Self.cycle=[[nsmutablearray alloc]initwithcapacity:1]; for (Nsinteger I=vertex; i!=temp; i=[self.edgeto[i] IntegerValue]) {[Self.cycle insertobject:[nsnumber num            BERWITHINTEGER:I] atindex:0];            } [self.cycle Insertobject:[nsnumber numberwithinteger:temp] atindex:0];        [Self.cycle Insertobject:[nsnumber Numberwithinteger:vertex] atindex:0]; }} self.onstack[vErtex]=[nsnumber Numberwithbool:false];} -(Boolean) hascycle{return [Self.cycle count]>0;} -(Boolean) ismarked: (Nsinteger) vertex{return self.marked[vertex]==[nsnull Null]?false:[self.marked[vertex] Boolvalue];} -(Boolean) Isstack: (Nsinteger) vertex{return self.onstack[vertex]==[nsnull Null]?false:[self.onstack[vertex] Boolvalue];} @end

test code:

        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]; Directedcycle *directedcycle=[[directedcycle Alloc]initwithgraph:gRaph];         if ([directedcycle.cycle count]) {NSLog (@ "The node forming a forward loop is:%@", [directedcycle.cycle componentsjoinedbystring:@ "--"]);        } NSLog (@ "Technology Exchange Group:%@", @ "228407086"); NSLog (@ "blog Park-flyelephant:http://www.cnblogs.com/xiaofeixiang");

Test results:

Topological sorting

Topological sequencing can solve the problem of scheduling, task scheduling, but only the directed acyclic graph (Directed acyclic graph abbreviated DAG) can be sorted, and the forward loop detection is an aid to the topological ordering. Topological sorting can also be modified in the same depth-first search, the deep search will access each vertex just once, can be in the depth of the search recursive parameter vertices in a data structure, traverse the data structure can access all the vertices in the graph, the order of the traversal depends on the time of the call, can also be after recursion before recursion.

In general, there are three sorts of permutations:

    • Pre-order: The array is added before recursion;
    • Post-entry: Add the array after recursion;
    • Reverse post-entry: In the recursive value of the week into the array, but each time is stored in the first, similar to the stack;

Vertex sort:

@interface depthfirstorder:nsobject//record whether vertices are marked @property  (strong,nonatomic)  Nsmutablearray  *marked;@ Property  (strong,nonatomic)  Nsmutablearray  *prequeue;//The pre-order arrangement of all vertices @property  (strong,nonatomic)  Nsmutablearray  *postqueue;//The order of all vertices @property  (strong,nonatomic)   nsmutablearray  * reversepoststack;//the inverse order of all vertices @property (assign,nonatomic)  Nsinteger count;//Find all connected nodes with seven points vertex-( Instancetype) Initwithgraph: (Digraph *) graph;-(void) Depthsearch: (Digraph *) Graph  vertex: (nsinteger) vertex;// Whether the node is marked-(Boolean) ismarked: (Nsinteger) vertex; @end

Implementation file:

@implementation Depthfirstorder#pragma Mark Getter and setter-(Nsmutablearray *) marked{if (!_marked) {_marked    =[[nsmutablearray Alloc]initwithcapacity:1]; } return _marked;}    -(Nsmutablearray *) prequeue{if (!_prequeue) {_prequeue=[[nsmutablearray alloc]initwithcapacity:1]; } return _prequeue;}    -(Nsmutablearray *) postqueue{if (!_postqueue) {_postqueue=[[nsmutablearray alloc]initwithcapacity:1]; } return _postqueue;} -(Nsmutablearray *) reversepoststack{if (!_reversepoststack) {_reversepoststack=[[nsmutablearray Alloc]initWith    CAPACITY:1]; } return _reversepoststack;}    -(Instancetype) Initwithgraph: (Digraph *) graph{self=[super init];        if (self) {for (Nsinteger i=0; i<graph.vertexs;i++) {[self.marked addobject:[nsnull null]]; }//Traverse the graph's vertex for (Nsinteger s=0; s<graph.vertexs; s++) {if (![          Self ismarked:s]) {[self depthsearch:graph vertex:s];  }}} return self;} http://www.cnblogs.com/xiaofeixiang/-(void) Depthsearch: (Digraph *) graph vertex: (nsinteger) vertex{[        Self.prequeue Addobject:[nsnumber Numberwithinteger:vertex]];    Self.marked[vertex]=[nsnumber Numberwithbool:true];    self.count++; for (Nsinteger i=0; I<[graph.adjdatasource[vertex] count]; i++) {Nsinteger Temp=[[graph.adjdatasource[vertex] o        BJECTATINDEX:I] IntegerValue]; if (![        Self ismarked:temp]) {[self depthsearch:graph vertex:temp];    }} [Self.postqueue Addobject:[nsnumber Numberwithinteger:vertex]; [Self.reversepoststack Insertobject:[nsnumber Numberwithinteger:vertex] atindex:0];} -(Boolean) ismarked: (Nsinteger) vertex{return self.marked[vertex]==[nsnull Null]?false:[self.marked[vertex] Boolvalue];} @end

Both the loopback check and the vertex sort are prepared for topological ordering, and the topology ordering only needs to be called:

@interface topologicalsort:nsobject@property  (strong,nonatomic)  Nsmutablearray  *order;-( Instancetype) Initwithdigraph: (Digraph *) graph; @end

Implementation file:

@implementation Topologicalsort#pragma Mark Getter and  setter-(Nsmutablearray *) order{    if (!_order) {        _ Order=[[nsmutablearray alloc]initwithcapacity:1];    }    return _order;} -(Instancetype) Initwithdigraph: (Digraph *) graph{    self=[super init];    if (self) {        directedcycle *cyclefinder=[[directedcycle alloc]initwithgraph:graph];        if (!cyclefinder.hascycle) {            depthfirstorder  *dfs=[[depthfirstorder alloc]initwithgraph:graph];            Self.order=dfs.reversepoststack;        }    }    return self;} @end

We can check the correctness of the program by the following image:

Test code:

        Digraph *digraph=[[digraph alloc]initwithvertex:13];        [digraph addedges:0 Endvertex:6];        [digraph addedges:0 endvertex:1];        [digraph addedges:0 Endvertex:5];        [digraph addedges:2 endvertex:0];        [digraph addedges:2 Endvertex:3];        [digraph addedges:3 Endvertex:5];        [digraph addedges:5 Endvertex:4];        [digraph addedges:6 Endvertex:4];        [digraph addedges:6 Endvertex:9];        [digraph addedges:7 Endvertex:6];        [digraph addedges:8 Endvertex:7];        [digraph addedges:9 endvertex:10];        [digraph addedges:9 Endvertex:12];        [digraph addedges:9 endvertex:11];        [digraph addedges:11 Endvertex:12];        Topologicalsort *logicsort=[[topologicalsort Alloc]initwithdigraph:digraph];        for (Nsinteger i=0; i<[logicsort.order count]; i++) {NSLog (@ "Node%ld", [Logicsort.order[i] integervalue]);        } NSLog (@ "Technology Exchange Group:%@", @ "228407086"); NSLog (@ "Blog Park-flyelephant:http://www.cnblogs.com/xiaoFeixiang "); 

Test results:

If the node representation may be more straightforward, the effect is as follows:

Algorithm-A forward loop and a topological sort

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.