JAVA实现图的构建、BFS、DFS(分邻接矩阵存储与邻接表存储)

一、文章内容

1、以邻接矩阵存储的图(构建、BFS、DFS)

2、以邻接表存储的图(构建、BFS、DFS)

3、广度优先遍历用到的队列

二、以邻接矩阵存储的图(构建、BFS、DFS)

1、AMGraph.java

import java.util.Scanner;

// 邻接矩阵存储的图,以无向网为例
public class AMGraph {
    private static final int MAXINT = 10000;// 作为极大值
    private static final int MAXNUM = 100;// 顶点数组的最大容量
    private char[] vexs;// 顶点数组
    private int[][] arcs;// 临界矩阵
    private int vexNum;// 顶点个数
    private int arcNum;// 边个数
    private boolean[] visited;// 用于遍历时顶点是否被访问的标志,每次遍历前需要重置,数组中元素全部置为false

    public void createAMGraph(){
        Scanner in = new Scanner(System.in);

        // 初始化顶点数和边数
        System.out.println("请输入顶点数和边数,以空格隔开:");
        String line01 = in.nextLine();
        String[] nums = line01.split(" ");
        vexNum = Integer.valueOf(nums[0]);
        arcNum = Integer.valueOf(nums[1]);

        // 初始化顶点数组
        vexs = new char[MAXNUM];
        System.out.println("请输入顶点,以空格隔开:");
        String line02 = in.nextLine();
        char[] temp = line02.replaceAll(" ", "").toCharArray();
        for (int i=0; i<temp.length; ++i){
            vexs[i] = temp[i];
        }

        // 初始化邻接矩阵,值全部设置为-1
        arcs = new int[vexNum][vexNum];
        for (int i=0; i<vexNum; ++i){
            for (int j=0; j<vexNum; ++j){
                arcs[i][j] = MAXINT;
            }
        }

        // 为边赋权值
        for (int k=0; k<arcNum; ++k){
            System.out.println("请输入两个邻接顶点及其边的权值,以空格隔开:");
            String line03 = in.nextLine();
            String[] strs = line03.split(" ");
            char v1 = strs[0].charAt(0);
            char v2 = strs[1].charAt(0);
            int weight = Integer.valueOf(strs[2]);

            // 获取v1、v2两个顶点在顶点数组中的下标
            int i = locateVex(vexs, v1);
            int j = locateVex(vexs, v2);

            // 为邻接矩阵设值
            this.arcs[i][j] = weight;
            this.arcs[j][i] = weight;
        }
    }

    // 获取指定顶点在顶点数组中的下标
    private int locateVex(char[] vexs, char v) {
        for (int i=0; i<vexs.length; ++i){
            if (v == vexs[i]){
                return i;
            }
        }
        System.out.println("输入顶点有误,程序退出!");
        System.exit(-1);
        return -1;
    }

    /**
     * 深度优先遍历
     * @param g 待遍历的图(以邻接矩阵存储的图)
     * @param start 开始遍历的顶点在顶点数组中的下标
     */
    public void dfsTraverse(AMGraph g, int start){
        this.visited[start] = true;
        System.out.print(g.getVexs()[start] + " ");
        for (int i=0; i<g.getVexNum(); ++i){// 遍历邻接矩阵中顶点所在的行
            if (g.getArcs()[start][i]!=MAXINT && !this.visited[i]){
                dfsTraverse(g, i);
            }
        }
    }

    // 广度优先遍历
    public void bfsTraverse(AMGraph g, int start){
        Queue<Character> queue = new Queue<>(g.getVexNum()+1);

        // 入队
        queue.enter(g.getVexs()[start]);
        visited[start] = true;

        while ( !queue.is_empty() ){
            char c = queue.out();// 出队
            System.out.print(c + " ");
            start = locateVex(g.getVexs(), c);

            for (int i=0; i<g.getVexNum(); ++i){
                if (g.getArcs()[start][i]!=MAXINT && !visited[i]){
                    queue.enter(g.getVexs()[i]);// 入队
                    visited[i] = true;
                }
            }
        }
    }

