-
David Sehnal authoredDavid Sehnal authored
binary-search.ts 4.33 KiB
function createData(n: number) {
const data = [];//new Int32Array(n);
let last = (15 * Math.random()) | 0;
for (let i = 0; i < n; i++) {
data[i] = last;
last += (15 * Math.random()) | 0;
}
return data;
}
function binarySearchHelper(list: ArrayLike<number>, t: number) {
let min = 0, max = list.length - 1;
while (min <= max) {
if (min + 11 > max) {
for (let i = min; i <= max; i++) {
if (t === list[i]) return i;
}
return -1;
}
const mid = (min + max) >> 1;
const v = list[mid];
if (t < v) max = mid - 1;
else if (t > v) min = mid + 1;
else return mid;
}
return -1;
}
function objSearch(obj: any, val: number) {
return typeof obj[val] !== 'undefined';
}
function setSearch(set: Set<number>, val: number) {
return set.has(val);
}
type Mask = { min: number, max: number, mask: ArrayLike<number> }
function maskSearch({ min, max, mask }: Mask, val: number) {
return val >= min && val <= max && !!mask[val - min];
}
function prepare(list: ArrayLike<number>) {
const obj = Object.create(null), set = new Set<number>();
for (let i = 0; i < list.length; i++) {
const v = list[i];
obj[v] = i;
set.add(v);
}
return { list, obj, set };
}
function prepareSet(list: ArrayLike<number>) {
const set = new Set<number>();
for (let i = 0; i < list.length; i++) {
const v = list[i];
set.add(v);
}
return set;
}
function prepareObj(list: ArrayLike<number>) {
const obj = Object.create(null);
for (let i = 0; i < list.length; i++) {
const v = list[i];
obj[v] = i;
}
return obj;
}
function prepareMask(list: ArrayLike<number>): Mask {
let max = Number.NEGATIVE_INFINITY, min = Number.POSITIVE_INFINITY;
for (let i = 0; i < list.length; i++) {
const v = list[i];
if (max < v) max = v;
if (min > v) min = v;
}
const mask = new Uint8Array(max - min + 1);
for (let i = 0; i < list.length; i++) {
const v = list[i];
mask[v - min] = 1;
}
return { min, max, mask };
}
function testBinary(list: ArrayLike<number>, points: ArrayLike<number>) {
let r = 0;
for (let i = 0, _i = points.length; i < _i; i++) {
if (binarySearchHelper(list, points[i]) >= 0) r += points[i];
}
return r;
}
function testObj(obj: any, points: ArrayLike<number>) {
let r = 0;
for (let i = 0, _i = points.length; i < _i; i++) {
if (objSearch(obj, points[i])) r += points[i];
}
return r;
}
function testSet(set: Set<number>, points: ArrayLike<number>) {
let r = 0;
for (let i = 0, _i = points.length; i < _i; i++) {
if (setSearch(set, points[i])) r += points[i];
}
return r;
}
function testMask(mask: Mask, points: ArrayLike<number>) {
let r = 0;
for (let i = 0, _i = points.length; i < _i; i++) {
if (maskSearch(mask, points[i])) r += points[i];
}
return r;
}
function run(f: () => number, n: number) {
for (let i = 0; i < n; i++) f();
}
(function () {
const size = 10000;
const list = createData(size);
const queryPoints = createData(size);
let obj = prepareObj(list);
let set = prepareSet(list);
let mask = prepareMask(list);
console.log('list', testBinary(list, queryPoints));
console.log('obj', testObj(obj, queryPoints));
console.log('set', testSet(set, queryPoints));
console.log('mask', testMask(mask, queryPoints));
console.log('----------------------')
console.time('obj');
run(() => testObj(obj, queryPoints), 100);
console.timeEnd('obj');
console.time('set');
run(() => testSet(set, queryPoints), 100);
console.timeEnd('set');
console.time('bin-search');
run(() => testBinary(list, queryPoints), 100);
console.timeEnd('bin-search');
console.time('mask-search');
run(() => testMask(mask, queryPoints), 100);
console.timeEnd('mask-search');
console.log('----------------------')
console.time('prepare-obj');
run(() => prepareObj(list), 1);
console.timeEnd('prepare-obj');
console.time('prepare-set');
run(() => prepareSet(list).size, 1);
console.timeEnd('prepare-set');
console.time('prepare-mask');
run(() => prepareMask(list).min, 1);
console.timeEnd('prepare-mask');
}())