数据结构—— Java实现图的算法代码(深度优先遍历、广度优先遍历、最短路径)


图的基础知识在这两篇博客中:
数据结构——图的基础知识
数据结构——图的应用算法详解


一、图的结构定义

package GraphPackage;

public class GraphNode {
    int[][] arc;    //边的信息
    char[] vex;   //顶点信息
    int arcnum;     //边数目
    int vexnum;     //顶点数目
    int[] visited;  //访问标志数组,用来记录节点是否被访问过

    public GraphNode(int[][] arc, char[] vex, int arcnum, int vexnum, int[] visited) {
        this.arc = arc;
        this.vex = vex;
        this.arcnum = arcnum;
        this.vexnum = vexnum;
        this.visited = visited;
    }

    public GraphNode() {
        this.arc = arc;
        this.vex = vex;
        this.arcnum = arcnum;
        this.vexnum = vexnum;
        this.visited = visited;
    }



    public int[] getVisited() {
        return visited;
    }

    public void setVisited(int[] visited) {
        this.visited = visited;
    }

    public int[][] getArc() {
        return arc;
    }

    public void setArc(int[][] arc) {
        this.arc = arc;
    }

    public char[] getVex() {
        return vex;
    }

    public void setVex(char[] vex) {
        this.vex = vex;
    }

    public int getArcnum() {
        return arcnum;
    }

    public void setArcnum(int arcnum) {
        this.arcnum = arcnum;
    }

    public int getVexnum() {
        return vexnum;
    }

    public void setVexnum(int vexnum) {
        this.vexnum = vexnum;
    }
}

二、深度优先遍历

package GraphPackage;

import java.util.Stack;

public class DFS {

    public static void dfs(GraphNode graph){
        graph.setVisited(new int[graph.vexnum]);    //初始化访问标志数组
        Stack<Integer> stack = new Stack<Integer>();
        for(int i = 0;i < graph.vexnum; i++){   //遍历图
            if(graph.visited[i] == 0){  //如果该节点没有被访问过
                graph.visited[i] = 1;   //访问该节点,将访问标志数组置为1
                System.out.print(graph.vex[i] + " ");   //打印该节点
                stack.push(i);  //该节点进栈
            }
            while(!stack.isEmpty()){    //栈不为空,进入循环
                int k = stack.pop();    //栈顶节点出栈
                for(int j = 0; j < graph.vexnum; j++){
                    //如果是相邻的节点且没有访问过
                    if(graph.arc[k][j] == 1 && graph.visited[j] == 0){
                        graph.visited[j] = 1;   //访问该节点,将访问标志数组置为1
                        System.out.print(graph.vex[j] + " ");   //打印该节点
                        stack.push(j);  //该节点进栈
                        break;  //这条路结束,返回上一个节点
                    }
                }
            }
        }
    }

    public static void main(String[] args) {
        GraphNode graph = new GraphNode();
        char[] vex = {'A', 'B', 'C', 'D', 'E', 'F', 'G'};
        int[][] arc = {{0,1,1,1,0,0,0},{1,0,0,1,1,0,0},{1,0,0,0,0,1,0},
                {1,1,0,0,0,1,1},{0,1,0,0,0,0,1},{0,0,1,1,0,0,1},{0,0,0,1,1,1,0}};
        graph.setVex(vex);  //给顶点赋值
        graph.setArc(arc);  //给边赋值
        graph.setVexnum(vex.length);    //给顶点个数赋值
        int arccount = 0;   //计算边的个数
        for (int i = 0; i < vex.length; i++){
            for (int j = 0; j < vex.length; j++){
                if (arc[i][j] == 1){
                    arccount++;
                }
            }
        }
        graph.setArcnum(arccount/2);    //给边个数赋值
        System.out.println("深度优先遍历:");
        dfs(graph);
    }
}

在这里插入图片描述

三、广度优先遍历

package GraphPackage;

import java.util.LinkedList;
import java.util.Stack;

public class BFS {

    public static void bfs(GraphNode graph){
        graph.setVisited(new int[graph.vexnum]);    //初始化访问标志数组
        LinkedList<Integer> queue = new LinkedList<>();
        for (int i = 0; i < graph.vexnum; i++){
            if (graph.visited[i] == 0){
                graph.visited[i] = 1;   //访问该节点,将访问标志数组置为1
                System.out.print(graph.vex[i] + " ");   //打印该节点
                queue.push(i);  //该节点入队
            }
            while(!queue.isEmpty()){    //队列不为空,进入循环
                int k = queue.poll();  //队头节点出队
                for(int j = 0; j < graph.vexnum; j++){
                    //如果是相邻的节点且没有访问过
                    if(graph.arc[k][j] == 1 && graph.visited[j] == 0){
                        graph.visited[j] = 1;   //访问该节点,将访问标志数组置为1
                        System.out.print(graph.vex[j] + " ");   //打印该节点
                        queue.push(j);  //该节点入队
                    }
                }
            }
        }
    }

    public static void main(String[] args) {
        GraphNode graph = new GraphNode();
        char[] vex = {'A', 'B', 'C', 'D', 'E', 'F', 'G'};
        int[][] arc = {{0,1,1,1,0,0,0},{1,0,0,1,1,0,0},{1,0,0,0,0,1,0},
                {1,1,0,0,0,1,1},{0,1,0,0,0,0,1},{0,0,1,1,0,0,1},{0,0,0,1,1,1,0}};
        graph.setVex(vex);  //给顶点赋值
        graph.setArc(arc);  //给边赋值
        graph.setVexnum(vex.length);    //给顶点个数赋值
        int arccount = 0;   //计算边的个数
        for (int i = 0; i < vex.length; i++){
            for (int j = 0; j < vex.length; j++){
                if (arc[i][j] == 1){
                    arccount++;
                }
            }
        }
        graph.setArcnum(arccount/2);    //给边个数赋值
        System.out.println("广度优先遍历:");
        bfs(graph);
    }
}

