爪哇国新游记之二十五----图及其遍历查找

代码:

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Queue;
import java.util.Set;


// 顶点类
class Vertex{
    String name;// 名称
    boolean visited;// 是否已访问过
    
    public Vertex(String name){
        this.name=name;
        this.visited=false;
    }
}

// 图类
public class Graph{
    //
    private Vertex[] arr;// 顶点数组
    private int[][] matrix;// 邻接矩阵
    
    // 建立图的数据
    private Set<String> vertexSet;// 包含不重复顶点的集合
    private Map<String,String[]> connMap;// 包含连接的哈希表
    
    // 添加顶点之间的连接关系
    public void addConn(String from,String[] toArr){
        if(vertexSet==null){
            vertexSet=new HashSet<String>();
        }
        
        vertexSet.add(from);
        for(String to:toArr){
            vertexSet.add(to);
        }
        
        if(connMap==null){
            connMap=new LinkedHashMap<String,String[]>();
        }
        
        connMap.put(from, toArr);
    }
    
    // 建立图(即其中的顶点数组和邻接矩阵)
    public void rebuildGraph(){
        // 初始化顶点数组
        List<String> ls=new ArrayList<String>();
        ls.addAll(vertexSet);
        Collections.sort(ls);
        
        int size=ls.size();
        arr=new Vertex[size];
        for(int i=0;i<ls.size();i++){
            arr[i]=new Vertex(ls.get(i));
        }
        
        // 初始化邻接矩阵
        matrix=new int[size][size];
        for(String key:connMap.keySet()){
            String[] values=connMap.get(key);
            
            for(String value:values){
                int x=findVertexIndex(key);
                int y=findVertexIndex(value);
                
                if(x!=-1 && y!=-1){
                    matrix[x][y]=1;
                    matrix[y][x]=1;
                }
            }
        }
    }
    
    // 在顶点数组里找顶点下标
    private int findVertexIndex(String name){
        for(int i=0;i<arr.length;i++){
            if(name.equals(arr[i].name)){
                return i;
            }
        }
        
        return -1;
    }
    
    public void displayMatix(){
        int n=arr.length;
        
        System.out.print("  ");
        for(int i=0;i<n;i++){
            System.out.print(arr[i].name+",");
        }
        System.out.println();
        
        System.out.print("-");
        for(int i=0;i<n;i++){
            System.out.print("--");
        }
        System.out.println();
        
        for(int i=0;i<n;i++){
            System.out.print(arr[i].name+":");
            
            for(int j=0;j<n;j++){
                System.out.print(matrix[i][j]+",");
            }
            
            System.out.println();
        }
    }
    
    // 得到两个点之间的路径(深度优先搜索)
    public String getPath(String from,String to){
        resetArr();
        
        // 初始化
        int fromIndex=findVertexIndex(from);
        if(fromIndex==-1){
            return "找不到顶点:"+from;
        }
        
        int toIndex=findVertexIndex(to);
        if(toIndex==-1){
            return "找不到顶点:"+to;
        }
        
        //  用于记住路径的栈
        Stack<Integer> stack=new Stack<Integer>(Integer.class,arr.length);
        
        // 开始寻找
        arr[fromIndex].visited=true;
        stack.push(fromIndex);
        
        while(stack.isEmpty()==false){
            int j=getConnVertex(stack.peek());
            
            if(j==-1){
                stack.pop();
            }else{
                arr[j].visited=true;
                stack.push(j);
            
                if(arr[j].name.equals(to)){
                    // 找到了
                    
                    StringBuilder sb=new StringBuilder();
                    
                    while(stack.isEmpty()==false){
                        int index=stack.pop();
                        
                        sb.insert(0, arr[index].name+"->");
                    }
                    
                    return sb.substring(0, sb.length()-2);
                }
            }
        }
        
        return "不可能从"+from+"到"+to;
    }
    
    // 广度优先搜索
    public String getPath2(String from,String to){
        resetArr();
        
        // 初始化
        int fromIndex=findVertexIndex(from);
        if(fromIndex==-1){
            return "找不到顶点:"+from;
        }
        
        int toIndex=findVertexIndex(to);
        if(toIndex==-1){
            return "找不到顶点:"+to;
        }
        
        // 用于记住路径的队列
        Queue<Integer> queue=new LinkedList<Integer>();
        
        // 开始寻找
        StringBuilder sb=new StringBuilder();
        arr[fromIndex].visited=true;
        queue.add(fromIndex);
        sb.append(arr[fromIndex].name+"->");
        int j;
        
        while(queue.isEmpty()==false){
            int i=queue.remove();
            
            while((j=getConnVertex(i))!=-1){
                arr[j].visited=true;
                sb.append(arr[j].name+"->");
                queue.add(j);
                
                if(arr[j].name.equals(to)){
                    // 找到了
                    
                    return sb.substring(0, sb.length()-2);
                }
            }
        }
        
        return "不可能从"+from+"到"+to;
    }
    
    /**
     * 重置顶点访问情况
     */
    private void resetArr(){
        int n=arr.length;
        
        for(int j=0;j<n;j++){
            arr[j].visited=false;
        }
    }
    
    // 取得连接未访问过的顶点
    private int getConnVertex(int i){
        int n=arr.length;
        
        for(int j=0;j<n;j++){
            if(matrix[i][j]==1 && arr[j].visited==false){
                return j;
            }
        }
        
        return -1;
    }
    
    public static void main(String[] args){
        Graph g=new Graph();
        
        g.addConn("A", new String[]{"B","D"});
        g.addConn("B", new String[]{"A","C"});
        g.addConn("C", new String[]{"B","D","E"});
        g.addConn("D", new String[]{"A","C"});
        g.addConn("E", new String[]{"C"});
        g.addConn("F", new String[]{"E","G"});
        g.addConn("G", new String[]{"F"});
        g.addConn("H", new String[]{"I","J"});
        g.addConn("I", new String[]{"H","J"});
        g.addConn("J", new String[]{"H","I"});
        
        g.rebuildGraph();
        g.displayMatix();
        
        String path=g.getPath("A", "G");
        System.out.println(path);
        
        path=g.getPath("A", "H");
        System.out.println(path);
        
        path=g.getPath("J", "H");
        System.out.println(path);
        
        path=g.getPath("F", "B");
        System.out.println(path);
        
        path=g.getPath2("A", "G");
        System.out.println(path);
        
        path=g.getPath2("F", "B");
        System.out.println(path);
    }
}

 

输出:

  A,B,C,D,E,F,G,H,I,J,
---------------------
A:0,1,0,1,0,0,0,0,0,0,
B:1,0,1,0,0,0,0,0,0,0,
C:0,1,0,1,1,0,0,0,0,0,
D:1,0,1,0,0,0,0,0,0,0,
E:0,0,1,0,0,1,0,0,0,0,
F:0,0,0,0,1,0,1,0,0,0,
G:0,0,0,0,0,1,0,0,0,0,
H:0,0,0,0,0,0,0,0,1,1,
I:0,0,0,0,0,0,0,1,0,1,
J:0,0,0,0,0,0,0,1,1,0,
A->B->C->E->F->G
不可能从A到H
J->H
F->E->C->B
A->B->D->C->E->F->G
F->E->G->C->B

 

 顶点示意图:

posted @ 2014-08-01 17:23  逆火狂飙  阅读(173)  评论(0编辑  收藏  举报
生当作人杰 死亦为鬼雄 至今思项羽 不肯过江东