Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,4 @@ The examples are results of following the following course available on Udemy: h
- [Binary Heap](./src/binary-heap) (example MIN implementation)
- [AVL Tree](./src/avl-tree)
- [Memoization](./src/memoization/)
- [Adjacency List Graph](./src/graph/)
81 changes: 81 additions & 0 deletions src/graph/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
# AdjacencyListGraph

The `AdjacencyListGraph` class is a TypeScript implementation of a graph data structure using an adjacency list. This implementation supports adding vertices and edges, retrieving all vertices, retrieving all edges, and getting the neighbors of a specific vertex.

## Features

- Add vertices to the graph.
- Add edges between vertices.
- Retrieve all vertices in the graph.
- Retrieve all edges in the graph.
- Get the neighbors of a specific vertex.
- Handles errors for invalid operations, such as adding edges for non-existent vertices or retrieving neighbors of a non-existent vertex.

## Usage

Here is an example of how to use the `AdjacencyListGraph` class:

```typescript
import { AdjacencyListGraph } from './index'

const graph = new AdjacencyListGraph()

// Add vertices
graph.addVertex('A')
graph.addVertex('B')
graph.addVertex('C')

// Add edges
graph.addEdge('A', 'B')
graph.addEdge('A', 'C')

// Retrieve vertices
console.log(graph.getVertices()) // Output: ['A', 'B', 'C']

// Retrieve edges
console.log(graph.getEdges()) // Output: [['A', 'B'], ['A', 'C']]

// Get neighbors of a vertex
console.log(graph.getNeighbors('A')) // Output: ['B', 'C']
```

## API Reference

`addVertex(vertex: string): void`

Adds a vertex to the graph. If the vertex already exists, it will not be added again.

- **Parameters:**
- `vertex`: The name of the vertex to add.

`addEdge(vertex1: string, vertex2: string): void`

Adds an edge between two vertices in the graph. If either vertex does not exist, an error will be thrown.

- **Parameters:**
- `vertex1`: The first vertex of the edge.
- `vertex2`: The second vertex of the edge.
- **Throws:**
- `Error`: If one or both vertices do not exist.

`getVertices(): string[]`

Retrieves all vertices in the graph.

- **Returns:** An array of vertex names.

`getEdges(): [string, string][]`

Retrieves all edges in the graph. Each edge is represented as a tuple of two vertices.

- **\*Returns:** An array of edges.

`getNeighbors(vertex: string): string[]`

Retrieves the neighbors of a specific vertex.

- **Parameters:**
- `vertex`: The name of the vertex.
- **Returns:** An array of neighbors of the specified vertex.
- **Throws:**
- `Error`: If the vertex does not exist.
54 changes: 54 additions & 0 deletions src/graph/index.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import { describe, it, expect } from 'bun:test'
import { AdjacencyListGraph } from './index'

