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);
}
}
图的基本操作
最新推荐文章于 2024-03-08 17:47:21 发布