邻接表

邻接表将图表示为链表数组。数组的索引代表一个顶点,其链表中的每个元素代表与该顶点形成边的其他顶点。

例如,我们有下图所示的图。

A graph
无向图

我们可以将此图以链表的形式表示在计算机中,如下图所示。

Linked list representation of the graph
图的链表表示

在这里,0123 是顶点,每个顶点都与其所有相邻顶点形成一个链表。例如,顶点 1 有两个相邻顶点 0 和 2。因此,在上面的图中,1 与 0 和 2 相连。


邻接表的优点

  • 邻接表在存储方面非常高效,因为我们只需要存储边的值。对于具有数百万个顶点和边的稀疏图,这可以节省大量空间。
  • 它还有助于轻松找到与某个顶点相邻的所有顶点。

邻接表的缺点

  • 查找邻接表不像邻接矩阵那样快,因为必须先遍历所有连接的节点才能找到它们。

邻接表结构

最简单的邻接表需要一个节点数据结构来存储顶点,一个图数据结构来组织节点。

我们遵循图的基本定义——一组顶点和边 {V, E}。为了简单起见,我们使用无标签图而不是有标签图,也就是说,顶点由它们的索引 0, 1, 2, 3 来标识。

让我们深入了解这里涉及的数据结构。

struct node{
    int vertex;
    struct node* next;
};

struct Graph{
    int numVertices;
    struct node** adjLists;
};

不要被 struct node** adjLists 吓倒。

我们只是说我们想要存储一个指向 struct node* 的指针。这是因为我们不知道图会有多少个顶点,因此我们无法在编译时创建链表数组。


C++ 邻接表

结构是相同的,但通过使用 C++ 内置的列表 STL 数据结构,我们使结构更简洁。我们还能够抽象实现细节。

class Graph{
    int numVertices;
    list<int> *adjLists;
    
  public:
    Graph(int V);
    void addEdge(int src, int dest);
};

Java 邻接表

我们使用 Java 集合来存储链表数组。

class Graph{
    private int numVertices;
    private LinkedList<integer> adjLists[];
}

LinkedList 的类型取决于您想在其中存储什么数据。对于有标签的图,您可以存储字典而不是整数


Python 邻接表

Python 之所以如此受欢迎是有原因的。一个简单的顶点及其边的字典就足以表示图。您可以根据需要使顶点本身变得复杂。

graph = {'A': set(['B', 'C']),
         'B': set(['A', 'D', 'E']),
         'C': set(['A', 'F']),
         'D': set(['B']),
         'E': set(['B', 'F']),
         'F': set(['C', 'E'])}

Python、Java 和 C/C++ 中的邻接表代码

# Adjascency List representation in Python


class AdjNode:
    def __init__(self, value):
        self.vertex = value
        self.next = None


class Graph:
    def __init__(self, num):
        self.V = num
        self.graph = [None] * self.V

    # Add edges
    def add_edge(self, s, d):
        node = AdjNode(d)
        node.next = self.graph[s]
        self.graph[s] = node

        node = AdjNode(s)
        node.next = self.graph[d]
        self.graph[d] = node

    # Print the graph
    def print_agraph(self):
        for i in range(self.V):
            print("Vertex " + str(i) + ":", end="")
            temp = self.graph[i]
            while temp:
                print(" -> {}".format(temp.vertex), end="")
                temp = temp.next
            print(" \n")


if __name__ == "__main__":
    V = 5

    # Create graph and edges
    graph = Graph(V)
    graph.add_edge(0, 1)
    graph.add_edge(0, 2)
    graph.add_edge(0, 3)
    graph.add_edge(1, 2)

    graph.print_agraph()
// Adjascency List representation in Java

import java.util.*;

class Graph {

  // Add edge
  static void addEdge(ArrayList<ArrayList<Integer>> am, int s, int d) {
    am.get(s).add(d);
    am.get(d).add(s);
  }

  public static void main(String[] args) {

    // Create the graph
    int V = 5;
    ArrayList<ArrayList<Integer>> am = new ArrayList<ArrayList<Integer>>(V);

    for (int i = 0; i < V; i++)
      am.add(new ArrayList<Integer>());

    // Add edges
    addEdge(am, 0, 1);
    addEdge(am, 0, 2);
    addEdge(am, 0, 3);
    addEdge(am, 1, 2);

    printGraph(am);
  }

  // Print the graph
  static void printGraph(ArrayList<ArrayList<Integer>> am) {
    for (int i = 0; i < am.size(); i++) {
      System.out.println("\nVertex " + i + ":");
      for (int j = 0; j < am.get(i).size(); j++) {
        System.out.print(" -> " + am.get(i).get(j));
      }
      System.out.println();
    }
  }
}
// Adjascency List representation in C

#include <stdio.h>
#include <stdlib.h>

struct node {
  int vertex;
  struct node* next;
};
struct node* createNode(int);

struct Graph {
  int numVertices;
  struct node** adjLists;
};

// Create a node
struct node* createNode(int v) {
  struct node* newNode = malloc(sizeof(struct node));
  newNode->vertex = v;
  newNode->next = NULL;
  return newNode;
}

// Create a graph
struct Graph* createAGraph(int vertices) {
  struct Graph* graph = malloc(sizeof(struct Graph));
  graph->numVertices = vertices;

  graph->adjLists = malloc(vertices * sizeof(struct node*));

  int i;
  for (i = 0; i < vertices; i++)
    graph->adjLists[i] = NULL;

  return graph;
}

// Add edge
void addEdge(struct Graph* graph, int s, int d) {
  // Add edge from s to d
  struct node* newNode = createNode(d);
  newNode->next = graph->adjLists[s];
  graph->adjLists[s] = newNode;

  // Add edge from d to s
  newNode = createNode(s);
  newNode->next = graph->adjLists[d];
  graph->adjLists[d] = newNode;
}

// Print the graph
void printGraph(struct Graph* graph) {
  int v;
  for (v = 0; v < graph->numVertices; v++) {
    struct node* temp = graph->adjLists[v];
    printf("\n Vertex %d\n: ", v);
    while (temp) {
      printf("%d -> ", temp->vertex);
      temp = temp->next;
    }
    printf("\n");
  }
}

int main() {
  struct Graph* graph = createAGraph(4);
  addEdge(graph, 0, 1);
  addEdge(graph, 0, 2);
  addEdge(graph, 0, 3);
  addEdge(graph, 1, 2);

  printGraph(graph);

  return 0;
}
// Adjascency List representation in C++

#include <bits/stdc++.h>
using namespace std;

// Add edge
void addEdge(vector<int> adj[], int s, int d) {
  adj[s].push_back(d);
  adj[d].push_back(s);
}

// Print the graph
void printGraph(vector<int> adj[], int V) {
  for (int d = 0; d < V; ++d) {
    cout << "\n Vertex "
       << d << ":";
    for (auto x : adj[d])
      cout << "-> " << x;
    printf("\n");
  }
}

int main() {
  int V = 5;

  // Create a graph
  vector<int> adj[V];

  // Add edges
  addEdge(adj, 0, 1);
  addEdge(adj, 0, 2);
  addEdge(adj, 0, 3);
  addEdge(adj, 1, 2);
  printGraph(adj, V);
}

邻接表的应用

  • 对于边数较少的图,使用邻接表更快。
你觉得这篇文章有帮助吗?

我们的高级学习平台,凭借十多年的经验和数千条反馈创建。

以前所未有的方式学习和提高您的编程技能。

试用 Programiz PRO
  • 交互式课程
  • 证书
  • AI 帮助
  • 2000+ 挑战