implementation, much less efficient, that would make it unusable for, the huge
graphs that we see in practice. Another one is called the adjacency matrix
representation, Here we maintain a 2-dimensional v x v
array, It's a boolean array, 0-1 or true or
false. And for every edge v-w in the graph you
put true for row v in column w and for row w in column v.
So it's actually two representations of each edge in an adjacency matrix graph
representation. S, you can immediately, give a v and w
test whether there's an edge connecting v and w.
But that's one of the few operations that's efficient with this representation
and it's not very widely used, because for a huge graph, say with billions of, of,
vertices, You would have to have billion squared
number of entries in this array, which is going to be too big for your computer,
most likely. So this one actually isn't that widely
used. A, The one that is most widely used in
practice, and the one that we'll stick with, is called the adjacency list
representation. And that's where we keep a vertex index
array where, for every vertex, we maintain a list of the vertices that are adjacent
to that. So, for example, vertex four, Has, five,
is connected to five, six, and three, so its list has five, six, and three on it.
Now, on lower level representations we've talk about using linked width or array for
these, But actually in modern lingo with the
background that we'd built with algorisms what we're going to use is an abstract
data type. Our bag representation for this, which is
implemented with a linked list, but we don't have to think about it when we're
talking about graphs. we'd keep the vertices,
Names of, numbers of the vertices that are adjacent to each given vertex in a bag.
And we know that we can implement it, such that we can iterate through and time
proportional to the number of entries and the space taken is also proportional to
the number of entries,, And that's going to enable us to process
huge graphs. So here's the full implementation of the
Jason C, List graph representation.
So, the private instance variables that we're gonna use area the number of
vertices in the graph and then a array of nags of integers. so data the types and
set of values, set operations on those values, so those are the sets of values
for a graph. So here's the constructor of an empty
graph with V vertices. We keep the value v in the instance
variable as usual. Then we create.
An array of size V. And, of bags of integers.
And, store that array in, [inaudible] as the adjacency array of the graph.
Adjacency lists array. And then, as usual.
When we create, a, a, an array of objects. We go through.
And for every entry in the array, we initialize with, a, empty object.
So, after this code, we have the empty bags.
And so that's the constructor and then the other main engine and building graphs is
at edge and so, to add an edge between V and W, we add W to V's bag, and we add V
to W's bag. That's it.
And to iterate through all the vertices adjacent to a given vertex we simply
return the bag which is iterable. This is a nice example, illustrating the
power of abstraction. Because we did the low level processing,
for, that, that's involved, with our bag implementation in one of the early,
lectures. And now we, we get to use that to give a
very compact implementation, and efficient implementation, of the, graph data
structure. So it's really important to understand
this code. And you should make sure, that you study
it. So, as I mentioned in practice.
We're gonna be using this adjacency list representation.
Because all the algorithms are based on iterating over the vertices adjacent to V.
And this gets that done in time proportional to the number of such
vertices. So that's number one and number two, in
the real world, the graphs have lots of num, lots of vertices,
But a pretty small vertex degre. so number one, we can afford to represent, represent
the graph when we use the adjacency list representation because basically our space
is proportional to the number of edges. And number two, we can afford to process
it because our time taken is proportional to the number of edges that, that we
examined, with the ray of edges representation in the adjacency matrix
representation it gets very slow for some very simple task,
But, mostly, it's very slow for iterating over the vertices given to, adjacent to a
given vertex. Which is the key operation.
A list of edges, you have to go through all the edges to find the ones adjacent to
a given vertex. Adjacency matrix, you have to go through,
all possible, vertices adjacent and that's just going to be much too slow in
practice, Because adjacency list gets it done, in
time proportional degree of v, which is much smaller, for the huge graph that we
see in the real world. So that's our basic API.
Next, we'll look at some algorithms that are clients of this API.