jstructures
Version:
The project is JavaScript Data Structures incudes Vector, List, Tree, Graph, Heap...etc
280 lines (258 loc) • 6.94 kB
JavaScript
/**
* @param {Array} _elem 初始数组
* @class
* @return {Vector} Instance
*/
function Vector(_elem = []) {
Object.defineProperty(_elem, "size", {
/**
* 获取向量大小
* @time O(1)
* @space O(0)
* @memberof Vector
* @name size
* @instance
*
* @return {number}
*/
get: function size() {
return _elem.length;
}
});
/**
* e 作为秩为 r 的元素插入,原后继元素依次后移
* @time O(N)
* @space O(0)
* @memberof Vector
* @instance
*
* @param {number} r 插入新元素的秩 0 <= r <= size
* @param {Anyone} e
* @return {number}
*/
_elem.insert = function insert(r, e) {
for (let i = _elem.length; i > r; i -= 1) _elem[i] = _elem[i - 1];
_elem[r] = e;
return r;
};
/**
* 删除指定区间的元素, 原后继元素依次前移[lo, hi)
* @time O(N)
* @space O(0)
* @memberof Vector
* @instance
*
* @param {number} lo 要删除元素起始的秩 0 <= r <= size
* @param {number} hi 要删除元素结束的秩 0 <= r <= size
* @return {number} 删除的元素数量
*/
_elem.removeRange = function removeRange(lo, hi) {
if (hi - lo <= 0) return 0;
while (hi < _elem.length) _elem[lo++] = _elem[hi++];
_elem.length = lo;
return hi - lo;
};
/**
* 删除指定秩的元素, 原后继元素依次前移
* @time O(N)
* @space O(1)
* @memberof Vector
* @instance
*
* @param {number} r 要删除元素的秩 0 <= r <= size
* @return {Anyone} e 删除的元素
*/
_elem.remove = function remove(r) {
const e = _elem[r];
_elem.removeRange(r, r + 1);
return e;
};
/**
* 返回向量中相邻元素逆序对总数, 当返回为0则代表向量有序
* @time O(N)
* @space O(1)
* @memberof Vector
* @instance
*
* @return {Number}
*/
_elem.disordered = function disordered() {
let count = 0;
for (let i = 1; i < _elem.length; i += 1)
if (_elem[i - 1] > _elem[i]) count += 1;
return count;
};
/**
* 在向量的区间 [lo, hi)查找元素等于 e 的最大秩
* @time O(N)
* @space O(1)
* @memberof Vector
* @instance
*
* @param {Anyone} e 要搜索的元素
* @param {number} [lo=0] 要查找的起始秩
* @param {number} [hi=_elem.length] 要查找的结束秩
* @return {number} 等于 e 的元素最大的秩
*/
_elem.findElem = function findElem(e, lo = 0, hi = _elem.length) {
while (lo < hi-- && _elem[hi] !== e) {}
return hi;
};
/**
* 在有序向量的区间[lo, hi)查找元素e 所在的秩, 0 <= lo <= hi <= size
* @time O(logN)
* @space O(1)
* @memberof Vector
* @instance
*
* @param {Anyone} e 要搜索的元素
* @param {number} lo 要查找的起始秩
* @param {number} hi 要查找的结束秩
* @return {number} 不大于 e 的元素最大的秩
*/
_elem.search = function binSearch(e, lo, hi) {
return Vector.binSearch(_elem, e, lo, hi);
};
/**
* 剔除重复元素,保证每个元素都是唯一的
* @time O(N²)
* @space O(1)
* @memberof Vector
* @instance
*
* @return {number} 被删除的元素个数
*/
_elem.deduplicate = function deduplicate() {
const { length } = _elem;
let i = 1;
while (i < _elem.length) {
// 在前缀中寻找相似者
if (_elem.findElem(_elem[i], 0, i) < 0) i += 1;
else _elem.remove(i);
}
return length - _elem.length;
};
/**
* 有序向量剔除重复元素,保证每个元素都是唯一的
* @time O(N)
* @space O(1)
* @memberof Vector
* @instance
*
* @return {number} 被删除的元素个数
*/
_elem.uniquify = function uniquify() {
const { length } = _elem;
let i = 0;
let j = 0;
while ((j += 1) < length) {
if (_elem[i] !== _elem[j]) _elem[(i += 1)] = _elem[j];
}
_elem.length = i + 1;
return length - _elem.length;
};
/**
* 向量的遍历
* @time O(N)
* @space O(1);
* @memberof Vector
* @instance
* @param {function} visit 访问函数
*
* @return void
*/
_elem.traverse = function traverse(visit) {
for (let i = 0; i < _elem.length; i += 1) visit(_elem[i]);
};
return _elem;
}
/**
* 在有序向量的区间[lo, hi)查找元素不大于 e 的元素的最大秩, 0 <= lo <= hi <= size
* @time O(logN)
* @space O(1)
*
* @param {Vector} _elem 要搜索的有序向量或有序数组
* @param {Anyone} e 要搜索的元素
* @param {number} lo 要查找的起始秩
* @param {number} hi 要查找的结束秩
* @return {number} 不大于 e 的元素最大的秩
*/
Vector.binSearch = function binSearch(_elem, e, lo = 0, hi = _elem.length) {
while (lo < hi) {
const mi = (lo + hi) >> 1; // 寻找中点
// 经比较后确认深入 [lo, mi) 或 [mi + 1, hi)
if (e < _elem[mi]) hi = mi;
else lo = mi + 1;
}
// 查找成功不能提前终止
// 循环结束时, lo 为大于e的元素的最小的秩,故 lo - 1即不大于 e de元素的最大秩
return lo - 1;
};
/**
* 排序算法 起泡排序, 具有稳定性
* @time O(N²)
* @space O(1)
*
* @param {Vector} _elem 要排序的向量或数据
* @param {number} lo 要查找的起始秩
* @param {number} hi 要查找的结束秩
* @return {void}
*/
Vector.bubbleSort = function bubbleSort(_elem, lo = 0, hi = _elem.length) {
const _lo = lo;
let sorted = true;
while ((lo += 1) < hi) {
if (_elem[lo - 1] > _elem[lo]) {
sorted = false;
const tmp = _elem[lo - 1];
_elem[lo - 1] = _elem[lo];
_elem[lo] = tmp;
}
}
if (!sorted) Vector.bubbleSort(_elem, _lo, (hi -= 1));
};
/**
* 排序算法 归并排序之合并
* @time O(N)
* @space O(logN)
*
* @param {Vector} _elem 要排序的向量或数据
* @param {number} lo 要查找的起始秩
* @param {number} hi 要查找的结束秩
* @return {void}
*/
Vector.merge = function merge(_elem, lo, mi, hi) {
let l = lo;
let r = mi;
let i = lo;
const B = _elem.slice(lo, mi); // 复制前子向量
while (l < mi && r < hi) {
if (_elem[r] < B[l - lo]) {
_elem[i] = _elem[r];
r += 1;
} else {
_elem[i] = B[l - lo];
l += 1;
}
i += 1;
}
while (l < mi) _elem[i++] = B[l++ - lo];
};
/**
* 排序算法 归并排序
* @time O(NlogN)
* @space O(logN)
*
* @param {Vector} _elem 要排序的向量或数据
* @param {number} lo 要查找的起始秩
* @param {number} hi 要查找的结束秩
* @return {void}
*/
Vector.mergeSort = function mergeSort(_elem, lo = 0, hi = _elem.length) {
if (hi - lo < 2) return; // 单个元素自然是有序的
const mi = (lo + hi) >> 1; // 找到中点
Vector.mergeSort(_elem, lo, mi); // 分治思想, 左半段
Vector.mergeSort(_elem, mi, hi); // 分治思想,右半段
Vector.merge(_elem, lo, mi, hi);
};
module.exports = Vector;