图的基本操作

来源:互联网 发布:模考软件pp2 编辑:程序博客网 时间:2024/05/21 15:43
import java.util.ArrayList;import java.util.Arrays;import java.util.Collections;import java.util.LinkedList;import java.util.List;import java.util.Queue;import java.util.Stack;//邻接矩阵class Graph{    char[] vertexs;    int[][] edges;    int vertexnum;    int edgenum;}class SortedEdge implements Comparable<SortedEdge>{    int m;    int n;    int weight;    @Override    public int compareTo(SortedEdge o) {        if(this.weight < o.weight)            return -1;        else if(this.weight > o.weight)            return 1;        else            return 0;    }}class UndirectedGraph{    public Graph createGraph(){        Graph graph = new Graph();        int vertexnum = 5;        int edgenum = 8;        //顶点数 边数        graph.vertexnum = vertexnum;        graph.edgenum = edgenum;        char[] vertexs = new char[vertexnum];        int[][] edges = new int[vertexnum][vertexnum];        for(int i = 0; i < vertexnum; i++)            for(int j = 0; j < vertexnum; j++)                edges[i][j] = 0;        //顶点        for(int i = 0; i < vertexnum; i++)            vertexs[i] = (char) (i + 'A');        graph.vertexs = vertexs;        //边        edges[0][1] = 3; edges[0][2] = 5; edges[0][3] = 8;        edges[1][0] = 3; edges[1][2] = 6; edges[1][3] = 4; edges[1][4] = 11;        edges[2][0] = 5; edges[2][1] = 6; edges[2][3] = 2;        edges[3][0] = 8; edges[3][1] = 4; edges[3][2] = 2; edges[3][4] = 10;        edges[4][1] = 11; edges[4][3] = 10;        graph.edges = edges;        return graph;    }    public void printGraph(Graph graph){        for(int i = 0; i < graph.vertexnum; i++){            System.out.print(graph.vertexs[i] + " ");        }        System.out.println();        for(int i = 0; i < graph.vertexnum; i++){            for(int j = 0; j < graph.vertexnum; j++)                System.out.print(graph.edges[i][j] + " ");            System.out.println();        }    }    public void DFS(Graph graph, int v, int[] visited){        visited[v] = 1;        System.out.print(graph.vertexs[v] + " ");        for(int j = 0; j < graph.vertexnum; j++) {            if (graph.edges[v][j] != 0 && visited[v] == 0) {                DFS(graph, v, visited);            }        }    }    public void deepFirstSearch(Graph graph){        int[] visited = new int[graph.vertexnum];        Arrays.fill(visited, 0);        for(int i = 0; i < graph.vertexnum; i++)            if(visited[i] == 0)                DFS(graph, i, visited);    }    public void BFS(Graph graph, int v, int[] visited){        visited[v] = 1;        Queue<Integer> queue = new LinkedList<Integer>();        queue.add(v);        while(!queue.isEmpty()){            int node = queue.poll();            System.out.print(graph.vertexs[node] + " ");            for(int j = 0; j < graph.vertexnum; j++) {                if (graph.edges[node][j] != 0 && visited[j] == 0) {                    queue.add(j);                    visited[j] = 1;                }            }        }    }    public void breadthFirstSearch(Graph graph){        int[] visited = new int[graph.vertexnum];        Arrays.fill(visited, 0);        for(int i = 0; i < graph.vertexnum; i++)            if(visited[i] == 0)                BFS(graph, i, visited);    }    public void sortGraphEdgesByWeights(Graph graph, ArrayList<SortedEdge> sortedEdges){        Collections.sort(sortedEdges);    }    //求单源最短路径 初始化有向图邻接矩阵    public Graph initDirectedGraph(){        Graph graph = new Graph();        int vertexnum = 6;        int edgenum = 11;        //顶点数 边数        graph.vertexnum = vertexnum;        graph.edgenum = edgenum;        char[] vertexs = new char[vertexnum];        int[][] edges = new int[vertexnum][vertexnum];        for(int i = 0; i < vertexnum; i++)            for(int j = 0; j < vertexnum; j++)                if(i == j)                    edges[i][j] = 0;                else                    edges[i][j] = 9999;        //顶点        for(int i = 0; i < vertexnum; i++)            vertexs[i] = (char) (i + 'A');        graph.vertexs = vertexs;        //边        edges[0][1] = 50; edges[0][2] = 10; edges[0][4] = 45;        edges[1][2] = 15; edges[1][4] = 10;        edges[2][0] = 20; edges[2][3] = 15;        edges[3][1] = 20; edges[3][4] = 35;        edges[4][3] = 30;        edges[5][3] = 3;        graph.edges = edges;        return graph;    }    //单源最短路径    public void dijkstraShortestPath(Graph graph, int v){        int[] distance = new int[graph.vertexnum];        int[] found = new int[graph.vertexnum];        int[] path = new int[graph.vertexnum + 1];        path[0] = -1;        for(int i = 0; i < graph.vertexnum; i++){            found[i] = 0;            distance[i] = graph.edges[v][i];            if(i != 0 && i != v && distance[i] != 9999)                path[i] = v;            else                path[i] = -1;        }        found[v] = 1;        distance[v] = 0;        for(int i = 0; i < graph.vertexnum - 2; i++){            int u = chooseLowestCostEdge(graph, distance, found);            found[u] = 1;            for(int w = 0; w < graph.vertexnum; w++)                if(found[w] == 0)                    if(distance[u] + graph.edges[u][w] < distance[w]){                        distance[w] = distance[u] + graph.edges[u][w];                        path[w] = u;                    }        }        printShortestPaths(graph, v, path, distance);    }    public void printShortestPaths(Graph graph, int v, int[] path, int[] distance){        System.out.println("最短路径信息:");        for(int i = 1; i < graph.vertexnum; i++){            System.out.println(v + " 到  " + i +" 的 最短路径为 :");            int k = i;            Stack<Integer> stack = new Stack<Integer>();            if(path[i] != -1)                stack.add(i);            while(path[k] != -1){                stack.add(path[k]);                k = path[k];            }            if(stack.isEmpty())                System.out.print("没有从 " + v +" 到  " + i + "的路径!");            while(!stack.isEmpty()){                if(stack.size() > 1)                    System.out.print(stack.pop() + "->");                else                    System.out.print(stack.pop());            }            System.out.print("\t最小代价 :" + distance[i]);            System.out.println();        }    }    public int chooseLowestCostEdge(Graph graph, int[] distance, int[] found){        int min, minpos;        min = Integer.MAX_VALUE;        minpos = -1;        for(int i = 0; i < graph.vertexnum; i++){            if(distance[i] < min && found[i] == 0){                min = distance[i];                minpos = i;            }        }        return minpos;    }    //所有顶点对之间的最短路径    public void floydWarshallShortestPath(Graph graph){        int i, j , k;        int n = graph.vertexnum;        int[][] distance = new int[n][n];        int[][] paths = new int[n][n];        for(i = 0; i < n; i++)            for(j = 0; j < n; j++){                distance[i][j] = graph.edges[i][j];                if(distance[i][j] < 9999)                    paths[i][j] = i;                else                    paths[i][j] = -1;            }        //最短路径算法        for(k = 0; k < n; k++)            for(i = 0; i < n; i++)                for(j = 0; j < n; j++)                    if(distance[i][k] + distance[k][j] < distance[i][j]){                        //  System.out.println("distance["+i+"]["+k+"] = " + distance[i][k]+" , distance["+k+"]["+j+"] ="+ distance[k][j]+" ,  distance["+i+"]["+j+"] = " + distance[i][j]);                        //  System.out.println("distance["+i+"]["+k+"] + distance["+k+"]["+j+"] < distance["+i+"]["+j+"]");                        distance[i][j] = distance[i][k] + distance[k][j];                        //  System.out.println("distance["+i+"]["+j+"] = " + distance[i][j]);                        paths[i][j] = paths[k][j];                    }        printAllShortestPathsWithWeight(graph, distance, paths);    }    public void printAllShortestPathsWithWeight(Graph graph, int[][] distance, int[][] paths){        Stack<Integer> stack = new Stack<Integer>();        int n = graph.vertexnum;        for(int i = 0; i < n; i++)            for(int j = 0; j < n; j++)                if(i != j && distance[i][j] < 9999){                    stack.add(j);                    int v = paths[i][j];                    while(v != i && v != j){                        stack.add(v);                        v = paths[i][v];                    }                    System.out.print(i + " -> ");                    while(!stack.isEmpty()){                        if(stack.size() > 1)                            System.out.print(stack.pop() + " -> ");                        else                            System.out.print(stack.pop());                    }                    System.out.println("  长度为  :" + distance[i][j]);                }else if(i != j && distance[i][j] == 9999){                    System.out.println("没有从 " + i +" 到  " + j + "的路径!");                }    }    //最小代价生成树 Kruskal 算法 和Prim 算法    public Graph initUndirectedGraph(){        Graph graph = new Graph();        int vertexnum = 7;        int edgenum = 9;        //顶点数 边数        graph.vertexnum = vertexnum;        graph.edgenum = edgenum;        char[] vertexs = new char[vertexnum];        int[][] edges = new int[vertexnum][vertexnum];        int n = vertexnum;        for(int i = 0; i < vertexnum; i++)            for(int j = 0; j < vertexnum; j++)                if(i == j)                    edges[i][j] = 0;                else                    edges[i][j] = 9999;        //顶点        for(int i = 0; i < vertexnum; i++)            vertexs[i] = (char) (i + 'A');        graph.vertexs = vertexs;        //边        edges[0][1] = 28; edges[0][5] = 10;        edges[1][2] = 16; edges[1][6] = 14;        edges[2][3] = 12;        edges[3][4] = 22; edges[3][6] = 18;        edges[4][6] = 24; edges[4][5] = 25;        edges[1][0] = 28; edges[5][0] = 10;        edges[2][1] = 16; edges[6][1] = 14;        edges[3][2] = 12;        edges[4][3] = 22; edges[6][3] = 18;        edges[6][4] = 24; edges[5][4] = 25;        graph.edges = edges;        return graph;    }    //kuskal最小生成树算法    public void kruskalMinimunCostSpanningTree(Graph graph){        int n = graph.vertexnum;        int lowestCost = 0;        List<SortedEdge> selectedEdges = new ArrayList<SortedEdge>();        List<SortedEdge> edges = new ArrayList<SortedEdge>();        int[] father = new int[n];        for(int p = 0; p < n; p++)            father[p] = p;        //无向图只选取上三角形的边        for(int i = 0; i < n; i++)            for(int j = i + 1; j < n; j++)                if(i != j){                    SortedEdge edge = new SortedEdge();                    edge.m = i;                    edge.n = j;                    edge.weight = graph.edges[i][j];                    edges.add(edge);                }        Collections.sort(edges);        while(selectedEdges.size() < n - 1 && !edges.isEmpty()){            SortedEdge minEdge = edges.get(0);            edges.remove(0);            int k, g;            /*for(k = minEdge.m; k != x[k]; k = x[k]);            for(g = minEdge.n; g != x[g]; g = x[g]);*/            k = find_set(minEdge.m, father);            g = find_set(minEdge.n, father);            //边的两个端点位于不同集合,构不成环,选中该边            if(k != g){                father[g] = k;                selectedEdges.add(minEdge);                lowestCost += minEdge.weight;            }        }        if(selectedEdges.size() < n - 1){            System.out.println("改图没有最小代价生成树 !");            return;        }        //选中的边以及最小代价        System.out.println("Kruskal最小代价生成树-选中的边以及权值为:");        for(SortedEdge se : selectedEdges)            System.out.println(se.m + " - " + se.n + " - " + se.weight);        System.out.println("最小代价为 :" + lowestCost);    }    public int find_set(int x,int[] father){        if(x != father[x])            father[x] = find_set(father[x], father);        return father[x];    }    //Prim最小生成树算法    public void primMinimunCostSpanningTree(Graph graph){        int n = graph.vertexnum;        int lowestCost = 0;        List<SortedEdge> selectedEdges = new ArrayList<SortedEdge>();        List<SortedEdge> edges = new ArrayList<SortedEdge>();        int[] father = new int[n];        for(int p = 0; p < n; p++)            father[p] = p;        //无向图只选取上三角形的边        for(int i = 0; i < n; i++)            for(int j = i + 1; j < n; j++)                if(i != j){                    SortedEdge edge = new SortedEdge();                    edge.m = i;                    edge.n = j;                    edge.weight = graph.edges[i][j];                    edges.add(edge);                }        Collections.sort(edges);        int k, g;        //先把第一条边加进去        SortedEdge minEdge0 = edges.get(0);        edges.remove(0);        father[minEdge0.n] = minEdge0.m;        selectedEdges.add(minEdge0);        int baseSet = minEdge0.m;        int i = 0;        while(selectedEdges.size() < n - 1 && !edges.isEmpty()){            SortedEdge minEdge = edges.get(i);            k = find_set(minEdge.m, father);            g = find_set(minEdge.n, father);            if((k == baseSet && g != baseSet) || (g == baseSet && k != baseSet)){                edges.remove(i);                selectedEdges.add(minEdge);                lowestCost += minEdge.weight;                if(k == baseSet)                    father[g] = k;                else                    father[k] = g;                i = 0;            }else                i++;        }        System.out.println("selectedEdges size:" + selectedEdges.size());        if(selectedEdges.size() < n - 1){            System.out.println("改图没有最小代价生成树 !");            return;        }        //选中的边以及最小代价        System.out.println("Prim最小代价生成树-选中的边以及权值为:");        for(SortedEdge se : selectedEdges)            System.out.println(se.m + " - " + se.n + " - " + se.weight);        System.out.println("最小代价为 :" + lowestCost);    }}//邻接表class EdgeNode{    int adjvertex;    EdgeNode next;}class VertexNode{    char data;    EdgeNode firstEdge;}class DGraph{    VertexNode[] adjList;    int vertexnum;    int edgenum;}class DirectedDGraph{    public int getposition(char[] vexs, char c){        return String.valueOf(vexs).indexOf(c);    }    public void printVertexEdgeNode(DGraph graph){        for(int i = 0; i < graph.vertexnum; i++){            System.out.println(graph.adjList[i].data + "顶点的所有连接点如下:");            for(EdgeNode p = graph.adjList[i].firstEdge; p != null; p = p.next)                System.out.print(p.adjvertex + " ");            System.out.println();        }    }    public DGraph createGraph(){        DGraph graph = new DGraph();        char vexs[] = {'A', 'B', 'C', 'D', 'E', 'F', 'G'};        char edges[][] = {{'A', 'B'}, {'B', 'C'}, {'B', 'E'}, {'B', 'F'}, {'C', 'E'}, {'D', 'C'}, {'E', 'B'}, {'E', 'D'},{'F', 'G'}};        graph.vertexnum = vexs.length;        graph.edgenum = edges.length;        graph.adjList = new VertexNode[graph.vertexnum];        //初始化邻接表的顶点        for(int i = 0; i < vexs.length; i++){            graph.adjList[i] = new VertexNode();            graph.adjList[i].data = vexs[i];            graph.adjList[i].firstEdge = null;        }        //初始化邻接表的边        for(int i = 0; i < edges.length; i++){            EdgeNode edgeNode = new EdgeNode();            int pos1 = getposition(vexs, edges[i][0]);            int pos2 = getposition(vexs, edges[i][1]);            edgeNode.adjvertex = pos2;            edgeNode.next = graph.adjList[pos1].firstEdge;            graph.adjList[pos1].firstEdge = edgeNode;        }        return graph;    }    public void DFS(DGraph graph, int v, int[] visited){        visited[v] = 1;        //  System.out.print(v + " ");        System.out.print(graph.adjList[v].data + " ");        for(EdgeNode edge = graph.adjList[v].firstEdge; edge != null; edge = edge.next)            if(visited[edge.adjvertex] == 0)                DFS(graph, edge.adjvertex, visited);    }    public void deepFirstSearch(DGraph graph){        int[] visited = new int[graph.vertexnum];        Arrays.fill(visited, 0);        for(int i = 0; i < graph.vertexnum; i++)            if(visited[i] == 0)                DFS(graph, i, visited);    }    public void BFS(DGraph graph, int v, int[] visited){        visited[v] = 1;        Queue<Integer> queue = new LinkedList<Integer>();        queue.add(v);        while(!queue.isEmpty()){            int node = queue.poll();            System.out.print(graph.adjList[node].data + " ");            for(EdgeNode edge = graph.adjList[node].firstEdge; edge != null; edge = edge.next)                if(visited[edge.adjvertex] == 0){                    queue.add(edge.adjvertex);                    visited[edge.adjvertex] = 1;                }        }    }    public void breadthFirstSearch(DGraph graph){        int[] visited = new int[graph.vertexnum];        Arrays.fill(visited, 0);        for(int i = 0; i < graph.vertexnum; i++)            if(visited[i] == 0)                BFS(graph, i, visited);    }}public class Tu {    public static void main(String[] args) {        //邻接矩阵        UndirectedGraph ugraph1 = new UndirectedGraph();        Graph graph1 = ugraph1.createGraph();        System.out.println("Graph DFS:");        ugraph1.deepFirstSearch(graph1);        System.out.println("\nGraph BFS:");        ugraph1.breadthFirstSearch(graph1);        //  graph1.printGraph(graph1.createGraph());        //邻接表        DirectedDGraph dgraph = new DirectedDGraph();        //  dgraph.printVertexEdgeNode(dgraph.createGraph());        DGraph graph = dgraph.createGraph();        System.out.println("\nDGraph DFS:");        dgraph.deepFirstSearch(graph);        System.out.println("\nDGraph BFS:");        dgraph.breadthFirstSearch(graph);        //有向图        //单源最短路径        System.out.println("\n单源最短路径 : ");        Graph dgraph3 = ugraph1.initDirectedGraph();        ugraph1.dijkstraShortestPath(dgraph3, 0);        //任意两点最短路径        System.out.println("\n所有顶点之间的最短路径 及其长度信息: ");        ugraph1.floydWarshallShortestPath(dgraph3);        //最小代价生成树        Graph graph4 = ugraph1.initUndirectedGraph();        System.out.println("\n kruskal最小代价生成树:");        ugraph1.kruskalMinimunCostSpanningTree(graph4);        System.out.println("\n prim最小代价生成树:");        ugraph1.primMinimunCostSpanningTree(graph4);    }}
0 0
原创粉丝点击