binary-search.ts 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. function createData(n: number) {
  2. const data = []; // new Int32Array(n);
  3. let last = (15 * Math.random()) | 0;
  4. for (let i = 0; i < n; i++) {
  5. data[i] = last;
  6. last += (15 * Math.random()) | 0;
  7. }
  8. return data;
  9. }
  10. function binarySearchHelper(list: ArrayLike<number>, t: number) {
  11. let min = 0, max = list.length - 1;
  12. while (min <= max) {
  13. if (min + 11 > max) {
  14. for (let i = min; i <= max; i++) {
  15. if (t === list[i]) return i;
  16. }
  17. return -1;
  18. }
  19. const mid = (min + max) >> 1;
  20. const v = list[mid];
  21. if (t < v) max = mid - 1;
  22. else if (t > v) min = mid + 1;
  23. else return mid;
  24. }
  25. return -1;
  26. }
  27. function objSearch(obj: any, val: number) {
  28. return typeof obj[val] !== 'undefined';
  29. }
  30. function setSearch(set: Set<number>, val: number) {
  31. return set.has(val);
  32. }
  33. type Mask = { min: number, max: number, mask: ArrayLike<number> }
  34. function maskSearch({ min, max, mask }: Mask, val: number) {
  35. return val >= min && val <= max && !!mask[val - min];
  36. }
  37. function prepare(list: ArrayLike<number>) {
  38. const obj = Object.create(null), set = new Set<number>();
  39. for (let i = 0; i < list.length; i++) {
  40. const v = list[i];
  41. obj[v] = i;
  42. set.add(v);
  43. }
  44. return { list, obj, set };
  45. }
  46. function prepareSet(list: ArrayLike<number>) {
  47. const set = new Set<number>();
  48. for (let i = 0; i < list.length; i++) {
  49. const v = list[i];
  50. set.add(v);
  51. }
  52. return set;
  53. }
  54. function prepareObj(list: ArrayLike<number>) {
  55. const obj = Object.create(null);
  56. for (let i = 0; i < list.length; i++) {
  57. const v = list[i];
  58. obj[v] = i;
  59. }
  60. return obj;
  61. }
  62. function prepareMask(list: ArrayLike<number>): Mask {
  63. let max = Number.NEGATIVE_INFINITY, min = Number.POSITIVE_INFINITY;
  64. for (let i = 0; i < list.length; i++) {
  65. const v = list[i];
  66. if (max < v) max = v;
  67. if (min > v) min = v;
  68. }
  69. const mask = new Uint8Array(max - min + 1);
  70. for (let i = 0; i < list.length; i++) {
  71. const v = list[i];
  72. mask[v - min] = 1;
  73. }
  74. return { min, max, mask };
  75. }
  76. function testBinary(list: ArrayLike<number>, points: ArrayLike<number>) {
  77. let r = 0;
  78. for (let i = 0, _i = points.length; i < _i; i++) {
  79. if (binarySearchHelper(list, points[i]) >= 0) r += points[i];
  80. }
  81. return r;
  82. }
  83. function testObj(obj: any, points: ArrayLike<number>) {
  84. let r = 0;
  85. for (let i = 0, _i = points.length; i < _i; i++) {
  86. if (objSearch(obj, points[i])) r += points[i];
  87. }
  88. return r;
  89. }
  90. function testSet(set: Set<number>, points: ArrayLike<number>) {
  91. let r = 0;
  92. for (let i = 0, _i = points.length; i < _i; i++) {
  93. if (setSearch(set, points[i])) r += points[i];
  94. }
  95. return r;
  96. }
  97. function testMask(mask: Mask, points: ArrayLike<number>) {
  98. let r = 0;
  99. for (let i = 0, _i = points.length; i < _i; i++) {
  100. if (maskSearch(mask, points[i])) r += points[i];
  101. }
  102. return r;
  103. }
  104. function run(f: () => number, n: number) {
  105. for (let i = 0; i < n; i++) f();
  106. }
  107. (function () {
  108. const size = 10000;
  109. const list = createData(size);
  110. const queryPoints = createData(size);
  111. let obj = prepareObj(list);
  112. let set = prepareSet(list);
  113. let mask = prepareMask(list);
  114. console.log('list', testBinary(list, queryPoints));
  115. console.log('obj', testObj(obj, queryPoints));
  116. console.log('set', testSet(set, queryPoints));
  117. console.log('mask', testMask(mask, queryPoints));
  118. console.log('----------------------')
  119. console.time('obj');
  120. run(() => testObj(obj, queryPoints), 100);
  121. console.timeEnd('obj');
  122. console.time('set');
  123. run(() => testSet(set, queryPoints), 100);
  124. console.timeEnd('set');
  125. console.time('bin-search');
  126. run(() => testBinary(list, queryPoints), 100);
  127. console.timeEnd('bin-search');
  128. console.time('mask-search');
  129. run(() => testMask(mask, queryPoints), 100);
  130. console.timeEnd('mask-search');
  131. console.log('----------------------')
  132. console.time('prepare-obj');
  133. run(() => prepareObj(list), 1);
  134. console.timeEnd('prepare-obj');
  135. console.time('prepare-set');
  136. run(() => prepareSet(list).size, 1);
  137. console.timeEnd('prepare-set');
  138. console.time('prepare-mask');
  139. run(() => prepareMask(list).min, 1);
  140. console.timeEnd('prepare-mask');
  141. }())