数据结构之图
各算法的思想在之前的文章中有详解,下述只是用Java重新编程了一遍,对用到的算法不理解的,可以参考下面的文章
数据结构之图论算法(邻接矩阵)
Java代码实现:
class Graph {
private int[][] Matrix;
private String[] Vert;
private int vertnum;
private int edgenum;
private final static Integer INF = Integer.MAX_VALUE;
public Graph() {
}
public int[] Locate(String s1, String s2) {
int m = 0;
int n = 0;
for (int i = 0; i < vertnum; ++i) {
if (s1.equals(Vert[i]))
m = i;
if (s2.equals(Vert[i]))
n = i;
}
int[] arr = new int[2];
arr[0] = m;
arr[1] = n;
return arr;
}
public void createGraph() {
Scanner input = new Scanner(System.in);
System.out.print("请输入顶点数:");
vertnum = input.nextInt();
Matrix = new int[vertnum][vertnum];
Vert = new String[vertnum];
for (int i = 0; i < vertnum; ++i) {
for (int j = 0; j < vertnum; ++j)
Matrix[i][j] = INF;
Matrix[i][i] = 0;
input = new Scanner(System.in);
System.out.print("请输入第" + (i + 1) + "个顶点信息:");
Vert[i] = input.nextLine();
}
System.out.print("请输入边数:");
edgenum = input.nextInt();
String s1 = null;
String s2 = null;
int distance = 0;
for (int i = 0; i < edgenum; ++i) {
System.out.print("请输入起点:");
input = new Scanner(System.in);
s1 = input.nextLine();
System.out.print("请输入终点:");
input = new Scanner(System.in);
s2 = input.nextLine();
System.out.print("请输入距离:");
distance = input.nextInt();
int[] arr = Locate(s1, s2);
Matrix[arr[0]][arr[1]] = distance;
//Matrix[arr[1]][arr[0]]=distance;
}
}
public void Print() {
System.out.print(String.format("%-5s", " "));
for (int i = 0; i < vertnum; ++i)
System.out.print(String.format("%-5s", Vert[i]));
System.out.println();
for (int i = 0; i < vertnum; ++i) {
System.out.print(String.format("%-5s", Vert[i]));
for (int j = 0; j < vertnum; ++j) {
if (Matrix[i][j] == INF)
System.out.print(String.format("%-5s", "oo"));
else
System.out.print(String.format("%-5d", Matrix[i][j]));
}
System.out.println();
}
}
public void TologySort() {
int[] In = new int[vertnum];
for (int i = 0; i < vertnum; ++i)
In[i] = 0;
for (int i = 0; i < vertnum; ++i) {
for (int j = 0; j < vertnum; ++j) {
if (Matrix[i][j] != INF && Matrix[i][j] != 0)
++In[j];
}
}
Queue<Integer> queue = new LinkedList<>();
for (int i = 0; i < vertnum; ++i) {
if (In[i] == 0)
queue.offer(i);
}
while (!queue.isEmpty()) {
int top = queue.peek();
queue.poll();
System.out.print(Vert[top] + " ");
for (int i = 0; i < vertnum; ++i) {
if (Matrix[top][i] != 0 && Matrix[top][i] != INF) {
--In[i];
if (In[i] == 0)
queue.offer(i);
}
}
}
System.out.println();
}
public void printPath(int[] parent, int root) {
if (parent[root] == -1) {
System.out.print(Vert[root] + " ");
return;
}
printPath(parent, parent[root]);
System.out.print(Vert[root] + " ");
}
public void NoWeight() {
int[] visit = new int[vertnum];
int[] parent = new int[vertnum];
int[] dist = new int[vertnum];
for (int i = 0; i < vertnum; ++i) {
visit[i] = 0;
parent[i] = -1;
dist[i] = INF;
}
System.out.println("请输入起点:");
Scanner input = new Scanner(System.in);
String start = input.nextLine();
Queue<Integer> queue = new LinkedList<>();
for (int i = 0; i < vertnum; ++i) {
if (Vert[i].equals(start)) {
visit[i] = 0;
dist[i] = 0;
queue.offer(i);
break;
}
}
while (!queue.isEmpty()) {
int top = queue.peek();
queue.poll();
for (int i = 0; i < vertnum; ++i) {
if (Matrix[top][i] != 0 && Matrix[top][i] != INF) {
if (visit[i] == 0) {
visit[i] = 1;
dist[i] = dist[top] + 1;
parent[i] = top;
queue.offer(i);
}
}
}
}
System.out.println(String.format("%-5s %-5s %-5s", "value", "dist", "path"));
for (int i = 0; i < vertnum; ++i) {
System.out.print(String.format("%-5s", Vert[i]) + " ");
System.out.print(String.format("%-5d", dist[i]) + " ");
printPath(parent, i);
System.out.println();
}
}
public void Dijkstra() {
int[] dist = new int[vertnum];
int[] parent = new int[vertnum];
int[] visit = new int[vertnum];
for (int i = 0; i < vertnum; ++i) {
parent[i] = -1;
dist[i] = INF;
visit[i] = 0;
}
System.out.print("请输入起点:");
Scanner input = new Scanner(System.in);
String start = input.nextLine();
int top = 0;
int current = 0;
for (int i = 0; i < vertnum; ++i) {
if (Vert[i].equals(start)) {
dist[i] = 0;
top = i;
visit[i] = 1;
++current;
break;
}
}
while (current < vertnum) {
for (int i = 0; i < vertnum; ++i) {
if (Matrix[top][i] != INF && Matrix[top][i] != 0) {
if (Matrix[top][i] + dist[top] < dist[i]) {
dist[i] = dist[top] + Matrix[top][i];
parent[i] = top;
}
}
}
int minz = INF;
int nextpos = -1;
for (int i = 0; i < vertnum; ++i) {
if (visit[i] == 0 && dist[i] < minz) {
minz = dist[i];
nextpos = i;
}
}
visit[nextpos] = 1;
top = nextpos;
++current;
}
System.out.println(String.format("%-5s %-5s %-5s", "value", "dist", "path"));
for (int i = 0; i < vertnum; ++i) {
System.out.print(String.format("%-5s", Vert[i]) + " ");
System.out.print(String.format("%-5d", dist[i]) + " ");
printPath(parent, i);
System.out.println();
}
}
public void Floyd() {
int[][] capacity = new int[vertnum][vertnum];
for (int i = 0; i < vertnum; ++i) {
for (int j = 0; j < vertnum; ++j)
capacity[i][j] = Matrix[i][j];
}
for (int k = 0; k < vertnum; ++k) {
for (int i = 0; i < vertnum; ++i) {
for (int j = 0; j < vertnum; ++j) {
if (capacity[i][k] != INF && capacity[k][j] != INF) {
if (capacity[i][k] + capacity[k][j] < capacity[i][j]) {
capacity[i][j] = capacity[i][k] + capacity[k][j];
}
}
}
}
}
System.out.print(String.format("%-5s", " "));
for (int i = 0; i < vertnum; ++i)
System.out.print(String.format("%-5s", Vert[i]));
System.out.println();
for (int i = 0; i < vertnum; ++i) {
System.out.print(String.format("%-5s", Vert[i]));
for (int j = 0; j < vertnum; ++j) {
if (capacity[i][j] == INF)
System.out.print(String.format("%-5s", "oo"));
else
System.out.print(String.format("%-5d", capacity[i][j]));
}
System.out.println();
}
}
public void Bellman_Ford(){
int[]dist=new int[vertnum];
int[]parent=new int[vertnum];
for(int i=0;i<vertnum;++i)
{
dist[i]=INF;
parent[i]=-1;
}
System.out.print("请输入起点:");
Scanner input=new Scanner(System.in);
String start=input.nextLine();
for(int i=0;i<vertnum;++i)
{
if(Vert[i].equals(start))
{
dist[i]=0;
break;
}
}
for(int k=0;k<vertnum;++k)
{
for(int i=0;i<vertnum;++i)
{
for(int j=0;j<vertnum;++j)
{
if(dist[i]!=INF&&Matrix[i][j]!=INF&&dist[i]+Matrix[i][j]<dist[j]){
dist[j]=dist[i]+Matrix[i][j];
parent[j]=i;
}
}
}
}
boolean flag=false;
for(int i=0;i<vertnum;++i)
{
for(int j=0;j<vertnum;++j)
{
if(dist[i]!=INF&&Matrix[i][j]!=INF&&dist[i]+Matrix[i][j]<dist[j]){
flag=true;
break;
}
}
if(flag)
break;
}
if(flag)
{
System.out.println("存在负环路");
}
else
{
System.out.println(String.format("%-5s %-5s %-5s", "value", "dist", "path"));
for (int i = 0; i < vertnum; ++i) {
System.out.print(String.format("%-5s", Vert[i]) + " ");
System.out.print(String.format("%-5d", dist[i]) + " ");
printPath(parent, i);
System.out.println();
}
}
}
public void SPFA(){
int[]dist=new int[vertnum];
int[]parent=new int[vertnum];
int[]count=new int[vertnum];
for(int i=0;i<vertnum;++i)
{
dist[i]=INF;
parent[i]=-1;
count[i]=0;
}
Queue<Integer>queue=new LinkedList<>();
System.out.print("请输入起点:");
Scanner input=new Scanner(System.in);
String start=input.nextLine();
for(int i=0;i<vertnum;++i)
{
if(Vert[i].equals(start)){
dist[i]=0;
queue.offer(i);
count[i]=1;
break;
}
}
boolean flag=false;
while(!queue.isEmpty()){
int top=queue.peek();
queue.poll();
for(int i=0;i<vertnum;++i)
{
if(dist[top]!=INF&&Matrix[top][i]!=INF&&dist[top]+Matrix[top][i]<dist[i]){
dist[i]=dist[top]+Matrix[top][i];
parent[i]=top;
count[i]++;
if(count[i]==vertnum)
{
flag=true;
break;
}
queue.offer(i);
}
}
if(flag)
break;
}
if(flag)
{
System.out.println("存在负环路");
}
else
{
System.out.println(String.format("%-5s %-5s %-5s", "value", "dist", "path"));
for (int i = 0; i < vertnum; ++i) {
System.out.print(String.format("%-5s", Vert[i]) + " ");
System.out.print(String.format("%-5d", dist[i]) + " ");
printPath(parent, i);
System.out.println();
}
}
}
public void Prim(){
int[]dist=new int[vertnum];
int[]parent=new int[vertnum];
for(int i=0;i<vertnum;++i)
{
dist[i]=INF;
parent[i]=-1;
}
int ans=0;
System.out.print("请输入起点:");
Scanner input=new Scanner(System.in);
String start=input.nextLine();
int top=0;
int count=0;
for(int i=0;i<vertnum;++i)
{
if(Vert[i].equals(start)){
top=i;
dist[i]=-1;
count=1;
break;
}
}
while(count<vertnum)
{
for(int i=0;i<vertnum;++i)
{
if(dist[i]!=-1&&Matrix[top][i]!=0&&Matrix[top][i]<dist[i]){
dist[i]=Matrix[top][i];
parent[i]=top;
}
}
int minz=INF;
int nextpos=0;
for(int i=0;i<vertnum;++i)
{
if(dist[i]!=-1&&dist[i]<minz)
{
minz=dist[i];
nextpos=i;
}
}
++count;
System.out.println(Vert[parent[nextpos]]+"--"+Vert[nextpos]+":"+minz);
ans+=minz;
top=nextpos;
dist[top]=-1;
}
System.out.println(ans);
}
public int Find(int[]parent,int root)
{
if(parent[root]==-1)
return root;
return Find(parent,parent[root]);
}
public boolean Union(int[]parent,int root1,int root2){
root1=Find(parent,root1);
root2=Find(parent,root2);
if(root1==root2)
return false;
parent[root1]=root2;
return true;
}
private class node
{
private int from;
private int to;
private int distance;
public node(int from,int to,int distance){
this.from=from;
this.to=to;
this.distance=distance;
}
}
private Comparator<node>distComparator=new Comparator<node>(){
@Override
public int compare(node o1,node o2){
return (o1.distance-o2.distance);
}
};
public void Kruskal(){
Queue<node>priorityqueue=new PriorityQueue<>(distComparator);
for(int i=0;i<vertnum;++i)
{
for(int j=0;j<vertnum;++j)
{
if(Matrix[i][j]!=0&&Matrix[i][j]!=INF)
{
node nn=new node(i,j,Matrix[i][j]);
priorityqueue.add(nn);
}
}
}
int count=0;
int[]visit=new int[vertnum];
int[]parent=new int[vertnum];
for(int i=0;i<vertnum;++i)
{
visit[i]=0;
parent[i]=-1;
}
int ans=0;
while(count<vertnum)
{
node temp=priorityqueue.peek();
priorityqueue.poll();
if(Union(parent,temp.from,temp.to))
{
ans+=temp.distance;
if(visit[temp.from]==0)
{
visit[temp.from]=1;
++count;
}
if(visit[temp.to]==0)
{
visit[temp.to]=1;
++count;
}
System.out.println(Vert[temp.from]+"--"+Vert[temp.to]+":"+temp.distance);
}
}
System.out.println(ans);
}
public void DFS(){
System.out.print("请输入起点:");
Scanner input=new Scanner(System.in);
String start=input.nextLine();
int[]visit=new int[vertnum];
for(int i=0;i<vertnum;++i)
visit[i]=0;
Stack<Integer>stack=new Stack<>();
for(int i=0;i<vertnum;++i)
{
if(Vert[i].equals(start))
{
stack.add(i);
visit[i]=1;
System.out.print(Vert[i]+" ");
break;
}
}
while(!stack.isEmpty()){
int top=stack.peek();
for(int i=0;i<vertnum;++i)
{
if(visit[i]==0&&Matrix[top][i]!=0&&Matrix[top][i]!=INF)
{
visit[i]=1;
stack.add(i);
System.out.print(Vert[i]+" ");
break;
}
}
if(top==stack.peek())
stack.pop();
}
System.out.println();
}
public void dfs(int[]visit,int top){
for(int i=0;i<vertnum;++i)
{
if(visit[i]==0&&Matrix[top][i]!=0&&Matrix[top][i]!=INF)
{
visit[i]=1;
System.out.print(Vert[i]+" ");
dfs(visit,i);
}
}
}
public void DFS1()
{
System.out.print("请输入起点:");
Scanner input=new Scanner(System.in);
String start=input.nextLine();
int[]visit=new int[vertnum];
for(int i=0;i<vertnum;++i)
visit[i]=0;
for(int i=0;i<vertnum;++i)
{
if(Vert[i].equals(start))
{
visit[i]=1;
System.out.print(Vert[i]+" ");
dfs(visit,i);
break;
}
}
for(int i=0;i<vertnum;++i)
{
if(visit[i]==0)
{
visit[i]=1;
System.out.print(Vert[i]+" ");
dfs(visit,i);
}
}
}
public int bfs(int[][]capacity,int[]pre,int[]flow,int start,int end){
for(int i=0;i<vertnum;++i)
{
pre[i]=-1;
flow[i]=INF;
}
pre[start]=start;
Queue<Integer>queue=new LinkedList<>();
queue.offer(start);
while(!queue.isEmpty()){
int top=queue.peek();
queue.poll();
if(top==end)
break;
for(int i=0;i<vertnum;++i)
{
if(pre[i]==-1&&capacity[top][i]!=INF&&capacity[top][i]!=0)
{
flow[i]=Math.min(flow[top],capacity[top][i]);
pre[i]=top;
queue.offer(i);
}
}
}
if(pre[end]==-1)
return -1;
return flow[end];
}
public void EK(){
System.out.print("请输入起点和终点:");
Scanner input=new Scanner(System.in);
String start=input.nextLine();
input=new Scanner(System.in);
String end=input.nextLine();
int[][]capacity=new int[vertnum][vertnum];
int[]flow=new int[vertnum];
int[]pre=new int[vertnum];
for(int i=0;i<vertnum;++i)
{
flow[i]=INF;
pre[i]=-1;
for(int j=0;j<vertnum;++j){
capacity[i][j]=Matrix[i][j];
}
}
int ans=0;
int[]arr=Locate(start,end);
while(true)
{
int offset=bfs(capacity,pre,flow,arr[0],arr[1]);
if(offset==-1)
break;
ans+=offset;
int j=arr[1];
while(j!=arr[0])
{
int k=pre[j];
capacity[k][j]-=offset;
capacity[j][k]+=offset;
j=k;
}
}
System.out.println(ans);
}
public boolean bfs(int[][]capacity,int[]dist,int start,int end)
{
for(int i=0;i<vertnum;++i)
dist[i]=-1;
dist[start]=0;
Queue<Integer>queue=new LinkedList<>();
queue.offer(start);
while(!queue.isEmpty()){
int top=queue.peek();
queue.poll();
for(int i=0;i<vertnum;++i)
{
if(dist[i]==-1&&capacity[top][i]!=0&&capacity[top][i]!=INF){
dist[i]=dist[top]+1;
queue.offer(i);
}
}
}
if(dist[end]!=-1)
return true;
return false;
}
public int dfs(int[][]capacity,int[]dist,int now,int end,int value){
if(now==end)
return value;
int minz=INF;
for(int i=0;i<vertnum;++i)
{
if(dist[i]==dist[now]+1&&capacity[now][i]!=INF&capacity[now][i]!=0)
{
if((minz=dfs(capacity,dist,i,end,Math.min(value,capacity[now][i])))!=0)
{
capacity[now][i]-=minz;
capacity[i][now]+=minz;
return minz;
}
}
}
return 0;
}
public void Dinic(){
System.out.print("请输入起点和终点:");
Scanner input=new Scanner(System.in);
String start=input.nextLine();
String end=input.nextLine();
int[][]capacity=new int[vertnum][vertnum];
int[]dist=new int[vertnum];
for(int i=0;i<vertnum;++i)
{
dist[i]=-1;
for(int j=0;j<vertnum;++j)
{
capacity[i][j]=Matrix[i][j];
}
}
int[]arr=Locate(start,end);
int ans=0;
while(bfs(capacity,dist,arr[0],arr[1])){
ans+=dfs(capacity,dist,arr[0],arr[1],INF);
}
System.out.println(ans);
}
public void SAP(){
int[][]capacity=new int[vertnum][vertnum];
int[]gap=new int[vertnum];
int[]flow=new int[vertnum];
int[]pre=new int[vertnum];
int[]dist=new int[vertnum];
for(int i=0;i<vertnum;++i)
{
gap[i]=0;
pre[i]=-1;
dist[i]=-1;
flow[i]=INF;
for(int j=0;j<vertnum;++j){
capacity[i][j]=Matrix[i][j];
}
}
Scanner input=new Scanner(System.in);
String start=input.nextLine();
input=new Scanner(System.in);
String end=input.nextLine();
int[]arr=Locate(start,end);
dist[arr[1]]=0;
gap[0]=1;
Queue<Integer>queue=new LinkedList<>();
queue.offer(arr[1]);
while(!queue.isEmpty()){
int top=queue.peek();
queue.poll();
for(int i=0;i<vertnum;++i)
{
if(dist[i]==-1&&capacity[i][top]!=0&&capacity[i][top]!=INF)
{
dist[i]=dist[top]+1;
gap[dist[i]]++;
queue.offer(i);
}
}
}
if(dist[arr[0]]==-1)
return;
int ans=0;
int top=arr[0];
int i,j;
while(dist[arr[0]]<vertnum){
boolean flag=false;
flow[arr[0]]=INF;
for(i=0;i<vertnum;++i)
{
if(dist[top]==dist[i]+1&&dist[i]>=0&&capacity[top][i]!=0
&&capacity[top][i]!=INF)
{
flag=true;
break;
}
}
if(flag)
{
flow[i]=Math.min(flow[top],capacity[top][i]);
pre[i]=top;
top=i;
if(top==arr[1])
{
ans+=flow[arr[1]];
int k=arr[1];
while(k!=arr[0])
{
capacity[pre[k]][k]-=flow[arr[1]];
capacity[k][pre[k]]+=flow[arr[1]];
k=pre[k];
}
top=arr[0];
for(j=0;j<vertnum;++j)
flow[j]=INF;
}
}
else
{
int minz=INF;
for(j=0;j<vertnum;++j)
{
if(dist[j]+1<minz&&dist[j]>=0&&
capacity[top][j]!=0&&capacity[top][j]!=INF)
minz=dist[j]+1;
}
gap[dist[top]]--;
if(gap[dist[top]]==0)
break;
dist[top]=minz;
gap[minz]++;
if(top!=arr[0])
top=pre[top];
}
}
System.out.println(ans);
}
}
public class test{
public static void main(String[]args)throws Exception {
Graph graph=new Graph();
graph.createGraph();
graph.Print();
//graph.TologySort();
//graph.NoWeight();
//graph.Dijkstra();
//graph.Floyd();
//graph.Bellman_Ford();
//graph.SPFA();
//graph.Prim();
//graph.Kruskal();
//graph.DFS();
//graph.DFS1();
//graph.EK();
//graph.Dinic();
//graph.SAP();
}
}