邻接矩阵来实现带权图结构,并通过Dijkstra算法寻找最短路径

1.邻接矩阵来实现带权图结构

package com.upupgogogo;

/**
 * Created by upupgogogo on 2018/3/26.上午11:45
 */
public class AdjMatrixGraph {

    protected SeqList vertexlist;    //顺序表储存图的定点集合
    protected int[][] adjmatrix;        //图的邻接矩阵
    private final int MAX_WEIGHT = 99999;  //最大权值(表示无穷大)

    public AdjMatrixGraph(int size){
        size = size < 10 ? 10 : size;
        this.vertexlist = new SeqList<>(size);  //构造容量为size的空顺序表,当前定点数为0
        this.adjmatrix = new int[size][size];   //初始化邻接矩阵
        for (int i = 0; i < size; i++)
            for (int j = 0; j < size; j++)
                this.adjmatrix[i][j] = (i == j) ? 0 : MAX_WEIGHT;
    }

    public AdjMatrixGraph(T[] vertexlist, Edge[] edges){
        this(vertexlist.length);
        if (vertexlist == null)
            return;
        for (int i = 0; i < vertexlist.length; i++)
            insertVertex(vertexlist[i]);
        if (edges != null)
            for (int j = 0; j < edges.length; j++)
                insertEdge(edges[j]);
    }

    //返回顶点数
    public int vertexCount(){return this.vertexlist.length();}

    //返回顶点vi的数据元素
    public T get(int i){ return this.vertexlist.get(i);}

    //返回边的权值
    public int getWeight(int i, int j){

        return this.adjmatrix[i][j];
    }

    public void checkIndex(int i, int j){
        if (i > this.vertexCount() || i < 0 || j > this.vertexCount() || j < 0)
            throw new IndexOutOfBoundsException("size ="+this.vertexCount());
    }
    
    //新增一个顶点
    public int insertVertex(T x){
        //顺序表自动扩容
        this.vertexlist.add(x);
        
        //二维数组判断是否扩容
        if (this.vertexCount() > this.adjmatrix.length){
            int[][] temp = this.adjmatrix;
            adjmatrix = new int[temp.length*2][temp.length*2];
            for (int i = 0; i < temp.length; i++){
                for (int j = 0; j < temp.length; j++)
                    this.adjmatrix[i][j] = temp[i][j];
                for (int j = temp.length; j < temp.length*2; j++)
                    this.adjmatrix[i][j] = MAX_WEIGHT;
            }
            for (int i = temp.length; i < temp.length*2; i++)
                for (int j = 0; j < temp.length*2; j++)
                    adjmatrix[i][j] = (i == j) ? 0 : MAX_WEIGHT;
        }
        return this.vertexlist.length() - 1;
    }

    //新增一条边
    public void insertEdge(int i, int j, int weight){
        int n = this.vertexCount();
        if (i >= 0 && i < n && j >= 0 && j < n && i != j )
            this.adjmatrix[i][j] = weight;
    }

    public void insertEdge(Edge edge){
        insertEdge(edge.getStart(),edge.getDest(),edge.getWeight());
    }

    //删除一条边
    public void removeEdge(int i, int j){
        int n = this.vertexCount();
        if (i >= 0 && i < n && j >= 0 && j < n && i != j )
            this.adjmatrix[i][j] = MAX_WEIGHT;
    }
    
