图算法的实现

不包括最大流

package graph;

import java.util.*;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.PriorityBlockingQueue;

/**
 * Created by chenzhichao on 16/6/2.
 */
public class Graph {

    public static final int WHITE = 1;
    public static final int GRAY = 2;
    public static final int BLACK = 3;
    public static int time = 0;
    private LinkedBlockingQueue queue = new LinkedBlockingQueue();
    public ListGraphNode[] nodeList = new ListGraphNode[100];

    public static class ListGraphNode implements Cloneable {
        public int position;
        public int color = WHITE;
        private int begin;
        public int finish;
        private int d = Integer.MAX_VALUE;
        private ListGraphNode pre = null;
        private SimpleNode next = null;

        public ListGraphNode(int position) {
            this.position = position;
        }

        @Override
        protected ListGraphNode clone() throws CloneNotSupportedException {
            return (ListGraphNode) (super.clone());
        }
    }

    public static class SimpleNode implements Cloneable {
        private int position;
        private int weight;
        private SimpleNode next = null;

        public SimpleNode(int position) {
            this.position = position;
        }

        public SimpleNode(int position, int weight) {
            this.position = position;
            this.weight = weight;
        }

        @Override
        protected SimpleNode clone() throws CloneNotSupportedException {
            return (SimpleNode) (super.clone());
        }
    }

    /**
     * 边
     */
    public static class Edge implements Comparable {
        protected int weight;
        protected ListGraphNode from;
        protected ListGraphNode to;

        public Edge(int weight, ListGraphNode from, ListGraphNode to) {
            this.weight = weight;
            this.from = from;
            this.to = to;
        }

        public Edge() {
        }

        @Override
        public int compareTo(Object o) {
            return weight;
        }
    }

    public void init1() {
        ListGraphNode node = new ListGraphNode(1);
        node.next = new SimpleNode(2);
        node.next.next = new SimpleNode(4);
        nodeList[1] = node;
        node = new ListGraphNode(2);
        node.next = new SimpleNode(5);
        nodeList[2] = node;
        node = new ListGraphNode(3);
        node.next = new SimpleNode(5);
        node.next.next = new SimpleNode(6);
        nodeList[3] = node;
        node = new ListGraphNode(4);
        node.next = new SimpleNode(2);
        nodeList[4] = node;
        node = new ListGraphNode(5);
        node.next = new SimpleNode(4);
        nodeList[5] = node;
        node = new ListGraphNode(6);
        node.next = new SimpleNode(6);
        nodeList[6] = node;
    }


    public void init2() {
        ListGraphNode node = new ListGraphNode(0);
        node.next = new SimpleNode(1, 10);
        node.next.next = new SimpleNode(5, 11);
        nodeList[0] = node;
        node = new ListGraphNode(1);
        node.next = new SimpleNode(2, 18);
        node.next.next = new SimpleNode(8, 12);
        node.next.next.next = new SimpleNode(6, 16);
        nodeList[1] = node;
        node = new ListGraphNode(2);
        node.next = new SimpleNode(8, 8);
        node.next.next = new SimpleNode(3, 22);
        nodeList[2] = node;
        node = new ListGraphNode(3);
        node.next = new SimpleNode(8, 21);
        node.next.next = new SimpleNode(6, 24);
        node.next.next.next = new SimpleNode(7, 16);
        node.next.next.next.next = new SimpleNode(4, 20);
        nodeList[3] = node;
        node = new ListGraphNode(4);
        node.next = new SimpleNode(7, 7);
        node.next.next = new SimpleNode(5, 26);
        nodeList[4] = node;
        node = new ListGraphNode(5);
        node.next = new SimpleNode(6, 17);
        nodeList[5] = node;
        node = new ListGraphNode(6);
        node.next = new SimpleNode(7, 19);
        nodeList[6] = node;
        node = new ListGraphNode(7);
        nodeList[7] = node;
        node = new ListGraphNode(8);
        nodeList[8] = node;
    }

