图的深度优先搜索和广度优先搜索(邻接表) - Java实现

本文介绍了图的基本概念,包括顶点和边,以及图的两种表示方式:邻接矩阵和邻接表。重点讲解了邻接表在空间复杂度上的优势,并展示了如何创建邻接表。接着详细阐述了深度优先搜索(DFS)和广度优先搜索(BFS)的原理,并提供了Java实现。此外,还讨论了如何通过搜索记录路径并给出了测试结果。
摘要由CSDN通过智能技术生成

前言

1.什么是图?

图(graph)是由一些点(vertex)和这些点之间的连线(edge)所组成的;其中,点通常称为顶点(vertex),而点到点之间的连线通常称之为边或者弧(edge)。通常记为G=(V,E)。

大概张这样:
在这里插入图片描述

2.图如何表示?

图的表示有两种方式:

  • 邻接矩阵
    在这里插入图片描述
  • 邻接表
    在这里插入图片描述
    如何合理的使用这两种存储方式:
    设 顶点个数 V、边的个数 E
    那么从空间复杂度来说:邻接矩阵为O(V^2)、邻接表为O(V+E)
    从上面两个空间复杂度可以得出:
    对于边较少的图,明显采用邻接表较为合理。

3.如何创建一个邻接表

从上面的存储图可以得知,邻接表都是通过每个顶点,后面连接相关联的边信息。

Vertex.java

package com.kiger.graph;

/**
 * @ClassName Vertex
 * @Description 邻接表的顶点
 * 该类借鉴于一种Bag的数据结构
 * @Author zk_kiger
 * @Date 2019/11/12 22:30
 * @Version 1.0
 */

public class Vertex<T> {
   
    // 存储顶点数据
    private T data;
    // 下一条边信息
    private Edge first;
    // 该顶点连顶点数
    private int size;

    public Vertex() {
   }

    // 使用链表的头插法将边结点的信息插入顶点后面
    public void add(Edge item) {
   
        if (first == null) {
   
            first = item;
        } else {
   
            item.setNext(first);
            first = item;
        }
        size++;
    }

    // 获得下标为index的元素
    public int get(int index) {
   
        if (index >= size)
            return 0;
        Edge cur = first;
        while (index != 0) {
   
            cur = cur.getNext();
            --index;
        }
        return cur.getVertexIndex();
    }

    // 获取元素个数
    public int size() {
   
        return size;
    }

    // 判断是否为空
    public boolean isEmpty() {
   
        return (first == null);
    }

    public T getData() {
   
        return data;
    }

    public void setData(T data) {
   
        this.data = data;
    }

    public Edge getFirst() {
   
        return first;
    }

    public void setFirst(Edge first) {
   
        this.first = first;
    }

    @Override
    public String toString() {
   
        return "Vertex{" +
                "data=" + data +
                ", first=" + first +
                ", size=" + size +
                '}';
    }
}

Edge.java

package com.kiger.graph;

/**
 * @ClassName Edge
 * @Description 边结点
 * @Author zk_kiger
 * @Date 2019/11/12 22:32
 * @Version 1.0
 */

public class Edge {
   
    // 存在边的顶点下标
    private int vertexIndex;
    // 与顶点之间的权值
    private int weight;
    // 相连的下一个边
    private Edge next;

    public Edge() {
   }

    public Edge(int vertexIndex, Edge next) {
   
        this.vertexIndex = vertexIndex;
        this.next = next;
    }

    public Edge(int vertexIndex, int weight, Edge next) {
   
        this.vertexIndex = vertexIndex;
        this.weight = weight;
        this.next = next;
    }

    public int getVertexIn
  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 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、付费专栏及课程。

余额充值