-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
6 changed files
with
275 additions
and
7 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
import { GraphStructure } from "./interfaces" | ||
|
||
export class Graph<K> extends GraphStructure<K, K> { | ||
addEdge(v1: K, v2: K) { | ||
const list = this.map.get(v1) | ||
if (list) { | ||
list.push(v2) | ||
const edge = this.map.get(v2) | ||
if (edge?.includes(v1)) throw new Error('Edge already present') | ||
else if (edge) edge.push(v1) | ||
else this.map.set(v2, [v1]) | ||
} else throw new Error('First vertex not found') | ||
return this | ||
} | ||
|
||
removeEdge(v1: K, v2: K) { | ||
const list = this.map.get(v1) | ||
if (list) { | ||
const index = list.indexOf(v2) | ||
if (index != -1) list.splice(index, 1) | ||
else throw new Error('Edge not found') | ||
|
||
const edge = this.map.get(v2) | ||
if (edge) { | ||
const index = edge.indexOf(v1) | ||
if (index != -1) edge.splice(index, 1) | ||
} | ||
} else throw new Error('Vertex not found') | ||
return this | ||
} | ||
|
||
removeVertex(vertex: K) { | ||
if (this.map.delete(vertex)) { | ||
for (const list of this.map.values()) { | ||
const index = list.indexOf(vertex) | ||
if (index != -1) list.splice(index, 1) | ||
} | ||
} else throw new Error('Vertex not found') | ||
return this | ||
} | ||
|
||
getEdges(vertex: K) { | ||
const list = this.map.get(vertex) | ||
if (!list) throw new Error('Vertex not found') | ||
return [...list] as readonly K[] | ||
} | ||
|
||
isAdjacent(v1: K, v2: K) { | ||
const list = this.map.get(v1) | ||
if (!list) throw new Error('First vertex not found') | ||
return list.includes(v2) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
export class TreeLeaf<T> { | ||
leaves: TreeLeaf<T>[] = [] | ||
|
||
constructor(public data: T, leaves?: TreeLeaf<T>[]) { | ||
this.leaves = leaves ?? [] | ||
} | ||
|
||
push(data: T, ...datas: T[]) { | ||
let leaf = new TreeLeaf(data, []) | ||
this.leaves.push(leaf) | ||
for (const d of datas) { | ||
leaf = new TreeLeaf(d, []) | ||
this.leaves.push(leaf) | ||
} | ||
return leaf | ||
} | ||
|
||
get children() { | ||
return this.leaves.map(l => l.data) | ||
} | ||
|
||
get height(): number { | ||
return this.leaves.length > 0 ? 1 + Math.max(0, ...this.leaves.map(c => c.height)) : 0 | ||
} | ||
} | ||
|
||
const preOrder = <T>(node: TreeLeaf<T>, list: T[]) => { // root -> leaves | ||
list.push(node.data) | ||
for (const child of node.leaves) preOrder(child, list) | ||
} | ||
|
||
const postOrder = <T>(node: TreeLeaf<T>, list: T[]) => { // leaves -> root | ||
for (const child of node.leaves) postOrder(child, list) | ||
list.push(node.data) | ||
} | ||
|
||
const inOrder = <T>(node: TreeLeaf<T>, list: T[]) => { // first half -> root -> second half | ||
if (node.leaves.length == 0) list.push(node.data) | ||
else { | ||
const n = node.leaves.length, nd = Math.round(n / 2) | ||
for (let i = 0; i < nd; i++) { | ||
inOrder(node.leaves[i], list) | ||
} | ||
list.push(node.data) | ||
for (let i = nd; i < n; i++) { | ||
inOrder(node.leaves[i], list) | ||
} | ||
} | ||
} | ||
|
||
const heightOrder = <T>(node: TreeLeaf<T>, list: T[], first = true) => { // leaves for each height from top to bottom | ||
if (first) list.push(node.data) | ||
list.push(...node.leaves.map(l => l.data)) | ||
for (const child of node.leaves) heightOrder(child, list, false) | ||
} | ||
|
||
export class Tree<T> { | ||
root!: TreeLeaf<T> | ||
|
||
constructor(data: T) { | ||
this.root = new TreeLeaf(data) | ||
} | ||
|
||
traverse(order: "post" | "pre" | "in" | "height" = "pre") { | ||
const result: T[] = [] | ||
|
||
if (order == "pre") preOrder(this.root, result) | ||
else if (order == "post") postOrder(this.root, result) | ||
else if (order == "in") inOrder(this.root, result) | ||
else if (order == "height") heightOrder(this.root, result) | ||
|
||
return result | ||
} | ||
|
||
search(value: T) { | ||
const queue: TreeLeaf<T>[] = [this.root] | ||
while (queue.length > 0) { | ||
const node = queue.shift()! | ||
if (node.data == value) return node | ||
queue.push(...node.leaves) | ||
} | ||
return undefined | ||
} | ||
|
||
get depth() { | ||
return this.root.height | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
import { GraphStructure } from "./interfaces" | ||
|
||
type Weight = number | ||
type Edge<V> = [V, Weight] | ||
|
||
export class WeightedGraph<K> extends GraphStructure<K, Edge<K>> { | ||
addEdge(v1: K, v2: K, weight = 0) { | ||
const list = this.map.get(v1) | ||
if (list) { | ||
list.push([v2, weight]) | ||
const edge = this.map.get(v2) | ||
if (edge?.map(e => e[0])?.includes(v1)) throw new Error('Edge already present') | ||
else if (edge) edge.push([v1, weight]) | ||
else this.map.set(v2, [[v1, weight]]) | ||
} else throw new Error('First vertex not found') | ||
return this | ||
} | ||
|
||
removeEdge(v1: K, v2: K) { | ||
const list = this.map.get(v1) | ||
if (list) { | ||
const index = list.findIndex(e => e[0] == v2) | ||
if (index != -1) list.splice(index, 1) | ||
else throw new Error('Edge not found') | ||
|
||
const edge = this.map.get(v2) | ||
if (edge) { | ||
const index = edge.findIndex(e => e[0] == v1) | ||
if (index != -1) edge.splice(index, 1) | ||
} | ||
} else throw new Error('Vertex not found') | ||
return this | ||
} | ||
|
||
removeVertex(vertex: K) { | ||
if (this.map.delete(vertex)) { | ||
for (const list of this.map.values()) { | ||
const index = list.findIndex(e => e[0] == vertex) | ||
if (index != -1) list.splice(index, 1) | ||
} | ||
} else throw new Error('Vertex not found') | ||
return this | ||
} | ||
|
||
getEdges(vertex: K) { | ||
const list = this.map.get(vertex) | ||
if (!list) throw new Error('Vertex not found') | ||
return [...list.map(e => e[0])] as readonly K[] | ||
} | ||
|
||
getWeight(v1: K, v2: K, ...vn: K[]) { | ||
const list = this.map.get(v1) | ||
if (!list) throw new Error('First vertex not found') | ||
const edge = list.find(e => e[0] == v2) | ||
if (!edge) throw new Error('Second vertex not found') | ||
let weight = edge[1] | ||
if (vn.length) weight += this.getWeight(v2, vn[0], ...vn.slice(1)) | ||
return weight | ||
} | ||
|
||
isAdjacent(v1: K, v2: K) { | ||
const list = this.map.get(v1) | ||
if (!list) throw new Error('First vertex not found') | ||
return list.map(e => e[0]).includes(v2) | ||
} | ||
} |