describe('AdjacencyListGraph', () => {
it('should initialize an empty graph', () => {
const graph = new AdjacencyListGraph()
expect(graph.getVertices()).toEqual([])
expect(graph.getEdges()).toEqual([])
})

it('should add vertices to the graph', () => {
const graph = new AdjacencyListGraph()
graph.addVertex('A')
graph.addVertex('B')
expect(graph.getVertices()).toEqual(['A', 'B'])
})

it('should add edges to the graph', () => {
const graph = new AdjacencyListGraph()
graph.addVertex('A')
graph.addVertex('B')
graph.addEdge('A', 'B')
expect(graph.getEdges()).toEqual([['A', 'B']])
})

it('should not add duplicate vertices', () => {
const graph = new AdjacencyListGraph()
graph.addVertex('A')
graph.addVertex('A')
expect(graph.getVertices()).toEqual(['A'])
})

it('should handle edges for non-existent vertices gracefully', () => {
const graph = new AdjacencyListGraph()
expect(() => graph.addEdge('A', 'B')).toThrowError(
'One or both vertices do not exist'
)
})

it('should retrieve neighbors of a vertex', () => {
const graph = new AdjacencyListGraph()
graph.addVertex('A')
graph.addVertex('B')
graph.addVertex('C')
graph.addEdge('A', 'B')
graph.addEdge('A', 'C')
expect(graph.getNeighbors('A')).toEqual(['B', 'C'])
})

it('should throw an error when retrieving neighbors of a non-existent vertex', () => {
const graph = new AdjacencyListGraph()
expect(() => graph.getNeighbors('A')).toThrowError('Vertex does not exist')
})
})
110 changes: 110 additions & 0 deletions src/graph/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
/**
* Graph data structure implementation using an adjacency list.
* This implementation supports adding vertices and edges, retrieving all vertices,
* retrieving all edges, and getting the neighbors of a specific vertex.
*
* @class AdjacencyListGraph
* @description A class representing a graph using an adjacency list.
* @example
* ```typescript
* const graph = new AdjacencyListGraph()
* graph.addVertex('A')
* graph.addVertex('B')
* graph.addEdge('A', 'B')
* console.log(graph.getVertices()) // ['A', 'B']
* console.log(graph.getEdges()) // [['A', 'B']]
* ```
*/
export class AdjacencyListGraph {
private adjacencyList: Map<string, string[]>

constructor() {
this.adjacencyList = new Map()
}

/**
* Adds a vertex to the graph.
* If the vertex already exists, it will not be added again.
* @param {string} vertex The vertex to add to the graph.
*/
addVertex(vertex: string): void {
if (!this.adjacencyList.has(vertex)) {
this.adjacencyList.set(vertex, [])
}
}

/**
* Adds an edge between two vertices in the graph.
* If either vertex does not exist, an error will be thrown.
* If the edge already exists, it will not be added again.
* @param {string} vertex1 The first vertex of the edge.
* @param {string} vertex2 The second vertex of the edge.
* @throws Error if either vertex does not exist.
* @example
* ```typescript
* graph.addEdge('A', 'B')
* console.log(graph.getEdges()) // [['A', 'B']]
* ```
*/
addEdge(vertex1: string, vertex2: string): void {
if (!this.adjacencyList.has(vertex1) || !this.adjacencyList.has(vertex2)) {
throw new Error('One or both vertices do not exist')
}
this.adjacencyList.get(vertex1)!.push(vertex2)
this.adjacencyList.get(vertex2)!.push(vertex1) // Assuming an undirected graph
}

/**
* Retrieves all vertices in the graph.
* @returns An array of vertices in the graph.
* @example
* ```typescript
* console.log(graph.getVertices()) // ['A', 'B']
* ```
*/
getVertices(): string[] {
return Array.from(this.adjacencyList.keys())
}

/**
* Retrieves all edges in the graph.
* Each edge is represented as a tuple of two vertices.
* @returns {[string, string][]} An array of edges in the graph.
* @example
* ```typescript
* console.log(graph.getEdges()) // [['A', 'B']]
* ```
*/
getEdges(): [string, string][] {
const edges: [string, string][] = []
const visited = new Set<string>()

for (const [vertex, neighbors] of this.adjacencyList.entries()) {
for (const neighbor of neighbors) {
if (!visited.has(`${neighbor}-${vertex}`)) {
edges.push([vertex, neighbor])
}
}
visited.add(`${vertex}-${neighbors}`)
}

return edges
}

/**
* Retrieves the neighbors of a specific vertex.
* @param {string} vertex The vertex whose neighbors are to be retrieved.
* @returns {string[]} An array of neighbors of the specified vertex.
* @throws Error if the vertex does not exist.
* @example
* ```typescript
* console.log(graph.getNeighbors('A')) // ['B']
* ```
*/
getNeighbors(vertex: string): string[] {
if (!this.adjacencyList.has(vertex)) {
throw new Error('Vertex does not exist')
}
return this.adjacencyList.get(vertex)!
}
}
1 change: 1 addition & 0 deletions src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@ export * from './binary-tree'
export * from './binary-heap'
export * from './avl-tree'
export * from './memoization'
export * from './graph'