Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/ucxinstructor/dsa_package/llms.txt

Use this file to discover all available pages before exploring further.

Overview

The AdjacencyListGraph class represents an unweighted graph using an adjacency list. It stores each vertex and its list of adjacent vertices in a dictionary, making it space-efficient for sparse graphs.

Constructor

AdjacencyListGraph(directed=False, vertices=None)
directed
bool
default:"False"
Whether the graph is directed
vertices
list[str]
default:"None"
List of vertex labels to initialize the graph with
from dsa.graph import AdjacencyListGraph

# Create empty graph
g = AdjacencyListGraph()

# Create directed graph
g = AdjacencyListGraph(directed=True)

# Create with initial vertices
g = AdjacencyListGraph(vertices=['A', 'B', 'C', 'D'])

Attributes

is_directed
bool
Whether the graph is directed
is_weighted
bool
Whether the graph is weighted (always False)

Methods

add_vertex

Add a vertex to the graph.
add_vertex(label: str)
label
str
required
The vertex label to add
Raises: ValueError if the vertex already exists
g = AdjacencyListGraph()
g.add_vertex('A')
g.add_vertex('B')
g.add_vertex('C')

delete_vertex

Delete a vertex from the graph and remove all edges connected to it.
delete_vertex(label: str)
label
str
required
The vertex label to delete
g = AdjacencyListGraph(vertices=['A', 'B', 'C'])
g.add_edge('A', 'B')
g.delete_vertex('B')
print(g.vertices())  # ['A', 'C']

add_edge

Add an edge between two vertices.
add_edge(start_label: str, end_label: str, directed=None)
start_label
str
required
Starting vertex label
end_label
str
required
Ending vertex label
directed
bool
default:"None"
Override the graph’s default directed behavior. If None, uses self.is_directed
g = AdjacencyListGraph()

# Add undirected edge (creates A→B and B→A)
g.add_edge('A', 'B')

# Add directed edge (creates B→C only)
g.add_edge('B', 'C', directed=True)

# Vertices are auto-created if they don't exist
g.add_edge('D', 'E')

add_directed_edge

Add a directed edge from start to end.
add_directed_edge(start_label: str, end_label: str)
start_label
str
required
Starting vertex label
end_label
str
required
Ending vertex label
g = AdjacencyListGraph()
g.add_directed_edge('A', 'B')  # Only adds A→B

delete_edge

Delete an edge between two vertices.
delete_edge(start_label: str, end_label: str, directed=None)
start_label
str
required
Starting vertex label
end_label
str
required
Ending vertex label
directed
bool
default:"None"
Override the graph’s default directed behavior. If None, uses self.is_directed
Raises: KeyError if either vertex or the edge does not exist
g = AdjacencyListGraph()
g.add_edge('A', 'B')
g.delete_edge('A', 'B')

has_vertex

Check if a vertex exists in the graph.
has_vertex(label: str) -> bool
label
str
required
The vertex label to check
return
bool
True if the vertex exists, False otherwise
g = AdjacencyListGraph(vertices=['A', 'B'])
print(g.has_vertex('A'))  # True
print(g.has_vertex('C'))  # False

has_edge

Check if an edge exists between two vertices.
has_edge(start_label: str, end_label: str) -> bool
start_label
str
required
Starting vertex label
end_label
str
required
Ending vertex label
return
bool
True if an edge exists from start to end, False otherwise
Raises: KeyError if either vertex does not exist
g = AdjacencyListGraph()
g.add_edge('A', 'B')
print(g.has_edge('A', 'B'))  # True
print(g.has_edge('B', 'C'))  # Raises KeyError

vertices

Get a list of all vertex labels.
vertices() -> list
return
list[str]
List of all vertex labels in the graph
g = AdjacencyListGraph(vertices=['A', 'B', 'C'])
print(g.vertices())  # ['A', 'B', 'C']

edges

Get a list of all edges in the graph.
edges() -> list
return
list[tuple]
List of edges, each represented as a tuple (start, end)
g = AdjacencyListGraph()
g.add_edge('A', 'B')
g.add_edge('B', 'C')
print(g.edges())  # [('A', 'B'), ('B', 'A'), ('B', 'C'), ('C', 'B')]

undirected_edges