    public void init4(){
        ListGraphNode node = new ListGraphNode(0);
        node.next = new SimpleNode(1,10);
        node.next.next = new SimpleNode(4,5);
        nodeList[0] = node;
        node = new ListGraphNode(1);
        node.next = new SimpleNode(2,1);
        node.next.next = new SimpleNode(4,2);
        nodeList[1] = node;
        node = new ListGraphNode(2);
        node.next = new SimpleNode(3,4);
        nodeList[2] = node;
        node = new ListGraphNode(3);
        node.next = new SimpleNode(2,6);
        node.next.next = new SimpleNode(0,7);
        nodeList[3] = node;
        node = new ListGraphNode(4);
        node.next = new SimpleNode(2,9);
        node.next.next = new SimpleNode(3,2);
        node.next.next.next = new SimpleNode(1,3);
        nodeList[4] = node;
    }
    public static class SimpleEdge {
        public int weight = Integer.MAX_VALUE;
        public int pre = -1;

        public SimpleEdge(int weight) {
            this.weight = weight;
        }

        public SimpleEdge() {
        }

        public SimpleEdge(int weight, int pre) {
            this.weight = weight;
            this.pre = pre;
        }
    }

    public static SimpleEdge[][] init3() {
        SimpleEdge[][] edges = new SimpleEdge[5][5];
        edges[0][1] = new SimpleEdge(3, 0);
        edges[0][2] = new SimpleEdge(8, 0);
        edges[0][4] = new SimpleEdge(-4, 0);
        edges[1][4] = new SimpleEdge(7, 1);
        edges[1][3] = new SimpleEdge(1, 1);
        edges[2][1] = new SimpleEdge(4, 2);
        edges[3][0] = new SimpleEdge(2, 3);
        edges[3][2] = new SimpleEdge(-5, 3);
        edges[4][3] = new SimpleEdge(6, 4);
        for (int i = 0; i < 5; i++)
            for (int j = 0; j < 5; j++)
                if (edges[i][j] == null) {
                    edges[i][j] = new SimpleEdge();
                    if (i == j)
                        edges[i][j].weight = 0;
                }
        return edges;
    }

    /**
     * 广度优先遍历
     * 一个元素出队->遍历操作->他的所有邻接点入队
     */
    public void BFS() {
        nodeList[1].color = GRAY;
        nodeList[1].d = 0;
        queue.offer(nodeList[1]);
        while (queue.size() != 0) {
            ListGraphNode node = queue.poll();
            System.out.print(node.position + "***");
            SimpleNode next = node.next;
            while (next != null) {
                ListGraphNode currentNode = nodeList[next.position];
                if (currentNode.color == WHITE) {
                    currentNode.color = GRAY;
                    currentNode.d = node.d + 1;
                    currentNode.pre = node;
                    queue.offer(currentNode);
                }
                next = next.next;
            }
            node.color = BLACK;
        }
    }

    /**
     * 深度优先遍历
     * 对当前点进行遍历操作->对所有邻接点逐个进行深度优先遍历
     * 拓扑排序是在深度优先遍历结束后,按finish对节点进行排序(前提:有向无环图)
     */
    public void DFS() {
        for (ListGraphNode node : nodeList)
            if (node != null && node.color == WHITE) {
                dfs_visit(node);
                System.out.println("*********************");
            }
    }

    public void dfs_visit(ListGraphNode node) {
        node.color = GRAY;
        node.begin = ++time;
        SimpleNode next = node.next;
        while (next != null) {
            if (nodeList[next.position].color == WHITE)
                dfs_visit(nodeList[next.position]);
            next = next.next;
        }
        node.color = BLACK;
        node.finish = ++time;
        System.out.println(node.position + ",begin = " + node.begin + ",finish = " + node.finish);
    }