在这里插入图片描述

四、最短路径(Dijkstra)

package GraphPackage;

public class Dijkstra {

    public static int[] dijkstra(GraphNode graph){

        int[] results = new int[graph.vexnum];
        graph.setVisited(new int[graph.vexnum]);    //初始化访问标志数组
        graph.visited[0] = 1;   //0顶点已经被访问过
        for (int i = 1; i < graph.vexnum; i++){
            results[i] = graph.arc[0][i];
        }

        for (int i = 1; i < graph.vexnum; i++){
            int min = Integer.MAX_VALUE;    //用于暂时存放顶点A到i的最短距离,初始化为最大值
            int k = 0;
            //找到顶点A到其他顶点中距离最小的一个顶点
            for (int j = 1; j < graph.vexnum; j++){
                if (graph.visited[j] == 0 && results[j] != -1 && min > results[j]){
                    min = results[j];
                    k = j;
                }
            }
            graph.visited[k] = 1;   //将距离最小的点记为已遍历
            //将顶点A到其他顶点的距离 与 加入中间顶点k之后的距离 进行比较,更新最短距离
            for (int j = 1; j < graph.vexnum; j++){
                if (graph.visited[j] == 0){     //顶点j未被遍历
                    //顶点k到j有边;
                    //并且,顶点0到j的距离>顶点0到k再到j的距离 或 顶点0无法直接到达顶点j
                    if (graph.arc[k][j] != -1 &&
                            (results[j] > min + graph.arc[k][j] || results[j] == -1)){
                        results[j] = min + graph.arc[k][j];     //更新顶点0到j的最短距离
                    }
                }
            }
        }
        return results;
    }

    public static void main(String[] args) {
        GraphNode graph = new GraphNode();
        char[] vex = {'A', 'B', 'C', 'D', 'E', 'F'};
        int[][] arc = {{0,6,3,-1,-1,-1},{6,0,2,5,-1,-1},{3,2,0,3,4,-1},
                {-1,5,3,0,2,3},{-1,-1,4,2,0,5},{-1,-1,-1,3,5,0}};
        graph.setVex(vex);  //给顶点赋值
        graph.setArc(arc);  //给边赋值
        graph.setVexnum(vex.length);    //给顶点个数赋值
        int arccount = 0;   //计算边的个数
        for (int i = 0; i < vex.length; i++){
            for (int j = 0; j < vex.length; j++){
                if (arc[i][j] != -1 && arc[i][j] != 0){
                    arccount++;
                }
            }
        }
        graph.setArcnum(arccount/2);    //给边个数赋值
        System.out.println("A点到其他各点的最短路径:");
        int[] results = dijkstra(graph);
        for (int result : results){
            System.out.print(result + " ");
        }
    }
}

在这里插入图片描述
输入的测试用例为下面这个图:
在这里插入图片描述

  • 0
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是Java实现连通深度优先遍历广度优先遍历的示例代码: 1. 深度优先遍历(DFS): ```java import java.util.*; class Graph { private int V; // 顶点的个数 private LinkedList<Integer> adj[]; // 邻接表 // 构造函数 Graph(int v) { V = v; adj = new LinkedList[v]; for (int i = 0; i < v; ++i) adj[i] = new LinkedList(); } // 添加边 void addEdge(int v, int w) { adj[v].add(w); } // 递归函数,于深度优先遍历 void DFSUtil(int v, boolean visited[]) { visited[v] = true; System.out.print(v + " "); Iterator<Integer> i = adj[v].listIterator(); while (i.hasNext()) { int n = i.next(); if (!visited[n]) DFSUtil(n, visited); } } // 对给定的顶点进行深度优先遍历 void DFS(int v) { boolean visited[] = new boolean[V]; DFSUtil(v, visited); } } public class Main { public static void main(String args[]) { Graph g = new Graph(4); g.addEdge(0, 1); g.addEdge(0, 2); g.addEdge(1, 2); g.addEdge(2, 0); g.addEdge(2, 3); g.addEdge(3, 3); System.out.println("深度优先遍历结果:"); g.DFS(2); } } ``` 输出结果: ``` 深度优先遍历结果: 2 0 1 3 ``` 2. 广度优先遍历(BFS): ```java import java.util.*; class Graph { private int V; // 顶点的个数 private LinkedList<Integer> adj[]; // 邻接表 // 构造函数 Graph(int v) { V = v; adj = new LinkedList[v]; for (int i = 0; i < v; ++i) adj[i] = new LinkedList(); } // 添加边 void addEdge(int v, int w) { adj[v].add(w); } // 对给定的顶点进行广度优先遍历 void BFS(int s) { boolean visited[] = new boolean[V]; LinkedList<Integer> queue = new LinkedList<Integer>(); visited[s] = true; queue.add(s); while (queue.size() != 0) { s = queue.poll(); System.out.print(s + " "); Iterator<Integer> i = adj[s].listIterator(); while (i.hasNext()) { int n = i.next(); if (!visited[n]) { visited[n] = true; queue.add(n); } } } } } public class Main { public static void main(String args[]) { Graph g = new Graph(4); g.addEdge(0, 1); g.addEdge(0, 2); g.addEdge(1, 2); g.addEdge(2, 0); g.addEdge(2, 3); g.addEdge(3, 3); System.out.println("广度优先遍历结果:"); g.BFS(2); } } ``` 输出结果: ``` 广度优先遍历结果: 2 0 3 1 ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值