继续以上流图为例,上篇只求了各节点的前必经节点集合。
这篇中,计算以下几个元素:
(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 }