    // 输出邻接矩阵
    public void showAM(){
        for (int i=0; i<vexNum; ++i){
            for (int j=0; j<vexNum; ++j){
                System.out.print(arcs[i][j] + "\t\t\t\t\t");
            }
            System.out.println();
        }
    }

    public char[] getVexs() {
        return vexs;
    }

    public void setVexs(char[] vexs) {
        this.vexs = vexs;
    }

    public int[][] getArcs() {
        return arcs;
    }

    public void setArcs(int[][] arcs) {
        this.arcs = arcs;
    }

    public int getVexNum() {
        return vexNum;
    }

    public void setVexNum(int vexNum) {
        this.vexNum = vexNum;
    }

    public int getArcNum() {
        return arcNum;
    }

    public void setArcNum(int arcNum) {
        this.arcNum = arcNum;
    }

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

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

 2、Test.java

public class Test {
    public static void main(String[] args) {
        AMGraph g = new AMGraph();

        // 创建邻接矩阵存储的图
        g.createAMGraph();

        // 输出邻接矩阵
        System.out.println("邻接矩阵如下:");
        g.showAM();

        // 深度优先遍历
        g.setVisited(new boolean[g.getVexNum()]);
        System.out.print("深度优先遍历结果:");
        g.dfsTraverse(g, 0);
        System.out.println();

        // 深度优先遍历
        g.setVisited(new boolean[g.getVexNum()]);
        System.out.print("广度优先遍历结果:");
        g.bfsTraverse(g, 0);
        System.out.println();
    }
}

3、测试结果

 

三、以邻接表存储的图(构建、BFS、DFS)

1、ALGraph.java

import java.util.Scanner;

// 邻接表存储的图
public class ALGraph {
    private static final int MVNUM = 100;
    private VNode[] vexs = new VNode[MVNUM];
    private int vexNum;
    private int arcNum;
    private int[] visited;// 顶点访问标志数组,每次遍历时须重新初始化,数组中元素全部置为0

    // 构建图
    public void createALGraph(){
        Scanner in = new Scanner(System.in);

        // 初始化顶点个数与边个数
        System.out.println("请输入顶点个数和边的个数,以空格隔开:");
        String line01 = in.nextLine().replaceAll(" ", "");
        vexNum = (int)line01.charAt(0)-48;
        arcNum = (int)line01.charAt(1)-48;

        // 初始化VNode[]的顶点信息
        System.out.println("请输入顶点字符,以空格隔开:");
        String line02 = in.nextLine();
        char[] chars = line02.replaceAll(" ", "").toCharArray();
        for (int i=0; i<vexNum; ++i){
            VNode node = new VNode();
            node.setC(chars[i]);
            vexs[i] = node;
        }

        // 初始化VNode[]中边节点信息
        for (int k=0; k<arcNum; ++k){
            System.out.println("请输入互为邻接点的顶点及对应的权值,以空格隔开:");
            String line03 = in.nextLine();
            String[] strings = line03.split(" ");
            char v1 = strings[0].charAt(0);
            char v2 = strings[1].charAt(0);
            int weight = Integer.valueOf(strings[2]);

            // 定位顶点在VNode中的下标
            int i = locateVex(vexs, v1);
            int j = locateVex(vexs, v2);

            // 创建边节点,采用头插法连接到链表中
            AdjNode node01 = new AdjNode();// 连接到下标为i的指针域
            node01.setAdjVex(j);
            node01.setWeight(weight);
            node01.setNextArc(vexs[i].getFirstArc());
            vexs[i].setFirstArc(node01);
            AdjNode node02 = new AdjNode();// 连接到下标为j的指针域
            node02.setAdjVex(i);
            node02.setWeight(weight);
            node02.setNextArc(vexs[j].getFirstArc());
            vexs[j].setFirstArc(node02);
        }
    }

    // 定位顶点下标
    private int locateVex(VNode[] g, char v2) {
        for (int i=0; i<vexNum; ++i){
            if (g[i].getC() == v2){
                return i;
            }
        }
        System.out.println("输入节点信息有误,程序退出!");
        System.exit(-1);
        return -1;
    }

