我想知道在'图表'中最好的方法是什么,对象确实引用了他们的邻居,但我也有一个概述(坐标上有对象的哈希图),以确定其中两个对象是连接。
我读到Dijkstra可能效率不高,我读了BFS和DFS。
根据我的理解,BFS可能接近我需要的,我可以做得更好吗?有没有更常见的解决方法?也许更容易?时间复杂度确实发挥了作用:)
答案 0 :(得分:0)
在java中检查此代码,当您获得邻接矩阵时,您会看到节点是否已连接:
import java.util.*;
public class myListGraph
{
protected String[] names; // 1-d array to store the vertices
protected StringLinkList[] Edges; // 1-d array to store adjacencies between vertices,
protected int numVertices;
protected int numEdges;
// Default constructor. Sets aside enough capacity for one vertex
public myListGraph( )
{
this(1);
}
// Constructor that sets aside as much capacity as specified by the user
public myListGraph(int capacity)
{
names = new String[capacity];
Edges = new StringLinkList[capacity];
for (int i = 0 ; i < capacity ; i ++) {
Edges[i] = new StringLinkList();
}
}
public int numberOfVertices()
{
return numVertices;
}
public int numberOfEdges()
{
return numEdges;
}
// Finds the location at which a vertex is stored in Vertices.
// Returns -1 if vertex not found
public int getIndex(String vertex)
{
for(int i = 0; i < numVertices; i++)
if(vertex.equals(names[i]))
return i;
return -1;
}
// Resizes the array of vertices. Can make it larger or smaller, depending
// on what newSize is.
protected String[] resize(String[] array, int newSize)
{
String[] temp = new String[newSize];
int smallerSize = newSize;
if(array.length < smallerSize)
smallerSize = array.length;
for(int i = 0; i < smallerSize; i++)
temp[i] = array[i];
return temp;
}
// Resizes the array of Edges. Can make it larger or smaller, depending
// on what newSize is.
protected StringLinkList[] resize (StringLinkList[] array, int newSize)
{
StringLinkList[] temp = new StringLinkList[newSize];
int smallerSize = newSize;
if(array.length < smallerSize)
smallerSize = array.length;
for(int i = 0; i < smallerSize; i++)
temp[i] = array[i];
for (int i = smallerSize ; i < temp.length ; i ++)
temp [i] = new StringLinkList();
return temp;
}
// Adds a new vertex
public void addVertex(String newVertex)
{
if(getIndex(newVertex) != -1)
{
System.out.print("addVertex: ");
System.out.print(newVertex);
System.out.println(" failed -- vertex already exists.");
return;
}
// if array of vertices is full, we need to expand it and
// also expand Edges
if (names.length == numVertices)
{
names = resize(names, 2*numVertices+1);
Edges = resize(Edges, 2*numVertices+1);
}
names[numVertices++] = newVertex;
}
// Adds a new edge
public void addEdge(String vertex1, String vertex2)
{
int i = getIndex(vertex1);
if(i == -1)
{
System.out.print("addEdge failed: ");
System.out.print(vertex1);
System.out.println(" does not exist.");
return;
}
int j = getIndex(vertex2);
if(j == -1)
{
System.out.print("addEdge failed: ");
System.out.print(vertex2);
System.out.println(" does not exist.");
return;
}
Edges[i].insertFirst(names[j]);
Edges[j].insertFirst(names[i]);
numEdges++;
}
// Prints the neighbors of the given vertex
public void printAdjacencyList (String vertex)
{
int i = getIndex(vertex);
if(i == -1)
{
System.out.print("addEdge failed: ");
System.out.print(vertex);
System.out.println(" does not exist.");
return;
}
System.out.print (vertex + " is connected to ");
Edges [i].displayList();
}
// returns the names of all the neighbors of a given vertex in a
// String array
public String[] getNeighbors(String vertex)
{
int source = getIndex(vertex);
if(source == -1)
{
System.out.print("getNeighbors failed: Vertex ");
System.out.print(vertex);
System.out.println(" does not exist.");
return null;
}
return Edges[source].copyIntoArray();
}
// returns the indices of all the neighbors of a given vertex. The
// vertex is specified as an index and the neighbors are returned
// in an int array
public int[] getNeighbors(int index)
{
if((index < 0) || (index >= numVertices))
{
System.out.print("getNeighbors failed: Index");
System.out.print(index);
System.out.println(" is out of bounds.");
return null;
}
// Call the earlier getNeighbors function to get the names of
// neighbors
String[] nbrNames = getNeighbors(names[index]);
// Turn the array of neighbor names into an array
// of neighbor indices
int[] nbrIndices = new int[nbrNames.length];
for(int i = 0; i < nbrIndices.length; i++)
nbrIndices[i] = getIndex(nbrNames[i]);
return nbrIndices;
}
// returns the degree of a vertex with given name
public int degree(String vertex)
{
// Get the index of the vertex
int i = getIndex(vertex);
if(i == -1)
{
System.out.print("In degree: ");
System.out.print(vertex);
System.out.println(" does not exist.");
return -1;
}
// Call the other degree function that returns the degree
// of a vertex, given its index
return degree(i);
}
// returns the degree of a vertex with given index
public int degree(int index)
{
return Edges[index].size();
}
// Boolean method that tells us if {v1, v2} is an edge in the graph
public boolean isEdge(String vertex1, String vertex2)
{
int i = getIndex(vertex1);
if(i == -1)
{
System.out.print("isEdge failed: ");
System.out.print(vertex1);
System.out.println(" does not exist.");
return false;
}
int j = getIndex(vertex2);
if(j == -1)
{
System.out.print("isEdge failed: ");
System.out.print(vertex2);
System.out.println(" does not exist.");
return false;
}
// if vertex2 exists in the adjacency list of
// vertex1, then return true
return (Edges[i].find(vertex2) != null);
}
// Computes the clustering coefficient of a vertex. This is the
// version that takes a vertex index as argument.
public double clusteringCoefficient(int i)
{
// Copy the adjacency list into an array, for easy access
// copyIntoArray is a new method in the GenericLinkList class
String[] temp = Edges[i].copyIntoArray();
// initialize edges-in-neighborhood to 0
int edgesInNbd = 0;
// Scan pairs of neighbors and increment counter whenever
// there is an edge
for(int j = 0; j < temp.length; j++)
for(int k = 0; k < j; k++)
if(isEdge(temp[j], temp[k]))
edgesInNbd++;
// if there are no neighbors or one neighbor then, clustering
// coefficient is trivially defined to be 1. Otherwise,
// compute the ratio of number of edges in neighborhood to
// the total number of pairs of neighbors
if(temp.length <= 1)
return 1;
else
return edgesInNbd*2.0/(temp.length*(temp.length-1));
}
// Computes the clustering coefficient of a vertex. This is the
// version that takes a vertex name as argument.
public double clusteringCoefficient(String v)
{
int i = getIndex(v);
if(i == -1)
{
System.out.print("clusteringCoefficient failed: ");
System.out.print(v);
System.out.println(" does not exist.");
return 0;
}
return clusteringCoefficient(i);
}
// Computes the clustering coefficient of the entire graph
// added on 2/23
public double clusteringCoefficient()
{
double sum = 0;
for(int i = 0; i < numVertices; i++)
sum = sum + clusteringCoefficient(i);
return sum/numVertices;
}
// Checks whether the graph is connected or not by calling breadthFirstSearch
public boolean isConnected()
{
// Perform breadth first search
int[] bfsTree = breadthFirstSearch(names[0]);
// Scan the bfsTree array, looking for -1. The graph
// is not connected if there is -1 in this array
for(int i = 0; i < bfsTree.length; i++)
if(bfsTree[i] == -1)
return false;
return true;
}
// Returns a 2-d array of vertex names representing the connected components
// of the graph. Each row in the 2-d array is a connected component.
public String[][] connectedComponents()
{
// The maximum number of connected components equals the number
// of vertices; so start by allocating this many rows.
String[][] cc = new String[numVertices][];
// Keeps track of which vertices have been visited by repeated
// calls to bfs
boolean[] visited = new boolean[numVertices];
for(int i = 0; i < numVertices; i++)
visited[i] = false;
// Keeps track of the number of vertices have been visited by repeated
// calls to bfs
int numVisited = 0;
// Keeps track of the number of connected components
int numComponents = 0;
// Repeat bfs until all vertices have been visited
while(numVisited < numVertices)
{
// Scan visited until an unvisited vertex is found
// and start bfs at that source
int source;
for(source = 0; source < numVisited; source++)
if(!visited[source])
break;
// Compute the bfsTree starting at this source
int[] bfsTree = breadthFirstSearch(names[source]);
// Scan bfsTree to count number of newly visited vertices
int countNewVisited = 0;
for(int i = 0; i < numVertices; i++)
if(bfsTree[i] != -1)
countNewVisited++;
// Allocate a row of size countNewVisited in the current row of
// cc to store the new connected component
cc[numComponents] = new String[countNewVisited];
// Scan bfsTree again, this time to copy the newly visited
// vertices into cc and set them as visited
countNewVisited = 0;
for(int i = 0; i < numVertices; i++)
if(bfsTree[i] != -1)
{
cc[numComponents][countNewVisited++] = names[i];
visited[i] = true;
}
// Update numVisited
numVisited = numVisited + countNewVisited;
// Update numComponents
numComponents++;
} // end while
// Resize cc to have exactly as mamy rows as numComponents
String[][] newCC = new String[numComponents][];
for(int i = 0; i < numComponents; i++)
newCC[i] = cc[i];
return newCC;
}
// Computes a shortest path (in hops) from source to destination. Does
// this by simply calling breadthFirstSearch and following the parent
// pointers in the BFS tree. If the source and destination are not in
// the same component, returns null. Otherwise, returns a String array
// of vertices in a shortest path
public String[] shortestPath(String source, String dest)
{
// Get index of source
int sourceIndex = getIndex(source);
if(sourceIndex == -1)
{
System.out.print("breadthFirstSearch failed: ");
System.out.print(source);
System.out.println(" does not exist.");
return null;
}
// Get index of destination
int destIndex = getIndex(dest);
if(destIndex == -1)
{
System.out.print("breadthFirstSearch failed: ");
System.out.print(dest);
System.out.println(" does not exist.");
return null;
}
// Perform a BFS from destination
int[] bfsTree = breadthFirstSearch(destIndex);
// If source is unreachable from destination
if(bfsTree[sourceIndex] == -1)
return null;
// Define a String[] for shortest path and place the source vertex
// in it
String[] path = new String[numVertices];
path[0] = names[sourceIndex];
// Start following parent pointers and store each new vertex
// encountered, in the path array. The while-loop executes
// until the root of the BFS tree is encountered
int currentIndex = sourceIndex;
int pathLength = 0;
while(currentIndex != bfsTree[currentIndex])
{
currentIndex = bfsTree[currentIndex];
pathLength++;
path[pathLength] = names[currentIndex];
}
// Resize the path array to be exactly of the correct size
String[] newPath = new String[pathLength + 1];
for(int i = 0; i < newPath.length; i++)
newPath[i] = path[i];
return newPath;
}
// Breadth first search function that takes a vertex name as argument;
// returns a breadth first search tree
// stored in an array of integers with the entry in slot i containing
// the index of the parent of the vertex with index i
// parent of source is itself; unvisited nodes have parent -1
public int[] breadthFirstSearch(String source)
{
int sourceIndex = getIndex(source);
if(sourceIndex == -1)
{
System.out.print("breadthFirstSearch failed: ");
System.out.print(source);
System.out.println(" does not exist.");
return null;
}
return breadthFirstSearch(sourceIndex);
}
// Breadth first search function that takes a vertex index as argument;
// returns a breadth first search tree
// stored in an array of integers with the entry in slot i containing
// the index of the parent of the vertex with index i
// parent of source is itself; unvisited nodes have parent -1
public int[] breadthFirstSearch(int sourceIndex)
{
// Initialize the bfsTree array; the entry -1 means
// not yet visited.
int[] bfsTree = new int[numVertices];
for(int i = 0; i < numVertices; i++)
bfsTree[i] = -1;
// The parent of the tree root is itself
bfsTree[sourceIndex] = sourceIndex;
// Then initialize the visited array
boolean[] visited = new boolean[numVertices];
for(int i = 0; i < numVertices; i++)
visited[i] = false;
visited[sourceIndex] = true;
// Then initialize the queue
Queue Q = new Queue(numVertices);
Q.enqueue(sourceIndex);
while(!Q.isEmpty())
{
// get the index of the vertex first in line
int current = Q.dequeue();
// Get the indices of the neighbors of the current vertex
int[] neighbors = getNeighbors(current);
// Scan the neighbors
for(int i = 0; i < neighbors.length; i++)
{
// Get the index of the current neighbor
int currentNeighbor = neighbors[i];
// Check if the neighbor is new, i.e., not visited
// If so, mark the neighbor as visited, enqueue the neighbor, and
// set the neighbor's parent in bfsTree
if(!visited[currentNeighbor])
{
visited[currentNeighbor] = true;
Q.enqueue(currentNeighbor);
bfsTree[currentNeighbor] = current;
}
} // end-scanning neighbors
} // end-while Q is not empty
return bfsTree;
}
} // end of class