    //删除一个顶点
    public void removeVertex(int i){
        int n = this.vertexCount();
        if (i < 0 || i >= n)
            return;
        this.vertexlist.remove(i);
        
        //删除二维数组该点的关系
        for (int j = i; j < n-1; j++){
            for (int k = 0; k < n; k++)
                this.adjmatrix[j][k] = adjmatrix[j+1][k];
        }
        for (int j = i; j < n-1; j++){
            for (int k = 0; k < n-1; k++)
                this.adjmatrix[k][j] = adjmatrix[k][j+1];
        }

    }

2.通过Dijkstra算法寻找最短路径

public void shortestPath(int i){
        int n = this.vertexCount();
        int[] dist = new int[n];   //i出发,到达每个顶点的最短路径长度
        int[] path = new int[n];   //i出发,最短路径终点的前一个顶点
        int[] vset = new int[n];   //i出发,以求最短路径的定点集合
        vset[i] = 1;
        for (int j = 0; j < n; j++){
            dist[j] = this.getWeight(i,j);
            path[j] = (j != i && dist[j] != MAX_WEIGHT) ? i : -1;
        }
        for(int j = (i+1) % n; j != i; j = (j+1) % n){
            int mindist = MAX_WEIGHT;
            int u = 0;
            for(int k = 0; k < n; k++)
                //从i出发,寻找未确定最短路径
                if (vset[k] == 0 && dist[k] < mindist){
                //得到最短路径的点
                u = k;
                //将最短路径的值放在临时的mindist变量里面来判断是否有还有最短路径
                mindist = dist[k];
                }
            if (mindist == MAX_WEIGHT)
                break;
            //将确定好的最短路径放入数组
            vset[u] = 1;

            //根据最短路径的点来进行调整其他的路径
            for (int k = 0; k < n; k++)
                //这里进行调整有三个判断要求
                //1.调整未确定的
                //2.该点到达其他点不能没有权值
                //3.该点到达其他点必须小于从i出发到达改点
                if (vset[k] == 0 && getWeight(u,k) < MAX_WEIGHT && dist[u]+getWeight(u,k)
                        

3.测试结果

public static void main(String[] args) {
        String[] vertices = {"A","B","C","D","E"};
        Edge[] edges = {new Edge(0,1,5),new Edge(0,3,2),
                        new Edge(1,0,5),new Edge(1,3,6),
                        new Edge(1,2,7),new Edge(2,1,7),
                new Edge(2,3,8),new Edge(2,4,3),
                new Edge(3,0,2),new Edge(3,1,6),
                new Edge(3,2,8),new Edge(3,4,9),
                new Edge(4,2,3),new Edge(4,3,9),
                };
        AdjMatrixGraph graph = new AdjMatrixGraph(vertices,edges);
        System.out.println(graph);
        graph.insertVertex("F");
        System.out.println(graph);
        graph.removeVertex(1);
        System.out.println(graph);
        graph.insertEdge(new Edge(4,0,4));
        System.out.println(graph);
        graph.shortestPath(4);
    }
顶点集合: [A,B,C,D,E,]
邻接矩阵:  
 0 5 ∞ 2 ∞
 5 0 7 6 ∞
 ∞ 7 0 8 3
 2 6 8 0 9
 ∞ ∞ 3 9 0


顶点集合: [A,B,C,D,E,F,]
邻接矩阵:  
 0 5 ∞ 2 ∞ ∞
 5 0 7 6 ∞ ∞
 ∞ 7 0 8 3 ∞
 2 6 8 0 9 ∞
 ∞ ∞ 3 9 0 ∞
 ∞ ∞ ∞ ∞ ∞ 0


顶点集合: [A,C,D,E,F,]
邻接矩阵:  
 0 ∞ 2 ∞ ∞
 ∞ 0 8 3 ∞
 2 8 0 9 ∞
 ∞ 3 9 0 ∞
 ∞ ∞ ∞ ∞ 0


顶点集合: [A,C,D,E,F,]
邻接矩阵:  
 0 ∞ 2 ∞ ∞
 ∞ 0 8 3 ∞
 2 8 0 9 ∞
 ∞ 3 9 0 ∞
 4 ∞ ∞ ∞ 0




从顶点F到其他顶点的最短距离如下: 
(F,A)长度为4
(F,A,D,C)长度为14
(F,A,D)长度为6

(F,A,D,E)长度为15

下面附上边类以及顺序表类

package com.upupgogogo;

/**
 * Created by upupgogogo on 2018/3/26.上午11:40
 */
public class Edge implements Comparable {

    private int start,dest,weight;

    public int getStart() {
        return start;
    }

    public int getDest() {
        return dest;
    }

    public int getWeight() {
        return weight;
    }

    public void setStart(int start) {
        this.start = start;
    }

    public void setDest(int dest) {
        this.dest = dest;
    }

    public void setWeight(int weight) {
        this.weight = weight;
    }

    public Edge(int start, int dest, int weight){
        this.start = start;
        this.dest = dest;
        this.weight = weight;
    }

    public String toString() {
        return "("+start+","+dest+","+weight+")";
    }

    public int compareTo(Edge e) {
        if (this.start != e.start)
            return this.start - e.start;
        return this.dest - e.dest;
    }
}
package com.upupgogogo;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

/**
 * Created by upupgogogo on 2018/3/19.下午6:34
 */

/**
 * 顺序表
 * @param 
 */
public class SeqList implements LList {


    private Object[] element; //数据保存数组,初始化时会给它一个默认大大小

    private int size;   //记录数据的元素,初始化为0

    private static int DEFAULT_CAPACITY = 10;  //给数组的一个默认大小

    public SeqList(){
        this.element = new Object[DEFAULT_CAPACITY];
        this.size = 0;
    }

    public SeqList(int capacity){
        if (capacity < 0)
            throw new NegativeArraySizeException("Array length anomaly");
        this.element = new Object[capacity];
        this.size = 0;
    }

    public T get(int index) {
        if (index < 0 || index >= size)
            throw new NegativeArraySizeException("index out of bounds");

        return (T)this.element[index];
    }

    public boolean isEmpty() {
        return size == 0;
    }

    public int length() {
        return this.size;
    }

    /**
     * 1.判断参数的可行性
     * 2.判断是否扩容
     * 3.从最后一个元素向后移一个下标,直到当前插入的下标
     * 4.赋值给给当前插入的下标
     * 5.容量长度+1
     * @param index 数组下标
     * @param x
     */
    public void add(int index, T x) {
        if (index < 0 || index > size)
            throw new NegativeArraySizeException("index out of bounds: index: " + index + " size:  " + size);

        if (size == element.length){
            Object[] temp = element;
            this.element = new Object[size*2];
            for (int j = 0; j < temp.length; j++)
                this.element[j] = temp[j];
        }

        for(int j = this.size-1; j >= index; j--)
            element[j+1] = element[j];
        element[index] = x;

        this.size++;
    }

    public void add(T x) {
        this.add(this.size,x);
    }

    public T remove(int index) {
        if (index < 0 || index >= size)
            throw new NegativeArraySizeException("index out of bounds");
        T old = (T)this.element[index];
        for (int j = index; j < this.size-1; j++)
            element[j] = element[j+1];
        element[this.size-1] = null;
        this.size--;
        return old;
    }

    public void set(int index, T x) {
        if (index < 0 || index >= size)
            throw new NegativeArraySizeException("index out of bounds: index: " + index + " size:  " + size);
        this.element[index] = x;

    }

    @Override
    public String toString() {
        String str = "";
        for (int i = 0; i < this.size; i++)
            str += element[i].toString()+",";
        return "["+str+"]";
    }

源码地址,有需要自取

https://github.com/OMGye/Graph

你可能感兴趣的:(java,数据结构,图结构)