图的入门和 深度优先遍历、广度优先遍历

一、基础知识:

(1)基本概念:

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

(2)图的表示方式:

邻接矩阵:
在这里插入图片描述
邻接表:
在这里插入图片描述

二、代码实现:

包含图的简单实现,深度优先遍历、广度优先遍历。
在这里插入图片描述
深度优先遍历:
在这里插入图片描述
广度优先遍历:
在这里插入图片描述在这里插入图片描述
在这里插入图片描述

代码汇总:

package graph;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;


/**
 * 图的简单实现
 */
public class GraphDemo {

    private ArrayList<String> vertexList; // 存储顶点集合
    private int[][] edges; // 定义邻接矩阵
    private int numOfEdges; //表示 图中 边的数目
    private boolean[] isVisited; // 表示是 该 节点 否被访问

    public GraphDemo(int n) {
        //初始化 邻接矩阵 和 存储顶点集合
        vertexList = new ArrayList<String>(n);
        edges = new int[n][n];
        numOfEdges = 0;
        isVisited = new boolean[n];
    }

    public static void main(String[] args) {

        int n = 8;

//        String vertex[] = {"A", "B", "C", "D", "E"};
        String vertex[] = {"1", "2", "3", "4", "5", "6", "7", "8"};
        GraphDemo graph = new GraphDemo(n);

        //首先添加顶点:
        for (String ver : vertex){
            graph.insertVertex(ver);
        }

        //添加边:
//        graph.insertEdge(0,1,1);
//        graph.insertEdge(0,2,1);
//        graph.insertEdge(1,2,1);
//        graph.insertEdge(1,3,1);
//        graph.insertEdge(1,4,1);

        //更新边的关系
        graph.insertEdge(0, 1, 1);
        graph.insertEdge(0, 2, 1);
        graph.insertEdge(1, 3, 1);
        graph.insertEdge(1, 4, 1);
        graph.insertEdge(3, 7, 1);
        graph.insertEdge(4, 7, 1);
        graph.insertEdge(2, 5, 1);
        graph.insertEdge(2, 6, 1);
        graph.insertEdge(5, 6, 1);

        graph.showGraph();

        System.out.println("深度优先遍历:");
        graph.depthFirstSearch();
        System.out.println();
        System.out.println("广度优先遍历:");
        graph.breadthFirstSearch();

    }


    //得到第一个邻接节点的下标(存在就返回对应的下标,否则返回-1)
    /**
     * index 从 0 开始
     * @param index
     * @return 找到就返回对应的下标,否则就返回 -1
     */
    public int getFirstNeighbor(int index){
        for (int i = 0; i < vertexList.size(); i++){
            if ( edges[index][i] > 0){
                return i;
            }
        }
        return -1;
    }

    //根据前一个邻接节点 的 下标 来获取下一个邻接节点的下标:(需要知道前一个邻接节点的 下标(v1,v2))
    public int getNextNeighbor(int v1, int v2){
        for (int j = v2 + 1; j < vertexList.size(); j++){
            if (edges[v1][j] > 0){
                return j;
            }
        }
        return -1;
    }

   //******************************************************
    //深度优先遍历:
    private void depthFirstSearch(boolean[] isVisited, int i){
        // 首先访问到该节点时,输出:
        System.out.print(getValueOfVertex(i) + "->");
        //将此节点设置为已经访问:
        isVisited[i] = true;

        //查找节点 i 的第一个邻接节点
        int firstNeighbor = getFirstNeighbor(i);

        while ( firstNeighbor != -1){ //查找,(进入到while循环说明有)
            if (!isVisited[firstNeighbor]){ //判断是否被访问过
                //如果没有被访问过,就进行遍历
                depthFirstSearch(isVisited,firstNeighbor); //存在且 未被访问 则进行 遍历
            }
            //如果已经被访问过:需要找下一个节点
            firstNeighbor = getNextNeighbor(i, firstNeighbor);
        }
    }

    //对depthFirstSearch进行重载,遍历所有的节点:
    public void depthFirstSearch(){
        isVisited = new boolean[vertexList.size()];
//        for (int i = 0 ; i < getNumOfVertex(); i++){
//            if (!isVisited[i]){ //  若没有 被访问 ,则进行 遍历
//                depthFirstSearch(isVisited,i);
//            }
//        }
        depthFirstSearch(isVisited,0);
    }
    //********************************************************

    //广度优先遍历:
    private void breadthFirstSearch(boolean[] isVisited, int i){
        int u; //队列头节点对应的下标
        int w; // 邻接节点w

        //创建一个队列记录节点的访问顺序
        LinkedList<Object> queue = new LinkedList<>();

        System.out.print(getValueOfVertex(i) + "->");

        isVisited[i] = true;

        queue.addLast(i);

        while (! queue.isEmpty()){
            u = (Integer) queue.removeFirst();

            w = getFirstNeighbor(u);

            while (w != -1){
                if (!isVisited[w]){
                    System.out.print(getValueOfVertex(w) + "->");
                    isVisited[w] = true;
                    queue.addLast(w);
                }
                w = getNextNeighbor(u,w);
            }
        }
    }

    public void breadthFirstSearch(){
        isVisited = new boolean[vertexList.size()];
        breadthFirstSearch(isVisited,0);
    }
    //***************************************************


    //返回结点的个数:
    public int getNumOfVertex(){
        return vertexList.size();
    }

    //显示 图 对应的 矩阵: 就是遍历 邻接矩阵
    public void showGraph(){
        for (int[] edge:edges){
            System.out.println(Arrays.toString(edge));
        }
    }

    //得到边的数目:
    public int getNumOfEdges(){
        return numOfEdges;
    }

    //返回结点 i (下标)对应的数据(即 节点的信息)
    public String getValueOfVertex(int i){
        return vertexList.get(i);
    }

    //返回 两顶点间 对应的权值: 两顶点间的权值在 邻接矩阵中 得到
    public int getWeight(int v1, int v2){
        return edges[v1][v2];
    }

    //插入结点:
    public void insertVertex(String vertex){
        vertexList.add(vertex);
    }


    //添加边:即 顶点 与 顶点 之间的关系(是否能够直接连通)
    /**
     * 指定 两个顶点的下标 v1 , v2 ,再指定 权值 weight (为 1 表示 能直连,0表示不能直连)
     * @param v1
     * @param v2
     * @param weight
     */
    public void insertEdge(int v1, int v2, int weight){
        edges[v1][v2] = weight;
        edges[v2][v1] = weight;
        numOfEdges++; //表示 边数 增加了 一条
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值