继续以上流图为例,上篇只求了各节点的前必经节点集合。
这篇中,计算以下几个元素:
(1)直接前必经节点
(2)求出所有的回边列表
(3)求出图中所有的循环


1
import java.util.ArrayList; 2 import java.util.List; 3 4 public class Node { 5 // 序号 6 public int no; 7 // 后接节点列表 8 public List<Node> nextList = new ArrayList<Node>(); 9 // 前接节点列表 10 public List<Node> preList = new ArrayList<Node>(); 11 // 前必经节点 12 public List<Node> dominatorList = new ArrayList<Node>(); 13 //直接必经节点 14 public Node zDominator=null; 15 public Node(int no) { 16 this.no = no; 17 } 18 19 public void addNext(Node n){ 20 nextList.add(n); 21 n.preList.add(this); 22 } 23 24 public String toString(){ 25 return no+""; 26 } 27 }
 1 public class BackEdge {
 2 
 3     public Node fromNode;
 4     public Node toNode;
 5     
 6     public BackEdge(Node fromNode,Node toNode){
 7         this.fromNode=fromNode;
 8         this.toNode=toNode;
 9     }
10 }
 1 import java.util.ArrayList;
 2 import java.util.List;
 3 
 4 
 5 public class Loop {
 6 
 7     BackEdge backEdge=null;
 8     List<Node> nodeList=new ArrayList<Node>();
 9     public Loop(BackEdge backEdge){
10         this.backEdge=backEdge;
11     }
12     
13     public void add(Node node){
14         nodeList.add(node);
15     }
16     
17     public boolean contains(Node node){
18         if(nodeList.contains(node)){
19             return true;
20         }
21         return false;
22     }
23     
24     public String toString(){
25         StringBuilder stb=new StringBuilder();
26         stb.append("Loop{");
27         for(int i=0;i<nodeList.size();i++){
28             if(i!=0){
29                 stb.append(",");
30             }
31             stb.append(nodeList.get(i).no);
32         }
33         stb.append("}");
34         return stb.toString();
35     }
36 }
  1 import java.util.ArrayList;
  2 import java.util.LinkedList;
  3 import java.util.List;
  4 
  5 public class Dominator {
  6 
  7     public static void main(String[] args) {
  8         // 初期化所有节点 并设置节点间连接关系
  9         List<Node> nodeList = getNodeList(12);
 10         // 计算前必经节点
 11         doDominator(nodeList);
 12         // 计算直接必经节点
 13         doZDominator(nodeList);
 14         // 打印必经节点列表
 15         printResult(nodeList);
 16         // 检索回边
 17         List<BackEdge> backEdgeList=searchLoop(nodeList);
 18         //打印回边列表
 19         printBackEdgeList(backEdgeList);
 20         //根据回边求出自然循环
 21         List<Loop> loopList=getLoopList(backEdgeList);
 22         //打印循环集合
 23         printLoopList(loopList);
 24 
 25     }
 26 
 27     //打印循环集合
 28     public static void printLoopList(List<Loop> loopList){
 29         System.out.println("循环列表:");
 30         for(int i=0;i<loopList.size();i++){
 31             System.out.println(i+1+":"+loopList.get(i));
 32         }
 33     }
 34     
 35     //根据回边求出自然循环
 36     public static List<Loop> getLoopList(List<BackEdge> backEdgeList){
 37         List<Loop> loopList=new ArrayList<>();
 38         for(BackEdge be:backEdgeList){
 39             LinkedList<Node> stack=new LinkedList<>();
 40             Loop loop=new Loop(be);
 41             loop.add(be.toNode);
 42             insertNode(be.fromNode,loop,stack);
 43             while(!stack.isEmpty()){
 44                 Node m=stack.pop();
 45                 List<Node> preList=m.preList;
 46                 for(Node p:preList){
 47                     insertNode(p,loop,stack);
 48                 }
 49             }
 50             loopList.add(loop);
 51         }
 52         return loopList;
 53     }
 54     
 55     
 56     private static void insertNode(Node node,Loop loop,LinkedList<Node> stack){
 57         if(loop.contains(node)){
 58             return;
 59         }
 60         loop.add(node);
 61         stack.push(node);
 62     }
 63     
 64     //打印回边列表
 65     public static void printBackEdgeList(List<BackEdge> backEdgeList){
 66         System.out.println("回边列表:");
 67         int i=1;
 68         for(BackEdge be:backEdgeList){
 69             System.out.println(i+++":"+be.fromNode.no+"->"+be.toNode.no);
 70         }
 71     }
 72     
 73     
 74     // 检索循环
 75     public static List<BackEdge> searchLoop(List<Node> nodeList) {
 76         List<BackEdge> backEdgeList=new ArrayList<BackEdge>();
 77         for (Node node : nodeList) {
 78             List<Node> temList = new ArrayList<Node>();
 79             temList.addAll(node.nextList);
 80             temList.retainAll(node.dominatorList);
 81             if (!temList.isEmpty()) {
 82                 for (Node toNode : temList) {
 83                     BackEdge be = new BackEdge(node, toNode);
 84                     backEdgeList.add(be);
 85                 }
 86             }
 87         }
 88         return backEdgeList;
 89     }
 90 
 91     // 计算直接必经节点
 92     public static void doZDominator(List<Node> nodeList) {
 93         for (Node node : nodeList) {
 94             List<Node> dominatorList = node.dominatorList;
 95             if (dominatorList.size() == 1) {
 96                 continue;
 97             }
 98             int maxSize = 1;
 99             for (Node dNode : dominatorList) {
100                 if (dNode == node) {
101                     continue;
102                 }
103                 int size = dNode.dominatorList.size();
104                 if (size >= maxSize) {
105                     maxSize = size;
106                     node.zDominator = dNode;
107                 }
108             }
109 
110         }
111     }
112 
113     // 打印必经结果
114     public static void printResult(List<Node> nodeList) {
115         for (int i = 0; i < nodeList.size(); i++) {
116             Node node = nodeList.get(i);
117             System.out.println("*******************");
118             System.out.println("node" + (i + 1));
119             System.out.print("前必经节点:");
120             printNodeListNo(node.dominatorList);
121             System.out.println("直接必经节点:" + node.zDominator);
122             System.out.println("!!!!!!!!!!!!!!!!!!!!!!!!!");
123         }
124     }
125 
126     // 打印节点NO
127     public static void printNodeListNo(List<Node> nodeList) {
128         for (int i = 0; i < nodeList.size(); i++) {
129             if (i != 0) {
130                 System.out.print(",");
131             }
132             System.out.print(nodeList.get(i).no);
133         }
134         System.out.println();
135     }
136 
137     // 计算必经节点
138     public static void doDominator(List<Node> nodeList) {
139         // 迭代次数
140         int n = 1;
141         // 判断状态是否稳定Flag
142         boolean changed = true;
143         while (changed) {
144             System.out.println("迭代次数:" + n++);
145             changed = false;
146             for (int i = 0; i < nodeList.size(); i++) {
147                 Node node = nodeList.get(i);
148                 List<Node> lastDominatorList = new ArrayList<Node>();
149                 lastDominatorList.addAll(node.dominatorList);
150                 List<Node> temList = new ArrayList<Node>();
151 
152                 for (Node preNode : node.preList) {
153                     List<Node> preDomList = preNode.dominatorList;
154                     if (temList.isEmpty()) {
155                         temList.addAll(preDomList);
156                     } else {
157                         temList.retainAll(preDomList);
158                     }
159                 }
160                 temList.add(node);
161                 int lastSize = lastDominatorList.size();
162                 lastDominatorList.retainAll(temList);
163                 if (lastSize != lastDominatorList.size()) {
164                     node.dominatorList = temList;
165                     changed = true;
166                 }
167             }
168         }
169     }
170 
171     // 初期化所有节点 并设置节点间连接关系
172     public static List<Node> getNodeList(int size) {
173         List<Node> nodeList = new ArrayList<Node>(size);
174         for (int i = 0; i < size; i++) {
175             Node node = new Node(i + 1);
176             nodeList.add(node);
177         }
178         Node node1 = nodeList.get(0);
179         Node node2 = nodeList.get(1);
180         Node node3 = nodeList.get(2);
181         Node node4 = nodeList.get(3);
182         Node node5 = nodeList.get(4);
183         Node node6 = nodeList.get(5);
184         Node node7 = nodeList.get(6);
185         Node node8 = nodeList.get(7);
186         Node node9 = nodeList.get(8);
187         Node node10 = nodeList.get(9);
188         Node node11 = nodeList.get(10);
189         Node node12 = nodeList.get(11);
190         // 节点之间关系设定
191         node1.addNext(node2);
192         //
193         node2.addNext(node3);
194         node2.addNext(node4);
195         //
196         node3.addNext(node2);
197         //
198         node4.addNext(node2);
199         node4.addNext(node5);
200         node4.addNext(node6);
201         //
202         node5.addNext(node7);
203         node5.addNext(node8);
204         //
205         node6.addNext(node7);
206         //
207         node7.addNext(node11);
208         //
209         node8.addNext(node9);
210         //
211         node9.addNext(node8);
212         node9.addNext(node10);
213         //
214         node10.addNext(node5);
215         node10.addNext(node12);
216         //
217         node11.addNext(node12);
218         // 初期化前必经节点的列表
219         for (int i = 0; i < nodeList.size(); i++) {
220             nodeList.get(i).dominatorList.addAll(nodeList);
221         }
222         return nodeList;
223     }
224 
225 }