Get a list of edges without duplicates for undirected graphs.
undirected_edges() -> list
return
list[tuple]
List of unique edges, each represented as a tuple (start, end)
g = AdjacencyListGraph()
g.add_edge('A', 'B')
g.add_edge('B', 'C')
print(g.undirected_edges())  # [('A', 'B'), ('B', 'C')]

adjacents

Get a list of adjacent vertices for a given vertex.
adjacents(vertex: str) -> list
vertex
str
required
The vertex label
return
list[str]
List of adjacent vertex labels
g = AdjacencyListGraph()
g.add_edge('A', 'B')
g.add_edge('A', 'C')
print(g.adjacents('A'))  # ['B', 'C']

order

Get the number of vertices in the graph.
order() -> int
return
int
The number of vertices
g = AdjacencyListGraph(vertices=['A', 'B', 'C'])
print(g.order())  # 3

size

Get the number of edges in the graph.
size() -> int
return
int
The number of edges
g = AdjacencyListGraph()
g.add_edge('A', 'B')
g.add_edge('B', 'C')
print(g.size())  # 2 (undirected, so A-B and B-C counted once each)

to_dict

Convert the graph to a dictionary representation.
to_dict() -> dict
return
dict
Dictionary where keys are vertices and values are lists of adjacent vertices
g = AdjacencyListGraph()
g.add_edge('A', 'B')
g.add_edge('B', 'C')
print(g.to_dict())
# {'A': ['B'], 'B': ['A', 'C'], 'C': ['B']}

Class Methods

from_dict

Create a graph from a dictionary representation.
@classmethod
from_dict(data: dict, directed: bool = False) -> AdjacencyListGraph
data
dict
required
Dictionary where keys are vertices and values are lists of adjacent vertices
directed
bool
default:"False"
Whether the graph is directed
return
AdjacencyListGraph
A new graph instance
data = {
    'A': ['B', 'C'],
    'B': ['A', 'D'],
    'C': ['A'],
    'D': ['B']
}
g = AdjacencyListGraph.from_dict(data)

Special Methods

__getitem__

Get adjacent vertices using bracket notation.
g = AdjacencyListGraph()
g.add_edge('A', 'B')
g.add_edge('A', 'C')
print(g['A'])  # ['B', 'C']

__contains__

Check if a vertex exists using the in operator.
g = AdjacencyListGraph(vertices=['A', 'B'])
print('A' in g)  # True
print('C' in g)  # False

__len__

Get the number of vertices.
g = AdjacencyListGraph(vertices=['A', 'B', 'C'])
print(len(g))  # 3

Complete Examples

from dsa.graph import AdjacencyListGraph

# Create social network (sparse graph)
g = AdjacencyListGraph()

# Add friendships
g.add_edge('Alice', 'Bob')
g.add_edge('Alice', 'Charlie')
g.add_edge('Bob', 'David')
g.add_edge('Charlie', 'Eve')
g.add_edge('David', 'Eve')

print(f"Users: {g.vertices()}")
print(f"Friendships: {g.undirected_edges()}")

# Find friends
alice_friends = g.adjacents('Alice')
print(f"Alice's friends: {alice_friends}")

# Find mutual friends
def find_mutual_friends(graph, user1, user2):
    friends1 = set(graph.adjacents(user1))
    friends2 = set(graph.adjacents(user2))
    return list(friends1.intersection(friends2))

mutual = find_mutual_friends(g, 'Bob', 'Charlie')
print(f"Mutual friends of Bob and Charlie: {mutual}")

Performance

  • Space Complexity: O(V + E) where V = vertices, E = edges
  • Add Vertex: O(1)
  • Delete Vertex: O(V + E) - must remove vertex from all adjacency lists
  • Add Edge: O(1) average case
  • Delete Edge: O(degree(V)) - must search adjacency list
  • Has Edge: O(degree(V))
  • Get Adjacents: O(1)
  • Get All Edges: O(V + E)

Notes

  • Best for sparse graphs where E is much less than V²
  • More space-efficient than adjacency matrix for sparse graphs
  • Faster vertex addition than adjacency matrix
  • Slower edge lookup than adjacency matrix
  • Vertex labels must be strings
  • Adjacency lists are implemented using Python dictionaries and lists
  • For undirected graphs, edges are stored in both directions

Build docs developers (and LLMs) love