    /**
     * 邻接矩阵求转置
     */
    public Graph getT() {
        ListGraphNode[] newNodeList = new ListGraphNode[nodeList.length];
        TreeMap> map = new TreeMap>();
        try {
            for (int i = 0; i < nodeList.length; i++) {
                if (nodeList[i] != null) {
                    newNodeList[i] = nodeList[i].clone();
                    newNodeList[i].next = null;
                    List list = new ArrayList();
                    SimpleNode next = nodeList[i].next;
                    while (next != null) {
                        list.add(next.clone());
                        next = next.next;
                    }
                    map.put(i, list);
                }
            }
            for (Map.Entry> entry : map.entrySet()) {
                for (SimpleNode sn : entry.getValue()) {
                    sn.next = newNodeList[sn.position].next;
                    newNodeList[sn.position].next = sn;
                    sn.position = entry.getKey();
                }
            }
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        Graph g = new Graph();
        g.nodeList = newNodeList;
        return g;
    }

    /**
     * 强连通分量
     */
    public static void stronglyConnectedComponents(Graph g) {
        g.DFS();
        System.out.println("+++++++++++++++++++++++");
        Graph gt = g.getT();
        Graph.ListGraphNode[] temp = Arrays.copyOfRange(g.nodeList, 1, 7);
        Arrays.sort(temp, new Comparator() {
            @Override
            public int compare(Graph.ListGraphNode o1, Graph.ListGraphNode o2) {
                return o2.finish - o1.finish;
            }
        });
        for (ListGraphNode node : gt.nodeList)
            if (node != null)
                node.color = Graph.WHITE;
        for (Graph.ListGraphNode node : temp) {
            if (gt.nodeList[node.position].color == Graph.WHITE) {
                gt.dfs_visit(gt.nodeList[node.position]);
                System.out.println("*********************");
            }
        }
    }

    private static ArrayList getEdges(Graph g) {
        ArrayList edges = new ArrayList();
        for (int i = 0; i < g.nodeList.length; i++)
            if (g.nodeList[i] != null) {
                SimpleNode next = g.nodeList[i].next;
                while (next != null) {
                    edges.add(new Edge(next.weight, g.nodeList[i], g.nodeList[next.position]));
                    next = next.next;
                }
            }
        return edges;
    }

    /**
     * 按无向图考虑
     *
     * @param g
     * @return
     */
    private static Map getEdgesMap(Graph g) {
        ArrayList edges = getEdges(g);
        Map map = new HashMap();
        for (Edge edge : edges) {
            map.put(edge.from.position + "|" + edge.to.position, edge.weight);
            map.put(edge.to.position + "|" + edge.from.position, edge.weight);//有向图许注释掉此行
        }
        return map;
    }

    protected static int find(int[] parent, int f) {
        while (parent[f] != 0)
            f = parent[f];
        return f;
    }

    public static void kruskal(Graph g) {
        ArrayList edges = getEdges(g);
        edges.sort(new Comparator() {
            @Override
            public int compare(Edge o1, Edge o2) {
                return o1.weight - o2.weight;
            }
        });
        int[] parents = new int[g.nodeList.length];
        for (Edge edge : edges) {
            int beginParent = find(parents, edge.from.position);
            int endParent = find(parents, edge.to.position);
            if (beginParent != endParent) {
                parents[beginParent] = endParent;
                System.out.println("from:" + edge.from.position + ",to:" + edge.to.position + ",weight =" + edge.weight);
            }
        }
    }

    public static void prim(Graph g, int index) {
        PriorityBlockingQueue queue = new PriorityBlockingQueue(1000, new Comparator() {
            @Override
            public int compare(ListGraphNode o1, ListGraphNode o2) {
                return o1.d - o2.d;
            }
        });

        for (int i = 0; i < g.nodeList.length; i++) {
            if (g.nodeList[i] != null) {
                g.nodeList[i].pre = null;
                g.nodeList[i].d = Integer.MAX_VALUE;
                queue.offer(g.nodeList[i]);
            }
        }
        g.nodeList[index].d = 0;
        Map edgeMap = getEdgesMap(g);
        while (!queue.isEmpty()) {
            ListGraphNode node = queue.poll();
            for (ListGraphNode nd : queue) {
                Integer w = edgeMap.get(node.position + "|" + nd.position);
                w = w == null ? Integer.MAX_VALUE : w;
                if (nd.d > w) {
                    queue.remove(nd);
                    nd.d = w;
                    nd.pre = node;
                    queue.offer(nd);
                }
            }
        }
    }

    public static void relax(ListGraphNode from, ListGraphNode to, Map map) {
        if (from.d != Integer.MAX_VALUE && to.d > from.d + map.get(to.position + "|" + from.position)) {
            to.d = from.d + map.get(to.position + "|" + from.position);
            to.pre = from;
        }
    }

    public static void initSinggeSource(Graph g, int index) {
        for (ListGraphNode nd : g.nodeList) {
            if (nd != null) {
                nd.d = Integer.MAX_VALUE;
                nd.pre = null;
            }
        }
        g.nodeList[index].d = 0;
        g.nodeList[index].pre = g.nodeList[index];
    }

    public static boolean bellmanFord(Graph g) {
        ArrayList edges = getEdges(g);
        Map map = getEdgesMap(g);
        initSinggeSource(g, 0);
        for (int i = 1; i < g.nodeList.length; i++)
            for (Edge edge : edges)
                relax(edge.from, edge.to, map);
        for (Edge edge : edges)
            if (edge.to.d > edge.from.d + edge.weight)
                return false;
        return true;
    }

    public static void floyd(SimpleEdge[][] edges, int n) {
        for (int k = 0; k < n; k++)
            for (int i = 0; i < n; i++)
                for (int j = 0; j < n; j++) {
                    if (edges[i][k].weight != Integer.MAX_VALUE && edges[k][j].weight != Integer.MAX_VALUE) {
                        int sum = edges[i][k].weight + edges[k][j].weight;
                        if (edges[i][j].weight > sum) {
                            edges[i][j].weight = sum;
                            edges[i][j].pre = k;
                        }
                    }
                }
    }

    private static String makeSinglePath(SimpleEdge[][] edges, int from, int to, String s) {
        if (from == edges[from][to].pre) {
            if (s.length() != 0)   // 此处涉及到cpu执行指令的一个知识,就是判断语句永远把最有可能出现的情况放在if后边而不是else后边,
                s = s + "->" + to; // 因为放在else后边涉及到指令跳转,会降低效率
            else
                s = s + from + "->" + to;
            return s;
        }
        return makeSinglePath(edges, edges[from][to].pre, to, makeSinglePath(edges, from, edges[from][to].pre, s));
    }

    public static void printPath(SimpleEdge[][] edges, int n) {
        for (int i = 0; i < n; i++)
            for (int j = 0; j < n; j++)
                if (edges[i][j].pre != -1)
                    System.out.println(i + "到" + j + "路径是:\n" + makeSinglePath(edges, i, j, ""));
    }

    public static void dijkstra(Graph g, int index) {
        Map map = getEdgesMap(g);
        initSinggeSource(g, index);
        PriorityQueue queue = new PriorityQueue(new Comparator() {
            @Override
            public int compare(ListGraphNode o1, ListGraphNode o2) {
                return o1.d - o2.d;
            }
        });
        for (ListGraphNode node : g.nodeList)
            if (node != null)
                queue.add(node);
        while (queue.size() != 0) {
            ListGraphNode node = queue.poll();
            List tempList = new ArrayList();
            for (ListGraphNode node1 : queue) {
                Integer w = map.get(node.position + "|" + node1.position);
                if (w != null && node.d != Integer.MAX_VALUE && (node.d + w) < node1.d) {
                    node1.d = node.d + w;
                    node1.pre = node;
                    tempList.add(node1);
                }
            }
            tempList.forEach((ListGraphNode nd) -> {
                queue.remove(nd);
                queue.add(nd);
            });
        }
    }

    public static void printDijstraPath(Graph g,int index){
        for(int i = 0; i < g.nodeList.length;i++){
            ListGraphNode node = g.nodeList[i];
            if(node != null && node.position != index){
                printDsinglePath(g,index,i);
                System.out.println();
            }
        }
    }

    private static void printDsinglePath(Graph g, int index, int i) {
        if(i != index){
            printDsinglePath(g, index, g.nodeList[i].pre.position);
            System.out.print("->" + i);
        }else
            System.out.print(i);

    }
}


你可能感兴趣的:(学习与实践)