-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbinarysearch.js
99 lines (85 loc) · 2.54 KB
/
binarysearch.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
import {DEFAULT_COMPARE, signedCompare} from './quicksort.js';
const DEFAULT_OPTIONS = {
invert: false, /* invert order */
compare: DEFAULT_COMPARE,
recursive: false, /* iterative is the default, true uses recursive */
};
export default function BinarySearch(data, item, opts) {
if ( ! opts ) {
opts = DEFAULT_OPTIONS;
}
opts = Object.assign({}, DEFAULT_OPTIONS, opts);
opts = Object.freeze(opts);
if ( opts.recursive ) {
return recursiveBinarySearch(data, item, 0, data.length - 1, opts);
} else {
return iterativeBinarySearch(data, item, 0, data.length - 1, opts);
}
}
export const find = BinarySearch;
export function recursiveBinarySearch(data, item, low, high, opts) {
const foundIndex = Math.floor((low + high)/2);
const foundItem = data[foundIndex];
const comparison = signedCompare(foundItem, item, opts);
if(low < high) {
if ( comparison > 0 ) {
low = foundIndex + 1;
} else if ( comparison < 0 ) {
high = foundIndex;
if ( high > 0 ) {
high--;
}
} else {
return {has: true, index: foundIndex};
}
return recursiveBinarySearch(data, item, low, high, opts);
} else {
if ( comparison === 0 ) {
return {has: true, index: foundIndex};
} else if ( comparison > 0 ) {
//console.log({foundItem, item, comparison, low, high, foundIndex, low1: low+1});
return {has: false, index: foundIndex+1};
} else if ( comparison < 0 ) {
//console.log({foundItem, item, comparison, low, high, foundIndex});
return {has: false, index: foundIndex};
}
}
}
export function iterativeBinarySearch(data, item, low, high, opts ) {
let foundIndex;
let foundItem;
let comparison;
if ( data.length === 0 ) {
throw new TypeError(`OK`);
}
do {
foundIndex = Math.floor((low + high)/2);
foundItem = data[foundIndex];
comparison = signedCompare(foundItem, item, opts);
if ( comparison > 0 ) {
low = foundIndex + 1;
} else if ( comparison < 0 ) {
high = foundIndex;
if ( high > 0 ) {
high--;
}
} else {
break;
}
} while( low < high );
foundIndex = Math.floor((low + high)/2);
foundItem = data[foundIndex];
comparison = signedCompare(foundItem, item, opts);
/**
if ( foundIndex < 0 ) {
console.log({low,high});
}
**/
if ( comparison === 0 ) {
return {has: true, index: foundIndex};
} else if ( comparison > 0 ) {
return {has: false, index: foundIndex+1};
} else if ( comparison < 0 ) {
return {has: false, index: foundIndex};
}
}