BFS
类似于树的层次遍历,用队列依次存储节点的孩子节点然后做出队操作。
唯一不同的是树不存在环,但图存在环,所以遍历图的时候需要设置一个访问矩阵,来记录一个节点是否已经被遍历过。
public static void BFS(int [][] graph, int sx){
int dim = graph.length;
boolean [] visited = new boolean [dim];
LinkedList<Integer> queue = new LinkedList<Integer>();
for(int i = 0; i < dim; ++i)
visited[i] = false;
queue.add(sx);
while(!queue.isEmpty()){
int node = queue.remove(0);
if(!visited[node])System.out.print(node + 1 + " ");
visited[node] = true;
for(int i = 0; i < dim; ++i){
if(graph[node][i] == 1 && !visited[i])
queue.add(i);
}
}
}
测试数据:邻接矩阵
int [][] graph ={{0,1,0,0,0,0,0,0},
{1,0,1,1,0,0,0,0},
{0,1,0,0,1,1,0,0},
{0,1,0,0,1,0,1,0},
{0,0,1,1,0,0,0,1},
{0,0,1,0,0,0,1,0},
{0,0,0,1,0,1,0,0},
{0,0,0,0,1,0,0,0}};
求以节点1为起点的遍历结果:1 2 3 4 5 6 7 8
DFS
类似于二叉树的前序遍历,一直递归到某一节点立即进行遍历,然后选一个孩子继续递归。
DFS的遍历结果不是唯一的。同样需要一个记录矩阵。
public static void DFS(int [][] graph, int sx){
int dim = graph.length;
boolean [] visited = new boolean [dim];
for(int i = 0; i < dim; ++i)
visited[i] = false;
System.out.print(sx + 1 + " ");
visited[sx] = true;
for(int i = 0; i < dim; ++i){
if(!visited[i] && graph[sx][i] == 1){
DFSnode(graph, i, visited);
}
}
}
public static void DFSnode(int [][] graph, int node, boolean [] visited){
int dim = graph.length;
System.out.print(node + 1 + " ");
visited[node] = true;
for(int i = 0; i < dim; ++i){
if(!visited[i] && graph[node][i] == 1){
DFSnode(graph, i, visited);
}
}
}
迪杰斯特拉算法
痛心疾首,华为FX计划有一道编程题考点就是dijstra思想,但是忘记了,着重复习一下:
1首先取一个起点,设置一个数组dist,记录起点到各个节点的距离,无法到达的设置为maxint。
2然后选一个dist里面的最小值,把这个节点标记为已选(加入已选节点集合),然后重新计算dist:
3如果其他节点的dist能因为加入此次的已选节点变小,则更新dist(以此次已选节点为辅助节点,曲线救国)
4再次从dist数组里挑选最小值,回到第二步。
public static void dijstra(int [][] gweight, int start, int end){
int dim = gweight.length;
int [] father = new int [dim];
int [] dist = new int [dim];
HashSet<Integer> hash = new HashSet<Integer>();
int maxint = Integer.MAX_VALUE;
for(int i = 0; i < dim; ++i)
dist[i] = maxint;
int pickVer = start;
int min = 0;
hash.add(pickVer);
while(pickVer != end){
for(int i = 0; i < dim; ++i){
if(gweight[pickVer][i] + min < dist[i] &&
gweight[pickVer][i] != 0 &&
!hash.contains(i)){
dist[i] = gweight[pickVer][i] + min;
father[i] = pickVer;
}
}
int temp = maxint; int minindex = 0;
for(int i = 0; i < dim; ++i){
if(dist[i] < temp && !hash.contains(i)){
temp = dist[i];
minindex = i;
}
}
min = temp;
pickVer = minindex;
hash.add(pickVer);
}
System.out.println("由节点 " + (start + 1) + " 至节点 " + (end + 1) + " 的最短路径长:"+dist[end]);
System.out.print("节点路径为:" + (end + 1));
for(int i = end; i != start;){
System.out.print("<-" + (father[i] + 1));
i = father[i];
}
}
int [][] weight ={{0,3,0,0,0,0,0,0},
{3,0,4,7,0,0,0,0},
{0,4,0,0,6,1,0,0},
{0,7,0,0,1,0,5,0},
{0,0,6,1,0,0,0,2},
{0,0,1,0,0,0,8,0},
{0,0,0,5,0,8,0,0},
{0,0,0,0,2,0,0,0}};
结果:由节点 1 至节点 7 的最短路径长:15
节点路径为:7<-4<-2<-1
代码中father数组记录了每个节点的上一个节点,用来记录最短路经过的节点路径。