1. 程式人生 > >Dijkstra演算法以及java實現_02(程式碼部分)

Dijkstra演算法以及java實現_02(程式碼部分)

1.資料庫表的設計:
這裡寫圖片描述

dijsname1和dijsname2是有向圖中的兩個點。
qinmid是這兩個點之間的親密度,將親密度的值作為邊的權值大小。

2.對資料庫中資料進行增刪改查操作:

//這裡主要實現了insert(插入)操作和查詢操作(通過兩個點查詢親密度)
package com.graduat.dao.impl;
public class DijstraImpl implements DijstTestDao {

    private static final String INSERT = "insert into dijsttest(dijsname1,dijsname2,qinmid) values(?,?,?)"
; private static final String FINDBYDN = "select qinmid from dijsttest where dijsname1=? and dijsname2=? "; @Override public void insert(DijstTest dijstTest) throws Exception { PreparedStatement prep = null; Connection conn = null; try { conn = DBConnection.getConnection(); prep = conn.prepareStatement(INSERT, Statement.RETURN_GENERATED_KEYS); prep.setString(1
, dijstTest.getDijsname1()); prep.setString(2, dijstTest.getDijsname2()); prep.setInt(3, dijstTest.getQinmid()); prep.executeUpdate(); ResultSet rst = prep.getGeneratedKeys(); rst.next(); int id = rst.getInt(1); dijstTest.setId(id); } finally
{ DBConnection.close(prep, conn); } } @Override public DijstTest findByDn(String Dname1, String Dname2) throws Exception { // TODO Auto-generated method stub PreparedStatement prep = null; Connection conn = null; DijstTest dijstTest = null; ResultSet rst = null; try { conn = DBConnection.getConnection(); prep = conn.prepareStatement(FINDBYDN); prep.setString(1, Dname1); prep.setString(2,Dname2); rst = prep.executeQuery(); if(rst.next()) { dijstTest = new DijstTest(); dijstTest.setQinmid(rst.getInt("qinmid")); } } finally { DBConnection.close(prep, conn); } return dijstTest; } }

3.定義節點資訊:

public class Node {
//定義節點的name屬性和child孩子屬性,並且實現其get和set方法。
    private String name;
    private Map<Node,Integer> child = new HashMap<Node, Integer>();
    public Node(String name) {
        this.name = name;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public Map<Node,Integer> getChild() {
        return child;
    }
    public void setChild(Map<Node,Integer> child) {
        this.child = child;
    }


4.初始化所有節點:


public class MapBuilder {
    String nodetestdemo = null;
    DijstTestDao dijks = DijstraFactory.getDijistra();
    DijstTest d;
    public Node build(Set<Node> open, Set<Node> close, List<Node> lists) throws Exception {
        Node n1;
        for (int i = 0; i < lists.size(); i++) {
            n1 = lists.get(i);
            for (int j = 0; j < lists.size(); j++) {
                if (n1 != lists.get(j)) {
//通過兩個節點資訊在資料庫中查詢親密度權值。
                    d = dijks.findByDn(lists.get(i).getName(), lists.get(j).getName());
                    if(d != null)
                        n1.getChild().put(lists.get(j), d.getQinmid());
                }
            }
        }
        // 遍歷node型別的陣列
        // 現在求每個點到其他點的最短距離之和已經實現,要迴圈抽象求和的最小值,輸出最小中心結點和最短距離。
        Node nn = null;
        //close陣列用來儲存源節點資訊
        //open陣列用來儲存除了源節點之外的所有節點資訊
        for (int i = 0; i < lists.size(); i++) {
            if( nodetestdemo.equals(lists.get(i).getName()) ) {
                nn = lists.get(i);
                close.add(lists.get());
            }
            else
                open.add(lists.get(i));
        }

        return nn;
    }
}

5.核心演算法:


public class Dijkstra {
    ArrayList<String> list = new ArrayList<String>();
    Set<Node> open = new HashSet<Node>();
    Set<Node> close = new HashSet<Node>();
    Map<String, Integer> path = new HashMap<String, Integer>();// 封裝路徑距離
    Map<String, String> pathInfo = new HashMap<String, String>();// 封裝路徑資訊

    String testpppp = null;
    ArrayList<String> listlist = new ArrayList<String>();
    ArrayList<Integer> listlist1 = new ArrayList<Integer>();
//通過輸入兩個節點的名字,去資料庫中查詢親密度權值大小
//可直接到達則直接返回,否則返回最大值
    public int finddistance(String num1, String num2) throws Exception {
        DijstTestDao dijks = DijstraFactory.getDijistra();
        DijstTest d = dijks.findByDn(num1, num2);
        if (d != null) {
            return d.getQinmid();
        } else {
            return Integer.MAX_VALUE;
        }
    }

    public Node init(List<Node> nodes) throws Exception {
        // 初始路徑,因沒有A->E這條路徑,所以path(E)設定為Integer.MAX_VALUE
        //list.size()是初始輸入節點的個數
        String[] t = new String[list.size()];
        for (int i = 0; i < list.size(); i++) {
            t[i] = list.get(i);
        }
        for (int i = 0; i < t.length; i++) {
            if (t[i] == testpppp) {
                continue;
            } else {
            //將兩節點的路徑資訊和路徑長度分別儲存在path和pathInfo中。
                path.put(t[i], finddistance(testpppp, t[i]));
                pathInfo.put(t[i], testpppp + "->" + t[i]);
            }
        }
        // 將初始節點放入close,其他節點放入open
        MapBuilder mapBuilder = new MapBuilder();
        mapBuilder.nodetestdemo = testpppp;
        Node start = mapBuilder.build(open, close, nodes);
        return start;
    }

    public void computePath(Node start) {
        Node nearest = getShortestPath(start);// 取距離start節點最近的子節點,放入close
        if (nearest == null) {
            return;
        }
        close.add(nearest);
        open.remove(nearest);
        Map<Node, Integer> childs = nearest.getChild();
        for (Node child : childs.keySet()) {
            if (open.contains(child)) {// 如果子節點在open中
                Integer newCompute = path.get(nearest.getName())
                        + childs.get(child);
                if (path.get(child.getName()) > newCompute) {// 之前設定的距離大於新計算出來的距離
                    path.put(child.getName(), newCompute);
                    pathInfo.put(
                            child.getName(),
                            pathInfo.get(nearest.getName()) + "->"
                                    + child.getName());
                }
            }
        }
        computePath(start);// 重複執行自己,確保所有子節點被遍歷
        computePath(nearest);// 向外一層層遞迴,直至所有頂點被遍歷
    }

    @SuppressWarnings({ "static-access", "rawtypes" })
    public void printPathInfo(ArrayList<String> bigList,ArrayList<Integer> bigList1) {
        Set<Map.Entry<String, String>> pathInfos = pathInfo.entrySet();


        Collection<Integer> values = path.values();
        int sum = 0;
        int sum_end = 0;
        for (Map.Entry<String, String> pathInfo : pathInfos) {
                   listlist.add(testpppp+"->"+pathInfo.getKey());
               bigList.add(testpppp+"->"+pathInfo.getKey());
        }
        for (Integer object : values) {
            sum = Integer.parseInt(object.toString());
            sum_end = sum_end + sum;
                listlist1.add(sum); 
            bigList1.add(sum);
        }
        System.out.println("和為sumend=" + sum_end);
        System.out.println(testpppp);
        Main main = new Main();
        main.sum = sum_end;
        main.testp = testpppp;
    }

    /**
     * 獲取與node最近的子節點,根據距離去判斷遠近關係
     */
    private Node getShortestPath(Node node) {
        Node res = null;
        int minDis = Integer.MAX_VALUE;
        Map<Node, Integer> childs = node.getChild();
        for (Node child : childs.keySet()) {
            if (open.contai`
s(child)) {
                int distance = childs.get(child);
                if (distance < minDis) {
                    minDis = distance;
                    res = child;
                }
            }
        }
        return res;
    }
}

6.測試main函式:

public class Main {
    int sumend = 0;
    static int sum = 0;
    static String testp = null;
    ArrayList<String> listlist = new ArrayList<String>();
    ArrayList<String> listlist1 = new ArrayList<String>();
    static ArrayList<String> bigList = new ArrayList<String>();
    static ArrayList<Integer> bigList1 = new ArrayList<Integer>();

    public static void main(String[] args) throws Exception {
    //在main函式中輸入測試陣列
        String t[] = new String[] { "A", "B", "C", "D", "E", "F", "G", "H" };
        Main.getShort(t);
        int instance =findShortInstance("A","D");
        System.out.println(instance);
    }
    public static String getShort(String[] ss) throws Exception {
        Map<String, Integer> map = new HashMap<String, Integer>();
        String aa = null;
        ArrayList<String> list = new ArrayList<String>();
        for (int i = 0; i < ss.length; i++) {
            list.add(ss[i]);
        }
        Dijkstra test;
        List<Node> lists = new ArrayList<Node>();
        for (int i = 0; i < ss.length; i++) {
            Node node = new Node(ss[i]);
            lists.add(node);
        }
        for (int i = 0; i < ss.length; i++) {
            test = new Dijkstra();
            test.list = list;
            test.testpppp = ss[i];
            Node start = test.init(lists);
            test.computePath(start);
            test.printPathInfo(bigList,bigList1);
            map.put(testp, sum);
        }
         for (Map.Entry<String, Integer> me : map.entrySet()) {
                 }
        if (map != null) {
            Collection<Integer> c = map.values();
            Object[] obj = c.toArray();
            Arrays.sort(obj);
            int value = (int) obj[0];
            System.out.println("中心點距離其他所有點的最短距離為" + value);
            for (Map.Entry entry : map.entrySet()) {
                if (value == (int) entry.getValue()) {
                aa = (String) entry.getKey();
                }
            }
        }
        return aa;  
    }
    public static int findShortInstance(String a, String b)throws Exception {
        int instance = -1;
                for(int i=0; i<bigList.size(); i++){
                        if(bigList.get(i).contains(a) && bigList.get(i).contains(b)){
                instance = bigList1.get(i);
                return instance;
            }
        }
        return instance;
    }
}