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

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

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

代码如下:

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

 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(int no) {
15         this.no = no;
16     }
17 
18     public void addNext(Node n){
19         nextList.add(n);
20         n.preList.add(this);
21     }
22     
23     public String toString(){
24         return no+"";
25     }
26 }
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