{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Graph Implementation Using Adjacency Lists\n", "for an undirected graph. \n", "© Joe James, 2019." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Vertex Class\n", "The Vertex class has a constructor that sets the name of the vertex (in our example, just a letter), and creates a new empty set to store neighbors.\n", "\n", "The add_neighbor method adds the name of a neighboring vertex to the neighbors set. This set automatically eliminates duplicates." ] }, { "cell_type": "code", "execution_count": 25, "metadata": {}, "outputs": [], "source": [ "class Vertex:\n", " def __init__(self, n):\n", " self.name = n\n", " self.neighbors = set()\n", " \n", " def add_neighbor(self, v):\n", " self.neighbors.add(v)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Graph Class\n", "The Graph class uses a dictionary to store vertices in the format, vertex_name:vertex_object.\n", " \n", "Adding a new vertex to the graph, we first check if the object passed in is a vertex object, then we check if it already exists in the graph. If both checks pass, then we add the vertex to the graph's vertices dictionary.\n", "\n", "When adding an edge, we receive two vertex names, we first check if both vertex names are valid, then we add each to the other's neighbors set.\n", "\n", "To print the graph, we iterate through the vertices, and print each vertex name (the key) followed by its sorted neighbors list." ] }, { "cell_type": "code", "execution_count": 26, "metadata": {}, "outputs": [], "source": [ "class Graph:\n", " vertices = {}\n", " \n", " def add_vertex(self, vertex):\n", " if isinstance(vertex, Vertex) and vertex.name not in self.vertices:\n", " self.vertices[vertex.name] = vertex\n", " return True\n", " else:\n", " return False\n", " \n", " def add_edge(self, u, v):\n", " if u in self.vertices and v in self.vertices:\n", " self.vertices[u].add_neighbor(v)\n", " self.vertices[v].add_neighbor(u)\n", " return True\n", " else:\n", " return False\n", " \n", " def print_graph(self):\n", " for key in sorted(list(self.vertices.keys())):\n", " print(key, sorted(list(self.vertices[key].neighbors)))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Test Code\n", "Here we create a new Graph object. We create a new vertex named A. We add A to the graph. Then we add new vertex B to the graph. Then we iterate from A to K and add a bunch of vertices to the graph. Since the add_vertex method checks for duplicates, A and B are not added twice." ] }, { "cell_type": "code", "execution_count": 27, "metadata": {}, "outputs": [], "source": [ "g = Graph()\n", "a = Vertex('A')\n", "g.add_vertex(a)\n", "g.add_vertex(Vertex('B'))\n", "for i in range(ord('A'), ord('K')):\n", " g.add_vertex(Vertex(chr(i)))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "An edge consists of two vertex names. Here we iterate through a list of edges and add each to the graph. \n", "\n", "This print_graph method doesn't give a very good visualization of the graph, but it does show the neighbors for each vertex." ] }, { "cell_type": "code", "execution_count": 28, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "A ['B', 'E']\n", "B ['A', 'F']\n", "C ['G']\n", "D ['E', 'H']\n", "E ['A', 'D', 'H']\n", "F ['B', 'G', 'I', 'J']\n", "G ['C', 'F', 'J']\n", "H ['D', 'E', 'I']\n", "I ['F', 'H']\n", "J ['F', 'G']\n" ] } ], "source": [ "edges = ['AB', 'AE', 'BF', 'CG', 'DE', 'DH', 'EH', 'FG', 'FI', 'FJ', 'GJ', 'HI']\n", "for edge in edges:\n", " g.add_edge(edge[0], edge[1])\n", "\n", "g.print_graph()" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.7.0" } }, "nbformat": 4, "nbformat_minor": 2 }