7.1. Implementation
This section describes how to implement a graph structure.
Types of Graphs
There are several types of graphs:
Can we represent undirected graphs using an implementation of directed graphs?
Let us create the class representing a directed edge under the package:
L1: inherits the interface.
L2-3: the source and target vertices are represented by unique IDs in int.
Let us the define the init() method, getters, and setters:
Let us override the compareTo() method that compares this edge to another edge by their weights:
L4: returns 1 if the weight of this edge is greater.
L5: returns -1 if the weight of the other edge is greater.
Let us create the class under the package:
L2: a list of edge lists where each dimension of the outer list indicates a target vertex and the inner list corresponds to the list of incoming edges to that target vertex.
L5: creates an empty edge list for each target vertex.
For example, a graph with 3 vertices 0, 1, and 2 and 3 edges 0 -> 1, 2 -> 1, and 0 -> 2, the incoming_edges is as follows:
Let us define setters for edges:
L2-4: retrieves the incoming edge list of target, and adds the new edge to the edge list.
L9-10: add edges to both directions.
Let us then define getters:
L6: uses the method that merges the list of edge lists into one list of edges.
L10: uses the and methods to find vertices with no incoming edges.
What is the worst-case complexity of the getVerticesWithNoIncomingEdges() method?
Let us define the getOutgoingEdges() method that returns the list of outgoing edges:
L1: returns a list of edge deque, where each dimension in the outer list represents the deque of outgoing edges for the corresponding source vertex.
L2: generates the list of empty edge deques.
What is the worst-case complexity of the getOutgoingEdges() method?