24.图的基础介绍

图是一种数据结构,其中节点可以具有零个或者多个相邻的元素,两个节点之间的连接成为边。节点也可以成为顶点。

常用概念

  • 顶点 vertex 图中的每一个节点都是一个顶点 通常记做V
  • 边 edge 两个顶点之间的连接 通常记做E
  • 路径 从一个顶点到另一个顶点经过的边的总和,如果带权则是所有边的权重和
  • 无向图 顶点与顶点之间没有方向,即可以从顶点A到顶点B,也可以动B到A
  • 有向图 与无向图相反顶点与顶点之间存在明显的方向
  • 带权图 边上面带有权值的图称为带权图
  • 弧头 弧尾 在有向图中,无箭头端的顶点称为起始点或者弧尾,有箭头的顶点称为终端点或者弧头
  • (V1,V2)和<V1,V2>的区别 ,(V1,V2)表示无向图中2个顶点V1和V2,<V1,V2>表示有向图V1到V2的单向关系

图的表示方式

主要有两种,二维数组表示的邻接矩阵或者链表表示的邻接表

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qQFSMWPQ-1596528523972)(C:\Users\denglw\AppData\Roaming\Typora\typora-user-images\image-20200731103849921.png)]

  • 邻接矩阵: 表示图中顶点之间相邻关系的矩阵,若有N个顶点的图来讲,矩阵的row和col都是N,上图就是由一个二维数据表示的01234 5个顶点之间的连接关系 数组中的值为1表示连接 0表示未连接如 arr[0,1]=1 表示 0顶点和1顶点是连同的即存在边 arr[0,2]=0 表示顶点0和顶点2没有直接连接的边

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Fz6ELa84-1596528523975)(C:\Users\denglw\AppData\Roaming\Typora\typora-user-images\image-20200731105835183.png)]

  • 邻接表: 邻接表一般采用数组+链表的形式,数组表示各个顶点,链表中的元素表示该顶点与链表中的元素相连,与链表本身的指针没有关系。如上图 数组0 对应的链表1->3->4 表示0这个顶点与1 3 4这个顶点连接 数组1 表示1这个顶点与 0 2 4顶点相连以此类推
  • 邻接矩阵和邻接表的区别 邻接矩阵会为每个顶点都分配N个边的空间,其实很多表都不存在,存在了空间的损失,邻接表值关心存在边,因此没有空间的损失。

核心方法

    /**
     * 添加顶点
     *
     * @param vertex
     */
    public void addVertex(String vertex) {
        vertexList.add(vertex);
    }

    /**
     * 为V1顶点和V2顶点添加边 如果只为1就是
     *
     * @param v1     第一个顶点
     * @param v2     第二个顶点
     * @param weight 权 约定1为连接 0未连接
     */
    public void insertEdge(int v1, int v2, int weight) {
        if (vertexSize < maxVertexSize) {
            edges[v1][v2] = weight;
            edges[v2][v1] = weight;
            vertexSize++;
        }
            /**
     * 打印图
     */
    public void show() {
        for (String s : vertexList) {
            System.out.print("\t" + s);
        }
        System.out.println();
        for (int i = 0; i < edges.length; i++) {
            int[] edge = edges[i];
            System.out.print(vertexList.get(i) + "\t");
            for (int j : edge) {
                System.out.print(j + "\t");
            }
            System.out.println();
        }
    }

完整代码

package com.corn.datastruct.graph;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class GraphDemo {
    public static void main(String[] args) {
        //测试一把图是否创建ok
        int n = 5;  //结点的个数
        String[] vertexs = {"A", "B", "C", "D", "E"};
//        String Vertexs[] = {"1", "2", "3", "4", "5", "6", "7", "8"};

        //创建图对象
        Graph graph = new Graph(n);
        //循环的添加顶点
        for (String vertex : vertexs) {
            graph.addVertex(vertex);
        }
        graph.insertEdge(0, 1, 1); // A->B
        graph.insertEdge(0, 2, 1); // A->C
        graph.insertEdge(1, 2, 1); // B->C
        graph.insertEdge(1, 3, 1); // B->D
        graph.insertEdge(1, 4, 1); // B->E
        graph.show();

    }
}

class Graph {
    /**
     * 顶点集合
     */
    public List<String> vertexList;

    /**
     * 表示顶点之间边关系的二维数组
     */
    public int[][] edges;

    /**
     * 最多顶点个数
     */
    public final int maxVertexSize;

    /**
     * 当前图顶点的个数
     */
    public int vertexSize;

    Graph(int maxVertexSize) {
        this.maxVertexSize = maxVertexSize;
        /**
         * 初始化 顶点集合 和顶点边关系二维数组
         */
        this.vertexList = new ArrayList<>(maxVertexSize);
        this.edges = new int[maxVertexSize][maxVertexSize];
    }

    /**
     * 获取某一个顶点的 第一个连接顶点 相当于从arr[v]中的一维数组中获取第一个为1的元素的下标
     *
     * @param v
     * @return
     */
    public int getFirstNeighbor(int v) {
        int firstIndex = 0;
        while (firstIndex < vertexSize) {
            if (edges[v][firstIndex] == 1) {
                return firstIndex;
            } else {
                firstIndex++;
            }
        }
        return -1;
    }

    /**
     * 获取v1顶点 从v2连接点之后的第一个连接点的下标
     * 比如V1=A V2=B
     * 如测试 ABCDE 这个图中  A->B 连接后 一个就是A-C 则下标为2
     * V1=D V2=A D->A没有连接 下一个看D->B是有连接的 则返回1
     *
     * @param v1
     * @param v2
     * @return
     */
    public int getNextNeighbor(int v1, int v2) {
        for (int i = v2 + 1; i < getVertexSize(); i++) {
            if (edges[v1][i] == 1) {
                return i;
            }
        }
        return -1;
    }

    /**
     * 添加顶点
     *
     * @param vertex
     */
    public void addVertex(String vertex) {
        vertexList.add(vertex);
    }

    /**
     * 为V1顶点和V2顶点添加边 如果只为1就是
     *
     * @param v1     第一个顶点
     * @param v2     第二个顶点
     * @param weight 权 约定1为连接 0未连接
     */
    public void insertEdge(int v1, int v2, int weight) {
        if (vertexSize < maxVertexSize) {
            edges[v1][v2] = weight;
            edges[v2][v1] = weight;
            vertexSize++;
        }
    }

    /**
     * 获取2个顶点的权重 (边信息)
     *
     * @param v1
     * @param v2
     */
    public int getWeight(int v1, int v2) {
        return edges[v1][v2];
    }

    /**
     * 获取index获取 顶点集合中的顶点元素
     *
     * @param index
     * @return
     */
    public String getVertexByIndex(int index) {
        return vertexList.get(index);
    }

    /**
     * 获取当前图中有多少个顶点
     *
     * @return
     */
    public int getVertexSize() {
        return vertexSize;
    }

    /**
     * 打印图
     */
    public void show() {
        for (String s : vertexList) {
            System.out.print("\t" + s);
        }
        System.out.println();
        for (int i = 0; i < edges.length; i++) {
            int[] edge = edges[i];
            System.out.print(vertexList.get(i) + "\t");
            for (int j : edge) {
                System.out.print(j + "\t");
            }
            System.out.println();
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值