使用LinkedList手撕图的邻接表

主要是学习图的邻接表的核心结构等等,话不多说直接上代码:

java 复制代码
import java.util.LinkedList;

public class GrapAdj {
    private int n ; // 表示图中顶点的数量。
    private LinkedList<Integer>[] adj;

    public GrapAdj(int n){
        this.n = n;
        adj = new LinkedList[n + 1];
    }

    private void init(){
        for (int i = 1;i <= n; i++){
            adj[i] = new LinkedList<>();
        }
    }
    public void add(int v1,int v2){
        adj[v1].add(v2);
    }

    public void print(){
        for (int v= 1; v <= n;v++){
            System.out.println(v+"->");
            for (int x: adj[v]){
                System.out.println(x+"->");
            }
            System.out.println(0);
        }
    }

    public static void main(String[] args) {
        GrapAdj graph = new GrapAdj(5);
        graph.init();
        graph.add(1, 2);
        graph.add(1, 3);
        graph.add(2, 4);
        graph.add(3, 4);
        graph.add(4, 5);
        graph.print();
    }
}

下面是基于数据结构方面的分析

在数据结构方面,使用邻接表来表示图是一种常用的图表示方法,特别适用于稀疏图(即边数远小于节点数平方的图)。以下是对邻接表数据结构的详细分析:

数据结构组成

1. 顶点数组:

private int n :表示图中顶点的数量。这个变量用于记录图的大小,方便在初始化和遍历时使用。
private LinkedList<Integer> adj :这是一个数组,每个元素是一个 `LinkedList<Integer>。数组的索引对应图中的顶点编号,数组的元素是存储与该顶点相邻的顶点列表的链表。

索引:数组的索引从1到 `n`,对应图中的顶点编号。使用 `n + 1` 的数组大小是为了方便使用从1开始的顶点编号。

链表:每个链表存储与对应顶点直接相连的所有顶点的编号。链表的动态特性使得添加和删除边的操作非常高效。

2,初始化过程

初始化数组:

adj = new LinkedListn + 1 ;:创建一个大小为 `n + 1` 的数组,每个元素初始化为 `null`。

init()` 方法遍历数组,为每个索引位置创建一个新的 LinkedList<Integer> 。这一步确保每个顶点都有一个空的邻接列表,准备用于添加邻接顶点。

(1) 添加边的过程

add(int v1, int v2) 方法:

