UNPKG

quick-find-union-find

Version:

Quick Find Union Find using ES next

155 lines (143 loc) 5.11 kB
/** * QuickFindUF is based on * http://algs4.cs.princeton.edu/15uf/QuickFindUF.java.html * * The QuickFindUF class represents a `union–find data type` * (also known as the `disjoint-sets data type`). * It supports the `union` and `find` operations, * along with a `connected` operation for determining whether * two sites are in the same component and a `count` operation that * returns the total number of components. * * The union–find data type models connectivity among a set of `n` * sites, named 0 through `n`–1. * The `is-connected-to` relation must be an * `equivalence relation`: * * - `Reflexive`: `p` is connected to `p`. * - `Symmetric`: If `p` is connected to `q`, * then `q` is connected to `p`. * - `Transitive`: If `p` is connected to `q` * and `q` is connected to `r`, then * `p` is connected to `r`. * * An equivalence relation partitions the sites into * `equivalence classes` (or `components`). In this case, * two sites are in the same component if and only if they are connected. * Both sites and components are identified with integers between 0 and * `n`–1. * Initially, there are `n` components, with each site in its * own component. The `component identifier` of a component * (also known as the `root`, `canonical element`, `leader`, * or `set representative`) is one of the sites in the component: * two sites have the same component identifier if and only if they are * in the same component. * * - `union`(`p`, `q`) adds a * connection between the two sites `p` and `q`. * If `p` and `q` are in different components, * then it replaces * these two components with a new component that is the union of * the two. * - `find`(`p`) returns the component * identifier of the component containing `p`. * - `connected`(`p`, `q`) * returns true if both `p` and `q` * are in the same component, and false otherwise. * - `count`() returns the number of components. * * * The component identifier of a component can change * only when the component itself changes during a call to * `union`—it cannot change during a call * to `find`, `connected`, or `count`. * * This implementation uses quick find. * Initializing a data structure with `n` sites takes linear time. * Afterwards, the `find`, `connected`, and `count` * operations take constant time but the `union` operation * takes linear time. * * For additional documentation, see <a href="http://algs4.cs.princeton.edu/15uf">Section 1.5</a> of * <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne. */ 'use strict'; class QuickFindUF { /** * Initializes an empty union–find data structure with `n` sites * `0 through `n-1`. Each site is initially in its own * component. * * @param n the number of sites * @throws RangeError: Invalid array length if `n < 0` */ constructor(n) { this._id = new Array(n); // id[i] = component identifier of i this._count = n; // number of components for (let i = 0; i < n; i++) { this._id[i] = i; } } /** * Returns the number of components. * * @return the number of components (between `1` and `n`) */ get count() { return this._count; } /** * Returns the component identifier for the component containing site `p`. * * @param p the integer representing one site * @return the component identifier for the component containing site `p` * @throws Index Out Of Bounds Exception unless `0 <= p < n` */ find(p) { this.validate(p); return this._id[p]; } // validate that p is a valid index validate(p) { let n = this._id.length; if (p < 0 || p >= n) { throw `Index Out Of Bounds. (index ${p} is not between 0 and ${n-1})`; } } /** * Returns true if the the two sites are in the same component. * * @param p the integer representing one site * @param q the integer representing the other site * @return `true` if the two sites `p` and `q` are in the same component; * `false` otherwise * @throws Index Out Of Bounds Exception unless * both `0 <= p < n` and `0 <= q < n` */ connected(p, q) { this.validate(p); this.validate(q); return this._id[p] == this._id[q]; } /** * Merges the component containing site `p` with the * the component containing site `q`. * * @param p the integer representing one site * @param q the integer representing the other site * @throws IndexOutOfBoundsException unless * both `0 <= p < n` and `0 <= q < n` */ union(p, q) { this.validate(p); this.validate(q); let pID = this._id[p]; // needed for correctness let qID = this._id[q]; // to reduce the number of array accesses // p and q are already in the same component if (pID == qID) return; for (let i = 0; i < this._id.length; i++) if (this._id[i] == pID) this._id[i] = qID; this._count--; } } module.exports = QuickFindUF;