您的位置:首页 > 其它

计算流图中的前必经节点

2014-01-30 07:00 134 查看


《现代编译器的Java实现》中的一图,左边是流图,右边是必经节点树

根据必经节点的算法写了程序验证了下。

只是为了验证算法,并没有考虑最优算法,不过因为此流图足够简单,所以只迭代了两次即求出了结果。

代码如下:

Node类抽象图中的节点,Dominator类用来计算

import java.util.ArrayList;
import java.util.List;

public class Node {
// 序号
public int no;
// 后接节点列表
public List<Node> nextList = new ArrayList<Node>();
// 前接节点列表
public List<Node> preList = new ArrayList<Node>();
// 初始前必经节点(全体节点)
public List<Node> dominatorList = new ArrayList<Node>();

public Node(int no) {
this.no = no;
}

public void addNext(Node n){
nextList.add(n);
n.preList.add(this);
}

public String toString(){
return no+"";
}
}


import java.util.ArrayList;
import java.util.List;

public class Dominator {

public static void main(String[] args) {
//初期化所有节点   并设置节点间连接关系
List<Node> nodeList = getNodeList(12);
// 计算前必经节点
doDominator(nodeList);
//打印必经节点列表
printResult(nodeList);

}

// 打印必经结果
public static void printResult(List<Node> nodeList) {
for (int i = 0; i < nodeList.size(); i++) {
Node node = nodeList.get(i);
System.out.println("*******************");
System.out.println("node" + (i + 1));
printNodeListNo(node.dominatorList);
}
}

//打印节点NO
public static void printNodeListNo(List<Node> nodeList) {
System.out.println("------");
for (int i = 0; i < nodeList.size(); i++) {
if (i != 0) {
System.out.print(",");
}
System.out.print(nodeList.get(i).no);
}
System.out.println();
}

// 计算必经节点
public static void doDominator(List<Node> nodeList) {
//迭代次数
int n = 1;
//判断状态是否稳定Flag
boolean changed = true;
while (changed) {
System.out.println("迭代次数:" + n++);
changed = false;
for (int i = 0; i < nodeList.size(); i++) {
Node node = nodeList.get(i);
List<Node> lastDominatorList = new ArrayList<Node>();
lastDominatorList.addAll(node.dominatorList);
List<Node> temList = new ArrayList<Node>();

for (Node preNode : node.preList) {
List<Node> preDomList = preNode.dominatorList;
if (temList.isEmpty()) {
temList.addAll(preDomList);
} else {
temList.retainAll(preDomList);
}
}
temList.add(node);
int lastSize = lastDominatorList.size();
lastDominatorList.retainAll(temList);
if (lastSize != lastDominatorList.size()) {
node.dominatorList = temList;
changed = true;
}
}
}
}

//初期化所有节点   并设置节点间连接关系
public static List<Node> getNodeList(int size) {
List<Node> nodeList = new ArrayList<Node>(size);
for (int i = 0; i < size; i++) {
Node node = new Node(i + 1);
nodeList.add(node);
}
Node node1 = nodeList.get(0);
Node node2 = nodeList.get(1);
Node node3 = nodeList.get(2);
Node node4 = nodeList.get(3);
Node node5 = nodeList.get(4);
Node node6 = nodeList.get(5);
Node node7 = nodeList.get(6);
Node node8 = nodeList.get(7);
Node node9 = nodeList.get(8);
Node node10 = nodeList.get(9);
Node node11 = nodeList.get(10);
Node node12 = nodeList.get(11);
// 节点之间关系设定
node1.addNext(node2);
//
node2.addNext(node3);
node2.addNext(node4);
//
node3.addNext(node2);
//
node4.addNext(node2);
node4.addNext(node5);
node4.addNext(node6);
//
node5.addNext(node7);
node5.addNext(node8);
//
node6.addNext(node7);
//
node7.addNext(node11);
//
node8.addNext(node9);
//
node9.addNext(node8);
node9.addNext(node10);
//
node10.addNext(node5);
node10.addNext(node12);
//
node11.addNext(node12);
//初期化前必经节点的列表
for (int i = 0; i < nodeList.size(); i++) {
nodeList.get(i).dominatorList.addAll(nodeList);
}
return nodeList;
}

}


打印结果如下:

迭代次数:1
迭代次数:2
*******************
node1
------
1
*******************
node2
------
1,2
*******************
node3
------
1,2,3
*******************
node4
------
1,2,4
*******************
node5
------
1,2,4,5
*******************
node6
------
1,2,4,6
*******************
node7
------
1,2,4,7
*******************
node8
------
1,2,4,5,8
*******************
node9
------
1,2,4,5,8,9
*******************
node10
------
1,2,4,5,8,9,10
*******************
node11
------
1,2,4,7,11
*******************
node12
------
1,2,4,12
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: