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