图的基本操作


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);
    }

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值