    // 输出邻接表
    public void showAL(){
        for (int i=0; i<vexNum; ++i){
            System.out.print(vexs[i].getC());
            AdjNode temp = vexs[i].getFirstArc();
            while (temp != null){
                System.out.print("-->" + temp.getAdjVex());
                temp = temp.getNextArc();
            }
            System.out.println();
        }
    }

    // 深度优先遍历
    public void dfsTraverse(ALGraph g, int start){
        visited[start] = 1;
        System.out.print(g.getVexs()[start].getC() + " ");

        AdjNode temp = g.getVexs()[start].getFirstArc();
        while (temp != null){
            if (visited[temp.getAdjVex()] == 0){
                start = temp.getAdjVex();
                dfsTraverse(g, start);
            }
            temp = temp.getNextArc();
        }
    }

    // 广度优先遍历
    public void bfsTraverse(ALGraph g, int start){
        Queue<VNode> queue = new Queue<>(g.getVexNum());

        // 遍历
        queue.enter(g.getVexs()[start]);
        visited[start] = 1;
        while ( !queue.is_empty() ){
            VNode node = queue.out();// 出队一个元素
            System.out.print(node.getC() + " ");

            // 入队邻接点
            AdjNode temp = node.getFirstArc();
            while (temp != null){
                start = temp.getAdjVex();
                if (visited[start] == 0){
                    queue.enter(g.getVexs()[start]);
                    visited[start] = 1;
                }
                temp = temp.getNextArc();
            }
        }
    }

    // getter and setter
    public VNode[] getVexs() {
        return vexs;
    }

    public void setVexs(VNode[] vexs) {
        this.vexs = vexs;
    }

    public int getVexNum() {
        return vexNum;
    }

    public void setVexNum(int vexNum) {
        this.vexNum = vexNum;
    }

    public int getArcNum() {
        return arcNum;
    }

    public void setArcNum(int arcNum) {
        this.arcNum = arcNum;
    }

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

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

// 数组元素
class VNode{
    private char c;
    private AdjNode firstArc;

    public char getC() {
        return c;
    }

    public void setC(char c) {
        this.c = c;
    }

    public AdjNode getFirstArc() {
        return firstArc;
    }

    public void setFirstArc(AdjNode firstArc) {
        this.firstArc = firstArc;
    }
}

// 边节点
class AdjNode{
    private int adjVex;
    private int weight;
    private AdjNode nextArc;

    public int getAdjVex() {
        return adjVex;
    }

    public void setAdjVex(int adjVex) {
        this.adjVex = adjVex;
    }

    public int getWeight() {
        return weight;
    }

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

    public AdjNode getNextArc() {
        return nextArc;
    }

    public void setNextArc(AdjNode nextArc) {
        this.nextArc = nextArc;
    }
}

2、Test.java

public class Test {
    public static void main(String[] args) {
        ALGraph g = new ALGraph();

        // 构建图
        g.createALGraph();

        // 输出邻接表
        System.out.println("邻接表如下:");
        g.showAL();

        // 深度优先遍历图
        System.out.print("深度优先遍历:");
        g.setVisited(new int[g.getVexNum()]);
        g.dfsTraverse(g, 0);
        System.out.println();

        // 广度优先遍历
        g.setVisited(new int[g.getVexNum()]);
        System.out.print("广度优先遍历:");
        g.bfsTraverse(g, 0);
        System.out.println();
    }
}

3、测试结果

 

四、广度优先遍历用到的队列

public class Queue<E> {
    private E[] arr;
    private int len;
    private int front = 0;
    private int rear = 0;

    // 初始化

    public Queue(int len) {
        this.len = len;
        this.arr = (E[]) new Object[len];
    }

    // 队列是否已满
    public boolean is_full(){
        return (front+1)%len==rear;
    }

    // 队列是否为空
    public boolean is_empty(){
        return front==rear;
    }

    // 入队
    public void enter(E e){
        if ( is_full() ){
            return;
        }
        front = (front+1)%len;
        arr[front] = e;
    }

    // 出队
    public E out(){
        if ( is_empty() ){

        }
        rear = (rear+1)%len;
        return arr[rear];
    }
}

  • 4
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值