When modeling a network, route optimization, or social graph, the adjacency list stands as one of the most flexible and memory-efficient data structures. Unlike an adjacency matrix, which allocates space for every possible connection, this structure only stores existing links, making it ideal for sparse graphs. A common point of confusion for developers and students alike is how to store weights in adjacency list, turning a simple list of neighbors into a powerful map of costs, distances, or capacities.

Understanding the Core Concept

At its simplest, an adjacency list is an array of lists, where each index represents a vertex and the list at that index contains its neighbors. To store weights in adjacency list, you stop keeping a raw list of integers and instead keep a list of pairs. Each pair binds a neighboring vertex to the specific value representing the edge connecting them, such as a distance of 5 or a cost of 10. This transformation is the fundamental shift required to handle weighted graphs.
The Pair Abstraction

The most universal approach is to define a structure or tuple containing two elements: the target node and the numeric weight. In languages like C++ or Java, this might be a custom `Edge` class with fields for `vertex` and `cost`. In Python, a tuple `(neighbor, weight)` is often the cleanest solution, as it is immutable and lightweight. By iterating through these pairs, algorithms can easily access not just who a node is connected to, but how "expensive" that connection is.
Practical Implementation Strategies

How you store weights in adjacency list often depends on the specific use case and performance requirements. For dense graphs where lookups are frequent, an array of vectors allows for rapid iteration over neighbors. For sparse graphs where memory is tight, a hash map keyed by neighbor vertex can provide faster edge existence checks. The key is to ensure that the weight moves with the vertex reference, so the data remains cohesive during traversal.
Handling Directed vs. Undirected Graphs
Implementation details change slightly based on graph directionality. For a directed graph, you add the weight to the list of the source vertex pointing to the destination. For an undirected graph, you must add two entries: one for A to B and another for B to A, ensuring the weight value is consistent in both records. Forgetting this symmetry is a common bug that leads to incorrect path calculations in routing algorithms.

Algorithmic Efficiency
Storing weights correctly directly impacts the efficiency of graph algorithms like Dijkstra's or Bellman-Ford. These algorithms rely on the ability to quickly fetch the cost of traversing an edge. With a well-structured adjacency list, fetching the neighbors of a node is an O(1) operation, and iterating over the weighted edges is proportional to the number of connections, not the total nodes in the graph. This results in optimal O(V + E log V) complexity for priority queue-based searches.
Memory Optimization Tips

While generally efficient, storing weights can bloat memory if not managed. Using integer types instead of floats when precision allows, or employing compression techniques for large sparse matrices, can save significant space. When you store weights in adjacency list, profiling your memory usage ensures that the structure scales to massive datasets without degradation.


