将顶点 `v2` 添加到顶点 `v1` 的邻接列表中,即 `adjv1.add(v2);。

这里假设图是有向图。如果图是无向图,还需要添加 `adjv2.add(v1);`,以表示双向连接。

(2)打印图的过程

print() 方法:

遍历每个顶点 `v`,打印其编号和箭头 `v+"->"`。

遍历顶点 `v` 的邻接列表,打印每个邻接顶点的编号和箭头 `x+"->"`。

每个顶点的邻接列表打印完毕后,打印一个0作为结束符,表示该顶点的邻接列表结束。

(3) 邻接表数据结构的优势

空间效率:邻接表只需要存储实际存在的边,对于稀疏图来说,相比于邻接矩阵,邻接表可以节省大量的空间。

动态操作:由于使用了链表,添加和删除边的操作非常高效,不需要像邻接矩阵那样重新分配整个矩阵。

灵活性:可以方便地处理图的动态变化,如增加或删除顶点和边,动态操作效率很高。

数据结构的局限性

查找边的操作 :在邻接表中查找是否存在一条边需要遍历链表,时间复杂度为 O(deg(v)),其中 deg(v) 是顶点 v 的度。对于稠密图,这可能不如邻接矩阵高效。
不支持权重:基本的邻接表不支持边的权重信息。如果需要处理加权图,需要对数据结构进行扩展,例如使用 `LinkedList<Pair<Integer, Integer>>` 来存储邻接顶点及其权重。

通过使用邻接表数据结构,能够有效地表示了图的结构,并且拥有了基本的图操作功能。邻接表是图论中常用的数据结构之一,特别适用于处理稀疏图和动态图。

下面是对于代码的详细分析

1,类定义和成员变量

  • private int n; :
    • 这个变量表示图中顶点的数量。它用于初始化和管理图的大小。
  • private LinkedList<Integer>[] adj; :
    • 这是一个数组,每个元素是一个 LinkedList<Integer>。数组的索引对应图中的顶点编号,数组的元素是存储与该顶点相邻的顶点列表的链表。
    • 使用 LinkedList 是因为链表可以方便地进行插入和删除操作,适合动态地添加和删除边。

2,构造函数

  • public GrapAdj(int n) :
    • 构造函数接受一个参数 n,表示图中顶点的数量。
    • 初始化 this.n 为 n。
    • 初始化 adj 数组的大小为 n + 1。这里使用 n + 1 是为了方便使用从1开始的顶点编号(例如,顶点编号从1到n)。

4,初始化方法

  • private void init() :
    • 这个方法用于初始化邻接表。
    • 使用一个 for 循环遍历从1到 n 的每个顶点。
    • 对于每个顶点 i,初始化 adj[i] 为一个新的 LinkedList<Integer>。这样,每个顶点的邻接列表都是一个空的链表,准备用于添加邻接顶点。

5,添加边的方法

  • public void add(int v1, int v2) :
    • 这个方法用于向图中添加一条从顶点 v1 到顶点 v2 的边。
    • 使用 adj[v1].add(v2) 将顶点 v2 添加到顶点 v1 的邻接列表中。
    • 这里假设图是有向图,如果图是无向图,还需要添加 adj[v2].add(v1)。

6,打印图的方法

  • public void print() :
    • 这个方法用于打印图的邻接表。
    • 使用一个 for 循环遍历从1到 n 的每个顶点 v。
    • 打印顶点 v 的编号和箭头 v+"->"。
    • 使用一个增强型 for 循环遍历顶点 v 的邻接列表中的每个顶点 x,并打印 x+"->"。
    • 每个顶点的邻接列表打印完毕后,打印一个0作为结束符,表示该顶点的邻接列表结束。

7,主方法(用于测试)

  • public static void main(String[] args) :
    • 创建一个 GrapAdj 对象 graph,顶点数量为5。
    • 调用 init() 方法初始化邻接表。
    • 使用 add() 方法添加几条边,构建一个简单的图。
    • 调用 print() 方法打印图的邻接表,展示图的结构。

8,难点分析

  • 数组初始化 :
    • adj = new LinkedList[n + 1]; 这行代码初始化了一个数组,但数组的每个元素都是 null。因此,需要在 init() 方法中为每个元素创建一个 LinkedList。
  • 邻接表的动态管理 :
    • 使用 LinkedList 作为邻接列表的好处是可以动态地添加和删除边,但需要确保在添加边之前邻接列表已经被正确初始化。
相关推荐
爱读书的小胖4 分钟前
LeetCode 122:买卖股票的最佳时机 II(C)解题分析
算法
结局无敌5 分钟前
React Native for OpenHarmony 实战:三方库 react-native-modal-dialog 的鸿蒙化适配指南
深度学习·算法·react native·react.js·harmonyos
OPEN-F35 分钟前
ROS2系列教程:上位机建图与导航(原理综合)
算法·机器人
weixin_3077791335 分钟前
C++代码实现MATLAB中的fitrtree函数功能
开发语言·c++·算法·matlab
tomwang03221 小时前
路径优化建模、优化算法分类及工程化小结
算法·数学建模·分类
小羊没烦恼!1 小时前
Ajax与JSON的一些总结
android·java·前端·数据库·mysql·算法·okhttp
2501_926978331 小时前
人机通信协议--人和机器之间的交互想象
人工智能·经验分享·算法·ai写作
行者全栈架构师1 小时前
【鸿蒙心迹】互动卡片全链路——把核心功能放到桌面(FormKit 实战)(HarmonyOS 7.x)
前端·算法·架构
无定义_1 小时前
10.11日常训练
算法
Code_Solitude1 小时前
c语言:关于qsoet函数知识点
c语言·数据结构·算法