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

简介:

代码:

复制代码
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
复制代码

 

 顶点示意图:
















本文转自张昺华-sky博客园博客,原文链接:http://www.cnblogs.com/xiandedanteng/p/3885477.html,如需转载请自行联系原作者


相关文章
|
2月前
|
存储 定位技术
【天梯赛】L2-048 寻宝图 (DFS做法)
遇到一个非'0'字符(也就是'1'和 宝藏'2'到'9')就让ans++,同时将这个非'0'字符染色为'0',然后往四个方向(上、下、左、右)搜索,这里的目的是那一片岛屿(也就是那一片为'1'的部分)都染色为‘0’。本题就请你统计一下,给定的地图上一共有多少岛屿,其中有多少是有宝藏的岛屿。为了判断有宝藏的岛屿,这里我开了一个全局变量f来判断这一片岛屿是否有宝藏(也就是有无字符'2'-'9'),当搜到字符'2'~'9'时就将f标记为1。在一行中输出 2 个整数,分别是岛屿的总数量和有宝藏的岛屿的数量。
40 5
|
4月前
|
算法
2024春晚纸牌魔术原理----环形链表的约瑟夫问题
2024春晚纸牌魔术原理----环形链表的约瑟夫问题
树的储存形势&代码实现(跑路人笔记1)
树的储存形势&代码实现(跑路人笔记)
树的储存形势&代码实现(跑路人笔记1)
|
机器学习/深度学习 存储 算法
【苏州程序大白用2万字】解析数据结构和八大排序算法☀️《❤️记得收藏❤️》
【苏州程序大白用2万字】解析数据结构和八大排序算法☀️《❤️记得收藏❤️》
110 0
【苏州程序大白用2万字】解析数据结构和八大排序算法☀️《❤️记得收藏❤️》