数据结构-13-图

十三、图(Graph)

1、概念

二叉树最多有两个子节点,节点存在父子关系,当我们想表示更多的关联关系时,就需要使用图来表示。

一个图由多个顶点(vertex)组成,每两个相连顶点间的通路被称之为(edge)。

从某个顶点到另外一个顶点所经过的所有顶点,被称之为路径。

无向图:顶点和顶点间的连接没有方向。即A-B,也可以是B-A。

A***B
**
* *
*  *
C***D

有向图:顶点和顶点间的连接有方向。即只能是A-B,不能是B-A。

A-->B
↓↘
C-->D

带权图(网):图的边上有权值。

A--3--B
| \
2   9
|    \
C--7--D

2、表示形式

A + + C
+ +    +
+   +   +
B + + D  E

一种是使用**二维数组(邻接矩阵)**的形式。

图有n个顶点,矩阵(正方形)大小就是n × n。使用既定的值来表示直接连通(例如1)和直接不通(例如0)。很直观,但是浪费内存空间。

  A B C D E
A 0 1 1 1 0
B 1 0 0 1 0
C 1 0 0 0 1
D 1 1 0 0 0
E 0 0 1 0 0

另一种是使用一维数组+链表的形式。数组按照顺序存储了每个顶点,每个顶点都有其对应的链表,记录了它所直接连通的其它顶点。没有浪费内存空间,但不是很直观。

A B C D
B A D
C A E
D A B
E C

3、图的遍历

深度优先Depth First Search):从初始查找顶点开始,访问它的第一个邻接顶点,然后再查找这个邻接顶点的邻接顶点,直到所有的顶点都查找到。这是一个递归的过程。

  1. 先访问顶点V1,并标记为已遍历。
  2. 再访问顶点V1的第一个邻接顶点V2。
  3. 如果V2存在,且未被遍历,则对V2进行DFS,否则就继续遍历V1的下一个邻接顶点。

广度优先Broad First Search):从初始查找顶点开始,依次查找它的所有邻接顶点,然后再查找初始查找顶点的邻接顶点的邻接顶点。需要通过一个队列来记录顶点查找的次序。

  1. 先访问顶点V1,并标记为已遍历。
  2. 将顶点V1入队列。
  3. 当队列非空时,继续。
  4. 获取队列的头节点,并从队列中移除,然后查找头节点的邻接顶点V2。
    1. 如果V2存在,则遍历它,并标记为已遍历。
    2. 将该顶点入队列。
    3. 然后查找V1的下一个邻接顶点V3。
  5. 重复执行步骤4

4、示例

二维数组(邻接矩阵)

class Graph<T> {
   

    private T[] vertexArray;

    private final int vertexCount;

    private int[][] edgeArray;

    private int edgeCount;

    private static final int EDGE_FLAG = 1;

    public Graph(T[] vertexArray) {
   
        this.vertexArray = vertexArray;
        this.vertexCount = vertexArray.length;
        this.edgeArray = new int[vertexCount][vertexCount];
        this.edgeCount = 0;
    }

    public void setEdge(T vertex1, T vertex2) {
   
        int x = findIndex(vertex1);
        int y = findIndex(vertex2);
        edgeArray[x][y] = EDGE_FLAG;
        edgeArray[y][x] = EDGE_FLAG;
        this.edgeCount++;
    }

    private int findIndex(T vertex) {
   
        for (int i = 0; i < vertexCount; i++) {
   
            if (vertexArray[i].equals(vertex)) {
   
                return i;
            }
        }
        return -1;
    }

    public int getEdgeCount() {
   
        return this.edgeCount;
    }

    public void printGraph() {
   
        System.out.print("  ");
        for (int i = 0; i < vertexCount; i++) {
   
            System.out.print(vertexArray[i] + " ");
        }
        System.out.println();

        for (int j = 0; j < vertexCount; j++) {
   
            System.out.print(vertexArray[j] + " ");
            for (int k = 0; k < vertexCount; k++) {
   
                System.out.print(edgeArray[j][k] + " ");
            }
            System.out.println();
        }
    }

    public void dfs() {
   
        boolean[] searchArray = new boolean[vertexCount];
        for (int i = 0; i < vertexCount; ) {
   
            if (!searchArray[i
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值