|
@@ -0,0 +1,312 @@
|
|
|
+// Copyright (c) Jupyter Development Team.
|
|
|
+// Distributed under the terms of the Modified BSD License.
|
|
|
+
|
|
|
+/*-----------------------------------------------------------------------------
|
|
|
+| Copyright (c) 2014-2016, PhosphorJS Contributors
|
|
|
+|
|
|
|
+| Distributed under the terms of the BSD 3-Clause License.
|
|
|
+|
|
|
|
+| The full license is in the file LICENSE, distributed with this software.
|
|
|
+|----------------------------------------------------------------------------*/
|
|
|
+import {
|
|
|
+ ArrayIterator, IIterator, IterableOrArrayLike, each
|
|
|
+} from '@phosphor/algorithm';
|
|
|
+
|
|
|
+
|
|
|
+/**
|
|
|
+ * A generic vector data structure.
|
|
|
+ */
|
|
|
+export
|
|
|
+class Vector<T> {
|
|
|
+ /**
|
|
|
+ * Construct a new vector.
|
|
|
+ *
|
|
|
+ * @param values - The initial values for the vector.
|
|
|
+ */
|
|
|
+ constructor(values?: IterableOrArrayLike<T>) {
|
|
|
+ if (values) {
|
|
|
+ each(values, value => { this.pushBack(value); });
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Test whether the vector is empty.
|
|
|
+ *
|
|
|
+ * @returns `true` if the vector is empty, `false` otherwise.
|
|
|
+ *
|
|
|
+ * #### Notes
|
|
|
+ * This is a read-only property.
|
|
|
+ *
|
|
|
+ * #### Complexity
|
|
|
+ * Constant.
|
|
|
+ *
|
|
|
+ * #### Iterator Validity
|
|
|
+ * No changes.
|
|
|
+ */
|
|
|
+ get isEmpty(): boolean {
|
|
|
+ return this._array.length === 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Get the length of the vector.
|
|
|
+ *
|
|
|
+ * @return The number of values in the vector.
|
|
|
+ *
|
|
|
+ * #### Notes
|
|
|
+ * This is a read-only property.
|
|
|
+ *
|
|
|
+ * #### Complexity
|
|
|
+ * Constant.
|
|
|
+ *
|
|
|
+ * #### Iterator Validity
|
|
|
+ * No changes.
|
|
|
+ */
|
|
|
+ get length(): number {
|
|
|
+ return this._array.length;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Get the value at the front of the vector.
|
|
|
+ *
|
|
|
+ * @returns The value at the front of the vector, or `undefined` if
|
|
|
+ * the vector is empty.
|
|
|
+ *
|
|
|
+ * #### Notes
|
|
|
+ * This is a read-only property.
|
|
|
+ *
|
|
|
+ * #### Complexity
|
|
|
+ * Constant.
|
|
|
+ *
|
|
|
+ * #### Iterator Validity
|
|
|
+ * No changes.
|
|
|
+ */
|
|
|
+ get front(): T {
|
|
|
+ return this._array[0];
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Get the value at the back of the vector.
|
|
|
+ *
|
|
|
+ * @returns The value at the back of the vector, or `undefined` if
|
|
|
+ * the vector is empty.
|
|
|
+ *
|
|
|
+ * #### Notes
|
|
|
+ * This is a read-only property.
|
|
|
+ *
|
|
|
+ * #### Complexity
|
|
|
+ * Constant.
|
|
|
+ *
|
|
|
+ * #### Iterator Validity
|
|
|
+ * No changes.
|
|
|
+ */
|
|
|
+ get back(): T {
|
|
|
+ return this._array[this._array.length - 1];
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Create an iterator over the values in the vector.
|
|
|
+ *
|
|
|
+ * @returns A new iterator starting at the front of the vector.
|
|
|
+ *
|
|
|
+ * #### Complexity
|
|
|
+ * Constant.
|
|
|
+ *
|
|
|
+ * #### Iterator Validity
|
|
|
+ * No changes.
|
|
|
+ */
|
|
|
+ iter(): IIterator<T> {
|
|
|
+ return new ArrayIterator<T>(this._array, 0);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Get the value at the specified index.
|
|
|
+ *
|
|
|
+ * @param index - The positive integer index of interest.
|
|
|
+ *
|
|
|
+ * @returns The value at the specified index.
|
|
|
+ *
|
|
|
+ * #### Complexity
|
|
|
+ * Constant.
|
|
|
+ *
|
|
|
+ * #### Iterator Validity
|
|
|
+ * No changes.
|
|
|
+ *
|
|
|
+ * #### Undefined Behavior
|
|
|
+ * An `index` which is non-integral or out of range.
|
|
|
+ */
|
|
|
+ at(index: number): T {
|
|
|
+ return this._array[index];
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Set the value at the specified index.
|
|
|
+ *
|
|
|
+ * @param index - The positive integer index of interest.
|
|
|
+ *
|
|
|
+ * @param value - The value to set at the specified index.
|
|
|
+ *
|
|
|
+ * #### Complexity
|
|
|
+ * Constant.
|
|
|
+ *
|
|
|
+ * #### Iterator Validity
|
|
|
+ * No changes.
|
|
|
+ *
|
|
|
+ * #### Undefined Behavior
|
|
|
+ * An `index` which is non-integral or out of range.
|
|
|
+ */
|
|
|
+ set(index: number, value: T): void {
|
|
|
+ this._array[index] = value;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Add a value to the back of the vector.
|
|
|
+ *
|
|
|
+ * @param value - The value to add to the back of the vector.
|
|
|
+ *
|
|
|
+ * @returns The new length of the vector.
|
|
|
+ *
|
|
|
+ * #### Complexity
|
|
|
+ * Constant.
|
|
|
+ *
|
|
|
+ * #### Iterator Validity
|
|
|
+ * No changes.
|
|
|
+ */
|
|
|
+ pushBack(value: T): number {
|
|
|
+ return this._array.push(value);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Remove and return the value at the back of the vector.
|
|
|
+ *
|
|
|
+ * @returns The value at the back of the vector, or `undefined` if
|
|
|
+ * the vector is empty.
|
|
|
+ *
|
|
|
+ * #### Complexity
|
|
|
+ * Constant.
|
|
|
+ *
|
|
|
+ * #### Iterator Validity
|
|
|
+ * Iterators pointing at the removed value are invalidated.
|
|
|
+ */
|
|
|
+ popBack(): T {
|
|
|
+ return this._array.pop();
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Insert a value into the vector at a specific index.
|
|
|
+ *
|
|
|
+ * @param index - The index at which to insert the value.
|
|
|
+ *
|
|
|
+ * @param value - The value to set at the specified index.
|
|
|
+ *
|
|
|
+ * @returns The new length of the vector.
|
|
|
+ *
|
|
|
+ * #### Complexity
|
|
|
+ * Linear.
|
|
|
+ *
|
|
|
+ * #### Iterator Validity
|
|
|
+ * No changes.
|
|
|
+ *
|
|
|
+ * #### Notes
|
|
|
+ * The `index` will be clamped to the bounds of the vector.
|
|
|
+ *
|
|
|
+ * #### Undefined Behavior
|
|
|
+ * An `index` which is non-integral.
|
|
|
+ */
|
|
|
+ insert(index: number, value: T): number {
|
|
|
+ let array = this._array;
|
|
|
+ let n = array.length;
|
|
|
+ index = Math.max(0, Math.min(index, n));
|
|
|
+ for (let i = n; i > index; --i) {
|
|
|
+ array[i] = array[i - 1];
|
|
|
+ }
|
|
|
+ array[index] = value;
|
|
|
+ return n + 1;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Remove the first occurrence of a value from the vector.
|
|
|
+ *
|
|
|
+ * @param value - The value of interest.
|
|
|
+ *
|
|
|
+ * @returns The index of the removed value, or `-1` if the value
|
|
|
+ * is not contained in the vector.
|
|
|
+ *
|
|
|
+ * #### Complexity
|
|
|
+ * Linear.
|
|
|
+ *
|
|
|
+ * #### Iterator Validity
|
|
|
+ * Iterators pointing at the removed value and beyond are invalidated.
|
|
|
+ *
|
|
|
+ * #### Notes
|
|
|
+ * Comparison is performed using strict `===` equality.
|
|
|
+ */
|
|
|
+ remove(value: T): number {
|
|
|
+ let index = this._array.indexOf(value);
|
|
|
+ if (index !== -1) this.removeAt(index);
|
|
|
+ return index;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Remove and return the value at a specific index.
|
|
|
+ *
|
|
|
+ * @param index - The index of the value of interest.
|
|
|
+ *
|
|
|
+ * @returns The value at the specified index, or `undefined` if the
|
|
|
+ * index is out of range.
|
|
|
+ *
|
|
|
+ * #### Complexity
|
|
|
+ * Constant.
|
|
|
+ *
|
|
|
+ * #### Iterator Validity
|
|
|
+ * Iterators pointing at the removed value and beyond are invalidated.
|
|
|
+ *
|
|
|
+ * #### Undefined Behavior
|
|
|
+ * An `index` which is non-integral.
|
|
|
+ */
|
|
|
+ removeAt(index: number): T {
|
|
|
+ let array = this._array;
|
|
|
+ let n = array.length;
|
|
|
+ if (index < 0 || index >= n) {
|
|
|
+ return void 0;
|
|
|
+ }
|
|
|
+ let value = array[index];
|
|
|
+ for (let i = index + 1; i < n; ++i) {
|
|
|
+ array[i - 1] = array[i];
|
|
|
+ }
|
|
|
+ array.length = n - 1;
|
|
|
+ return value;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Remove all values from the vector.
|
|
|
+ *
|
|
|
+ * #### Complexity
|
|
|
+ * Linear.
|
|
|
+ *
|
|
|
+ * #### Iterator Validity
|
|
|
+ * All current iterators are invalidated.
|
|
|
+ */
|
|
|
+ clear(): void {
|
|
|
+ this._array.length = 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Swap the contents of the vector with the contents of another.
|
|
|
+ *
|
|
|
+ * @param other - The other vector holding the contents to swap.
|
|
|
+ *
|
|
|
+ * #### Complexity
|
|
|
+ * Constant.
|
|
|
+ *
|
|
|
+ * #### Iterator Validity
|
|
|
+ * All current iterators remain valid, but will now point to the
|
|
|
+ * contents of the other vector involved in the swap.
|
|
|
+ */
|
|
|
+ swap(other: Vector<T>): void {
|
|
|
+ let array = other._array;
|
|
|
+ other._array = this._array;
|
|
|
+ this._array = array;
|
|
|
+ }
|
|
|
+
|
|
|
+ private _array: T[] = [];
|
|
|
+}
|