• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * Copyright (c) 2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15type CompFun<T> = (firstValue: T, secondValue: T) => boolean;
16
17function hashCode(element: any): number {
18  let str: string = '';
19  str = String(element);
20  let hash: number = 0;
21  if (hash === 0 && str.length > 0) {
22    for (let i: number = 0; i < str.length; i++) {
23      let char: number = 0;
24      char = str.charCodeAt(i);
25      hash = ((hash << 5) - hash) + char;
26      hash = hash & hash;
27    }
28  }
29  return hash;
30}
31function insert<T>(a: Array<T>, index: number, value: T): void {
32  for (let i: number = a.length; i > index; i--) {
33    a[i] = a[i - 1];
34  }
35  a[index] = value;
36}
37enum ComparResult {
38  LESS_THAN = -1,
39  BIGGER_THAN = 1,
40  EQUALS = 0
41}
42function compareToString(string1: String, string2: String): number {
43  let len1: number = string1.length;
44  let len2: number = string2.length;
45  let lim: number = 0;
46  lim = (len1 > len2 ? len2 : len1);
47  let k: number = 0;
48  while (k < lim) {
49    if (string1.charCodeAt(k) === string2.charCodeAt(k)) {
50      k++;
51      if (k === lim) {
52        return len1 > len2 ? ComparResult.BIGGER_THAN : ComparResult.LESS_THAN;
53      }
54      continue;
55    }
56    return string1.charCodeAt(k) > string2.charCodeAt(k) ? ComparResult.BIGGER_THAN : ComparResult.LESS_THAN;
57  }
58  throw new Error('this compare function run error');
59}
60function currencyCompare(a: any, b: any, compareFn?: CompFun<any>): number {
61  if (a === b) {
62    return ComparResult.EQUALS;
63  }
64  if (a instanceof Pair && b instanceof Pair) {
65    return currencyCompare(a.key, b.key, compareFn);
66  }
67  if (compareFn != undefined) {
68    return compareFn(a, b) ? ComparResult.BIGGER_THAN : ComparResult.LESS_THAN;
69  }
70  if (typeof a === 'number' && typeof b === 'number') {
71    if (a > b) {
72      return ComparResult.BIGGER_THAN;
73    } else {
74      return ComparResult.LESS_THAN;
75    }
76  } else if (typeof a === 'string' && typeof b === 'string') {
77    return compareToString(a, b);
78  } else if (typeof a === 'string' && typeof b === 'number') {
79    return ComparResult.BIGGER_THAN;
80  } else if (typeof a === 'number' && typeof b === 'string') {
81    return ComparResult.LESS_THAN;
82  }
83  throw new Error('This form of comparison is not supported');
84}
85function isIncludeToArray(array1: Array<any>, array2: Array<any>): boolean {
86  let newList: number[] = [];
87  newList = array1.filter((val) => {
88    return array2.indexOf(val) > -1;
89  })
90  if (newList.length === array2.length) {
91    return true;
92  }
93  return false;
94}
95class Pair<K, V>{
96  key: K;
97  value: V;
98  constructor(key: K, value: V = key as unknown as V) {
99    this.key = key;
100    this.value = value;
101  }
102  entry(): [K, V] {
103    return [this.key, this.value];
104  }
105  toString(): string {
106    return `[#${this.key}: ${this.value}]`;
107  }
108}
109class PlainArrayMembers<T> {
110  keys: Array<number>;
111  values: Array<T>;
112  constructor() {
113    this.keys = [];
114    this.values = [];
115  }
116}
117class PlainArrayClass<T> {
118  protected memberNumber: number;
119  protected members: PlainArrayMembers<T>;
120  constructor() {
121    this.memberNumber = 0;
122    this.members = new PlainArrayMembers<T>();
123  }
124  protected addmember(key: number, value: T): void {
125    let index: number = 0;
126    index = this.binarySearchAtPlain(key);
127    if (index >= 0) {
128      this.members.keys[index] = key;
129      this.members.values[index] = value;
130    } else {
131      index = ~index;
132      insert(this.members.keys, index, key);
133      insert(this.members.values, index, value);
134      this.memberNumber++;
135    }
136  }
137  protected deletemember(index: number, safeSize: number = 1): T {
138    this.memberNumber -= safeSize;
139    this.members.keys.splice(index, safeSize);
140    let removeValue = this.members.values.splice(index, safeSize)[0];
141    return removeValue;
142  }
143  protected binarySearchAtPlain(key: number, startIndex: number = 0, endIndex: number = this.memberNumber): number {
144    let low: number = startIndex;
145    let high: number = endIndex - 1;
146    while (low <= high) {
147      let mid: number = (low + high) >>> 1;
148      let midVal: number = this.members.keys[mid];
149      if (midVal < key) {
150        low = mid + 1;
151      } else {
152        if (midVal <= key) {
153          return mid;
154        }
155        high = mid - 1;
156      }
157    }
158    return -(low + 1);
159  }
160}
161class LightWeightMembers<K, V> {
162  hashs: Array<number>;
163  keys: Array<K>;
164  values: Array<V>;
165  constructor() {
166    this.hashs = [];
167    this.keys = [];
168    this.values = [];
169  }
170}
171class LightWeightClass<K, V> {
172  protected memberNumber: number;
173  protected members: LightWeightMembers<K, V>;
174  protected capacity: number = 8;
175  constructor() {
176    this.memberNumber = 0;
177    this.members = new LightWeightMembers<K, V>();
178  }
179  protected addmember(key: K, value: V = key as unknown as V): void {
180    let hash: number = 0;
181    hash = hashCode(key);
182    let index: number = 0;
183    index = this.binarySearchAtLightWeight(hash);
184    if (index >= 0) {
185      this.members.keys[index] = key;
186      this.members.values[index] = value;
187    } else {
188      index = ~index;
189      insert(this.members.hashs, index, hash);
190      insert(this.members.keys, index, key);
191      insert(this.members.values, index, value);
192      this.memberNumber++;
193    }
194    if (this.capacity < this.memberNumber) this.ensureCapacity(1);
195  }
196  protected getIndexByKey(key: K): number {
197    let hash: number = 0;
198    hash = hashCode(key);
199    let index: number = 0;
200    index = this.binarySearchAtLightWeight(hash);
201    // js ( A negative number indicates an inverted number in the array )
202    if (index < 0 || index >= this.memberNumber) return -1;
203    return index;
204  }
205  protected deletemember(key: K): V {
206    let result: any = undefined;
207    let index: number = 0;
208    index = this.getIndexByKey(key);
209    if (index < 0) {
210      return result;
211    }
212    this.memberNumber--;
213    this.members.hashs.splice(index, 1);
214    this.members.keys.splice(index, 1);
215    return this.members.values.splice(index, 1)[0];
216  }
217  protected ensureCapacity(addCapacity: number = 1): void {
218    let tempCapacity: number = 0;
219    tempCapacity = this.capacity + addCapacity;
220    while (this.capacity < tempCapacity) {
221      this.capacity = 2 * this.capacity;
222    }
223  }
224  protected getIndex(key: K): number {
225    let hash: number = 0;
226    hash = hashCode(key);
227    let index: number = 0;
228    index = this.binarySearchAtLightWeight(hash);
229    if (index < 0) {
230      index = ~index;
231    }
232    return index;
233  }
234  protected keyValueStringArray(): Array<string> {
235    let resultArray: Array<string> = [];
236    for (let i: number = 0; i < this.memberNumber; i++) {
237      resultArray.push(JSON.stringify(this.members.keys[i]) + ':' + JSON.stringify(this.members.values[i]));
238    }
239    return resultArray;
240  }
241  protected binarySearchAtLightWeight(hash: number, startIndex: number = 0, endIndex: number = this.memberNumber): number {
242    let low: number = startIndex;
243    let high: number = endIndex - 1;
244    while (low <= high) {
245      let mid: number = 0;
246      mid = (low + high) >>> 1;
247      let midVal: number = 0;
248      midVal = this.members.hashs[mid];
249      if (midVal < hash) {
250        low = mid + 1;
251      } else {
252        if (midVal <= hash) {
253          return mid;
254        }
255        high = mid - 1;
256      }
257    }
258    return -(low + 1);
259  }
260}
261type RBTreeNodeColor = 0 | 1;
262const BLACK = 0;
263const RED = 1;
264class RBTreeNode<K, V> extends Pair<K, V>{
265  color: RBTreeNodeColor;
266  left: RBTreeNode<K, V> | undefined;
267  right: RBTreeNode<K, V> | undefined;
268  parent: RBTreeNode<K, V> | undefined;
269  constructor(key: K,
270    value?: V,
271    color: RBTreeNodeColor = RED,
272    parent?: RBTreeNode<K, V>,
273    left?: RBTreeNode<K, V>,
274    right?: RBTreeNode<K, V>) {
275    super(key, value);
276    this.color = color;
277    this.left = left;
278    this.right = right;
279    this.parent = parent;
280  }
281}
282class RBTreeClass<K, V> {
283  private root: RBTreeNode<K, V> | undefined;
284  public memberNumber: number;
285  private isChange: boolean;
286  private treeNodeArray: Array<RBTreeNode<K, V>>;
287  private compFun: CompFun<K> | undefined;
288  constructor(comparator?: CompFun<K>, root?: RBTreeNode<K, V>) {
289    this.root = root;
290    this.compFun = comparator;
291    this.memberNumber = 0;
292    this.isChange = true;
293    this.treeNodeArray = [];
294  }
295  get keyValueArray(): Array<RBTreeNode<K, V>> {
296    let result: Array<RBTreeNode<K, V>> = [];
297    result = this.recordByMinToMax();
298    return result;
299  }
300  addNode(key: K, value: V = key as unknown as V): RBTreeClass<K, V> {
301    if (this.root === undefined) {
302      this.root = new RBTreeNode<K, V>(key, value);
303      this.setColor(BLACK, this.root);
304      this.memberNumber++;
305      this.isChange = true;
306    } else {
307      this.addProcess(key, value)
308    }
309    return this;
310  }
311  addProcess(key: K, value: V): RBTreeClass<K, V> {
312    let leafNode: RBTreeNode<K, V> | undefined = this.root;
313    let parentNode: RBTreeNode<K, V> = this.root as RBTreeNode<K, V>;
314    let comp: number = 0;
315    while (leafNode !== undefined) {
316      parentNode = leafNode;
317      comp = currencyCompare(leafNode.key, key, this.compFun);
318      if (comp === 0) {
319        leafNode.value = value;
320        return this;
321      } else if (comp < 0) {
322        leafNode = leafNode.right;
323      } else {
324        leafNode = leafNode.left;
325      }
326    }
327    leafNode = new RBTreeNode<K, V>(key, value)
328    leafNode.parent = parentNode;
329    if (comp < 0) {
330      parentNode.right = leafNode;
331    } else {
332      parentNode.left = leafNode;
333    }
334    this.insertRebalance(leafNode);
335    this.memberNumber++;
336    this.isChange = true;
337    return this;
338  }
339  removeNode(key: K): V | undefined {
340    let removeNode: RBTreeNode<K, V> | undefined = undefined;
341    removeNode = this.getNode(key);
342    if (removeNode === undefined) {
343      return undefined;
344    } else {
345      let result: V = removeNode.value;
346      this.removeNodeProcess(removeNode);
347      return result;
348    }
349  }
350  removeNodeProcess(removeNode: RBTreeNode<K, V>): void {
351    if (removeNode.left !== undefined && removeNode.right !== undefined) {
352      let successor: RBTreeNode<K, V> | undefined = removeNode.right;
353      while (successor.left !== undefined) {
354        successor = successor.left;
355      }
356      removeNode.key = successor.key;
357      removeNode.value = successor.value;
358      this.removeNodeProcess(successor); // only once
359      return;
360    } else {  // one or zero child
361      let child: RBTreeNode<K, V> | undefined = undefined;
362      child = (removeNode.left === undefined ? removeNode.right : removeNode.left);
363      if (removeNode.parent === undefined) { // remove is root
364        if (child === undefined) {
365          this.root = undefined;
366        } else {
367          child.parent = undefined;
368          child.color = BLACK;
369          this.root = child;
370        }
371      } else {
372        if (child != undefined) {
373          // delete removeNode
374          if (removeNode.parent.left === removeNode) {
375            removeNode.parent.left = child;
376          } else {
377            removeNode.parent.right = child;
378          }
379          if (this.getColor(removeNode) === BLACK) {
380            this.deleteRebalance(child)
381          }
382        } else {
383          if (this.getColor(removeNode) === BLACK) {
384            this.deleteRebalance(removeNode)
385          }
386          if (removeNode.parent.left === removeNode) {
387            removeNode.parent.left = child;
388          } else {
389            removeNode.parent.right = child;
390          }
391        }
392      }
393      this.memberNumber--;
394      this.isChange = true;
395    }
396  }
397  getNode(key: K): RBTreeNode<K, V> | undefined {
398    if (this.root === undefined) {
399      return undefined;
400    }
401    let findNode: RBTreeNode<K, V> | undefined = this.root;
402    while (findNode !== undefined && findNode.key !== key) {
403      findNode = currencyCompare(findNode.key, key, this.compFun) === ComparResult.BIGGER_THAN ?
404        findNode.left : findNode.right;
405    }
406    return findNode;
407  }
408  findNode(value: V): RBTreeNode<K, V> | undefined {
409    let tempNode: RBTreeNode<K, V> | undefined = undefined;
410    this.recordByMinToMax();
411    for (let i: number = 0; i < this.memberNumber; i++) {
412      if (this.treeNodeArray[i].value === value) {
413        tempNode = this.treeNodeArray[i];
414        break;
415      }
416    }
417    return tempNode;
418  }
419  firstNode(): RBTreeNode<K, V> | undefined {
420    let tempNode: RBTreeNode<K, V> | undefined = this.root;
421    while (tempNode !== undefined && tempNode.left !== undefined) {
422      tempNode = tempNode.left;
423    }
424    return tempNode;
425  }
426  lastNode(): RBTreeNode<K, V> | undefined {
427    let tempNode: RBTreeNode<K, V> | undefined = this.root;
428    while (tempNode !== undefined && tempNode.right !== undefined) {
429      tempNode = tempNode.right;
430    }
431    return tempNode;
432  }
433  isEmpty(): boolean {
434    return this.root === undefined;
435  }
436  setAll(map: RBTreeClass<K, V>): void {
437    let tempArray: RBTreeNode<K, V>[] = [];
438    tempArray = map.recordByMinToMax();
439    for (let i: number = 0; i < map.memberNumber; i++) {
440      this.addNode(tempArray[i].key, tempArray[i].value);
441    }
442  }
443  clearTree(): void {
444    this.root = undefined;
445    this.memberNumber = 0;
446  }
447  private recordByMinToMax(): Array<RBTreeNode<K, V>> {
448    if (!this.isChange) {
449      return this.treeNodeArray;
450    }
451    let stack: Array<any> = [];
452    this.treeNodeArray = [];
453    let node: RBTreeNode<K, V> | undefined = this.root;
454    while (node != undefined || stack.length) {
455      while (node != undefined) {
456        stack.push(node);
457        node = node.left;
458      }
459      let tempNode = stack.pop();
460      if (tempNode === undefined) {
461        throw new Error('this function run error');
462      }
463      node = tempNode;
464      this.treeNodeArray.push(node);
465      node = node.right;
466    }
467    this.isChange = false;
468    this.memberNumber = this.treeNodeArray.length;
469    return this.treeNodeArray;
470  }
471  private lRotate(datumPointNode: RBTreeNode<K, V>): RBTreeClass<K, V> {
472    let newTopNode: RBTreeNode<K, V> | undefined = datumPointNode.right;
473    if (newTopNode === undefined) {
474      throw new Error('[rotate right error]: the right child node of the base node === undefined')
475    }
476    datumPointNode.right = newTopNode.left;
477    datumPointNode.right !== undefined ? datumPointNode.right.parent = datumPointNode : '';
478    newTopNode.parent = datumPointNode.parent;
479    if (datumPointNode.parent === undefined) {
480      this.root = newTopNode;
481    } else if (datumPointNode.parent.left === datumPointNode) {
482      datumPointNode.parent.left = newTopNode;
483    } else if (datumPointNode.parent.right === datumPointNode) {
484      datumPointNode.parent.right = newTopNode;
485    }
486    datumPointNode.parent = newTopNode;
487    newTopNode.left = datumPointNode;
488    return this;
489  }
490  private rRotate(datumPointNode: RBTreeNode<K, V>): RBTreeClass<K, V> {
491    let newTopNode: RBTreeNode<K, V> | undefined = datumPointNode.left;
492    if (newTopNode === undefined) {
493      throw new Error('[rotate right error]: the left child node of the base node === undefined')
494    }
495    datumPointNode.left = newTopNode.right;
496    datumPointNode.left !== undefined ? datumPointNode.left.parent = datumPointNode : '';
497    newTopNode.parent = datumPointNode.parent
498    if (datumPointNode.parent === undefined) {
499      this.root = newTopNode;
500    } else if (datumPointNode === datumPointNode.parent.left) {
501      datumPointNode.parent.left = newTopNode;
502    } else if (datumPointNode === datumPointNode.parent.right) {
503      datumPointNode.parent.right = newTopNode;
504    }
505    datumPointNode.parent = newTopNode;
506    newTopNode.right = datumPointNode;
507    return this;
508  }
509  private insertRebalance(fixNode: RBTreeNode<K, V>): RBTreeClass<K, V> {
510    let parentNode: RBTreeNode<K, V> | undefined = fixNode.parent;
511    while (this.getColor(parentNode) === RED &&
512      parentNode !== undefined &&
513      parentNode.parent !== undefined) {
514      let grandpaNode = parentNode && parentNode.parent;
515      if (parentNode === grandpaNode.left &&
516        this.getColor(grandpaNode.right) === BLACK &&
517        fixNode === parentNode.left) {
518        this
519          .setColor(BLACK, parentNode)
520          .setColor(RED, grandpaNode)
521          .rRotate(grandpaNode)
522        break;
523      } else if (parentNode === grandpaNode.left &&
524        this.getColor(grandpaNode.right) === BLACK &&
525        fixNode === parentNode.right) {
526        this
527          .setColor(BLACK, fixNode)
528          .setColor(RED, grandpaNode)
529          .lRotate(parentNode)
530          .rRotate(grandpaNode)
531        break;
532      } else if (parentNode === grandpaNode.right &&
533        this.getColor(grandpaNode.left) === BLACK &&
534        fixNode === parentNode.left) {
535        this
536          .setColor(BLACK, fixNode)
537          .setColor(RED, grandpaNode)
538          .rRotate(parentNode)
539          .lRotate(grandpaNode)
540        break;
541      } else if (parentNode === grandpaNode.right &&
542        this.getColor(grandpaNode.left) === BLACK &&
543        fixNode === parentNode.right) {
544        this
545          .setColor(BLACK, parentNode)
546          .setColor(RED, grandpaNode)
547          .lRotate(grandpaNode)
548        break;
549      } else if ((parentNode === grandpaNode.right && this.getColor(grandpaNode.left) === RED) ||
550        (parentNode === grandpaNode.left && this.getColor(grandpaNode.right) === RED)) {
551        this
552          .setColor(BLACK, parentNode)
553          .setColor(BLACK, parentNode === grandpaNode.left ? grandpaNode.right : grandpaNode.left)
554          .setColor(RED, grandpaNode)
555        fixNode = grandpaNode;
556        parentNode = fixNode.parent;
557      } else {
558        throw new Error('Exceptions after adding')
559      }
560    }
561    this.root ? this.root.color = BLACK : '';
562    return this;
563  }
564  private deleteRebalance(fixNode: RBTreeNode<K, V>): void {
565    while (this.getColor(fixNode) === BLACK && fixNode !== this.root && fixNode.parent) {
566      let sibling: RBTreeNode<K, V> | undefined = undefined;
567      if (fixNode === fixNode.parent.left) {
568        sibling = fixNode.parent.right;
569        if (this.getColor(sibling) === RED) {
570          this
571            .setColor(RED, fixNode.parent)
572            .setColor(BLACK, sibling)
573            .lRotate(fixNode.parent)
574          sibling = fixNode.parent.right;
575        }
576        if (sibling === undefined) {
577          throw new Error('Error sibling node is undefined')
578        }
579        if (this.getColor(sibling.left) === BLACK && this.getColor(sibling.right) === BLACK) {
580          this.setColor(RED, sibling)
581          fixNode = fixNode.parent
582        } else if (this.getColor(sibling.left) === RED && this.getColor(sibling.right) === BLACK) {
583          this
584            .setColor(RED, sibling)
585            .setColor(BLACK, sibling.left)
586            .rRotate(sibling);
587          sibling = fixNode.parent.right
588          if (sibling === undefined) {
589            throw new Error('Error sibling node is empty')
590          }
591          this
592            .setColor(fixNode.parent.color, sibling)
593            .setColor(BLACK, fixNode.parent)
594            .setColor(BLACK, sibling.right)
595            .lRotate(fixNode.parent);
596          break;
597        } else if (this.getColor(sibling.right) === RED) {
598          this
599            .setColor(fixNode.parent.color, sibling)
600            .setColor(BLACK, fixNode.parent)
601            .setColor(BLACK, sibling.right)
602            .lRotate(fixNode.parent);
603          break;
604        } else {
605          throw new Error('Adjust the error after the error is deleted')
606        }
607      } else {
608        sibling = fixNode.parent.left;
609        if (this.getColor(sibling) === RED) {
610          this
611            .setColor(BLACK, sibling)
612            .setColor(RED, fixNode.parent)
613            .rRotate(fixNode.parent);
614          sibling = fixNode.parent.left;
615        }
616        if (sibling === undefined) {
617          throw new Error('Error sibling node is undefined')
618        }
619        if (this.getColor(sibling.left) === BLACK && this.getColor(sibling.right) === BLACK) {
620          this
621            .setColor(RED, sibling)
622          fixNode = fixNode.parent;
623        } else if (this.getColor(sibling.left) === BLACK && this.getColor(sibling.right) === RED) {
624          this
625            .setColor(RED, sibling)
626            .setColor(BLACK, sibling.right)
627            .lRotate(sibling);
628          sibling = fixNode.parent.left;
629          if (sibling === undefined) {
630            throw new Error('Adjust the error after the error is deleted')
631          }
632          this
633            .setColor(fixNode.parent.color, sibling)
634            .setColor(BLACK, fixNode.parent)
635            .setColor(BLACK, sibling.left)
636            .rRotate(fixNode.parent);
637          break;
638        } else if (this.getColor(sibling.left) === RED) {
639          this
640            .setColor(fixNode.parent.color, sibling)
641            .setColor(BLACK, fixNode.parent,)
642            .setColor(BLACK, sibling.left)
643            .rRotate(fixNode.parent);
644          break;
645        } else {
646          throw new Error('Adjust the error after the error is deleted')
647        }
648      }
649    }
650    this.setColor(BLACK, fixNode)
651  }
652  private getColor(node: RBTreeNode<K, V> | undefined): RBTreeNodeColor {
653    return node === undefined ? BLACK : node.color;
654  }
655  private setColor(color: RBTreeNodeColor, node: RBTreeNode<K, V> | undefined): RBTreeClass<K, V> {
656    if (node === undefined) {
657      throw new Error('Wrong color setting')
658    } else {
659      node.color = color
660    }
661    return this;
662  }
663}
664const MAXcapacity = 1 << 30;
665const LOADER_FACTOR = 0.75;
666class DictionaryClass<K, V>  {
667  private tableLink: { [hashIndex: number]: LinkedList<Pair<K, V>> | RBTreeClass<K, V> };
668  protected memberNumber: number;
669  private isChange: boolean;
670  private memberArray: Array<Pair<K, V>>;
671  private capacity: number;
672  constructor() {
673    this.tableLink = {};
674    this.memberNumber = 0;
675    this.isChange = true;
676    this.memberArray = [];
677    this.capacity = 16;
678  }
679  get keyValueArray(): Pair<K, V>[] {
680    let result: Pair<K, V>[] = [];
681    result = this.keyValues();
682    return result;
683  }
684  protected getHashIndex(key: K): number {
685    let h: number = 0;
686    let hash: number = 0;
687    hash = ((key === null) ? 0 : ((h = hashCode(key)) ^ (h >>> 16)));
688    if (this.expandCapacity()) {
689      this.keyValues();
690      this.memberNumber = 0;
691      this.tableLink = {};
692      this.isChange = true;
693      for (let item of this.memberArray) {
694        this.put(item.key, item.value);
695      }
696      this.memberNumber++;
697    }
698    let n: number = 0;
699    n = this.power(this.capacity);
700    return (n - 1) & hash;
701  }
702  private power(size: number): number {
703    let n: number = 1;
704    let temp: number = size;
705    while (temp >>> 1 != 1) {
706      n++;
707      temp = temp >>> 1;
708    }
709    return n;
710  }
711  private keyValues(): Pair<K, V>[] {
712    if (!this.isChange) {
713      return this.memberArray;
714    }
715    this.memberArray = [];
716    let keys: number[] = [];
717    keys = Object.keys(this.tableLink).map((item) => parseInt(item));
718    for (let i: number = 0; i < keys.length; i++) {
719      let members: RBTreeClass<K, V> | LinkedList<Pair<K, V>> = undefined;
720      members = this.tableLink[keys[i]];
721      if (members instanceof RBTreeClass) {
722        let tempArray: RBTreeNode<K, V>[] = members.keyValueArray;
723        for (let i: number = 0; i < members.memberNumber; i++) {
724          this.memberArray.push(new Pair(tempArray[i].key, tempArray[i].value));
725        }
726      } else {
727        if (members != undefined && !members.isEmpty()) {
728          let current: Node<Pair<K, V>> = members.getHead();
729          while (current != undefined) {
730            this.memberArray.push(current.element);
731            current = current.next;
732          }
733        }
734      }
735    }
736    this.memberNumber = this.memberArray.length;
737    let valuePairs: Pair<K, V>[] = this.memberArray;
738    return valuePairs;
739  }
740  protected expandCapacity(): boolean {
741    let capacityChange: boolean = false;
742    while (this.capacity < this.memberNumber / LOADER_FACTOR && this.capacity < MAXcapacity) {
743      this.capacity = 2 * this.capacity;
744      capacityChange = true;
745    }
746    return capacityChange;
747  }
748  protected put(key: K, value: V = key as unknown as V): boolean {
749    this.isChange = true;
750    if (!this.hasKey(key)) {
751      this.memberNumber++;
752    }
753    let position: number = 0;
754    position = this.getHashIndex(key);
755    let members: LinkedList<Pair<K, V>> | RBTreeClass<K, V> = undefined;
756    members = this.tableLink[position];
757    if (members instanceof LinkedList && members.count >= 8) {
758      let newElement: RBTreeClass<K, V> = new RBTreeClass<K, V>();
759      let current: Node<Pair<K, V>> = undefined;
760      current = members.getHead();
761      while (current != null || current != undefined) {
762        if (!(current.element instanceof Pair)) return false;
763        newElement.addNode(current.element.key, current.element.value);
764        current = current.next;
765      }
766      newElement.addNode(key, value);
767      this.tableLink[position] = newElement;
768      return true;
769    } else if (members instanceof RBTreeClass) {
770      members.addNode(key, value);
771      this.tableLink[position] = members;
772      return true;
773    } else {
774      if (this.tableLink[position] === undefined) {
775        members = new LinkedList<Pair<K, V>>();
776      }
777      if (!this.replaceMember(key, value)) {
778        members.push(new Pair(key, value));
779        this.tableLink[position] = members;
780      }
781      return true;
782    }
783  }
784  protected replaceMember(key: K, value: V = key as unknown as V): boolean {
785    let position: number = 0;
786    position = this.getHashIndex(key);
787    let members: LinkedList<Pair<K, V>> = undefined;
788    members = this.tableLink[position] as LinkedList<Pair<K, V>>;
789    if (members === null || members === undefined) {
790      return false;
791    }
792    let current: Node<Pair<K, V>> = undefined;
793    current = members.getHead();
794    while (current != undefined) {
795      if (current.element.key === key) {
796        current.element.value = value;
797        return true;
798      }
799      current = current.next;
800    }
801    return false;
802  }
803  protected getValueByKey(key: K): V | undefined {
804    let position: number = 0;
805    position = this.getHashIndex(key);
806    let members: LinkedList<Pair<K, V>> | RBTreeClass<K, V> = undefined;
807    members = this.tableLink[position];
808    if (members instanceof RBTreeClass) {
809      let resultNode: RBTreeNode<K, V> | undefined = undefined;
810      resultNode = members.getNode(key);
811      if (resultNode === undefined) return undefined;
812      return resultNode.value;
813    } else {
814      if (members != undefined && !members.isEmpty()) {
815        members as LinkedList<Pair<K, V>>;
816        let current: Node<Pair<K, V>> = undefined;
817        current = members.getHead();
818        while (current != undefined) {
819          if (current.element.key === key) {
820            return current.element.value;
821          }
822          current = current.next;
823        }
824      }
825    }
826    return undefined;
827  }
828  protected removeMember(key: K): V | undefined {
829    let position: number = 0;
830    position = this.getHashIndex(key);
831    let members: LinkedList<Pair<K, V>> | RBTreeClass<K, V> = undefined;
832    members = this.tableLink[position];
833    if (members instanceof RBTreeClass) {
834      let result: V | undefined = members.removeNode(key);
835      if (result != undefined) {
836        this.isChange = true;
837        this.memberNumber--;
838        return result;
839      }
840    } else {
841      if (members != undefined && !members.isEmpty()) {
842        let current: Node<Pair<K, V>> = undefined;
843        current = members.getHead();
844        while (current != undefined) {
845          if (current.element.key === key) {
846            let result: V | undefined = current.element.value;
847            members.remove(current.element);
848            if (members.isEmpty()) {
849              delete this.tableLink[position];
850            }
851            this.isChange = true;
852            this.memberNumber--;
853            return result;
854          }
855          current = current.next;
856        }
857      }
858    }
859    return undefined;
860  }
861  protected clear() {
862    this.tableLink = {};
863    this.memberNumber = 0;
864    this.isChange = true;
865    this.capacity = 16;
866  }
867  protected hasKey(key: K): boolean {
868    let position: number = 0;
869    position = this.getHashIndex(key);
870    let members: LinkedList<Pair<K, V>> | RBTreeClass<K, V> = undefined;
871    members = this.tableLink[position];
872    if (members === undefined || members === undefined) {
873      return false;
874    }
875    if (members instanceof RBTreeClass) {
876      return members.getNode(key) !== undefined;
877    }
878    let current: Node<Pair<K, V>> = undefined;
879    current = members.getHead();
880    while (current != undefined && current != undefined) {
881      if (current.element.key === key) {
882        return true;
883      }
884      current = current.next;
885    }
886    return false;
887  }
888  protected setAll(map: DictionaryClass<K, V>): void {
889    let memebers: Pair<K, V>[] = [];
890    memebers = map.keyValues();
891    for (let i: number = 0; i < memebers.length; i++) {
892      this.put(memebers[i].key, memebers[i].value);
893    }
894  }
895  protected Values(): V[] {
896    let values: Array<V> = [];
897    let valuePairs: Pair<K, V>[] = [];
898    valuePairs = this.keyValues();
899    for (let i: number = 0; i < valuePairs.length; i++) {
900      values.push(valuePairs[i].value);
901    }
902    return values;
903  }
904}
905class Node<T> {
906  element: T;
907  next: Node<T> | undefined;
908  constructor(element: T, next?: Node<T>) {
909    this.element = element;
910    this.next = next;
911  }
912}
913class LinkedList<T> {
914  public count: number;
915  protected next: Node<T> | undefined;
916  protected head: Node<T> | undefined;
917  constructor() {
918    this.count = 0;
919    this.next = undefined;
920    this.head = undefined;
921  }
922  push(element: T): void {
923    let node: Node<T> = undefined;
924    node = new Node(element);
925    let current: undefined | Node<T>;
926    if (this.head === undefined) {
927      this.head = node;
928    } else {
929      current = this.head;
930      while (current.next != undefined) {
931        current = current.next;
932      }
933      current.next = node;
934    }
935    this.count++;
936  }
937  removeAt(index: number): T {
938    if (index >= 0 && index < this.count) {
939      let current: Node<T> = this.head;
940      if (index === 0 && current != undefined) {
941        this.head = current.next;
942      } else {
943        let previous: Node<T> = this.getElementAt(index--);
944        if (previous !== undefined) {
945          current = previous.next;
946          previous.next = (current === undefined ? undefined : current.next);
947        }
948      }
949      if (current !== undefined) {
950        this.count--;
951        return current.element;
952      }
953    }
954    return undefined;
955  }
956  getElementAt(index: number): Node<T> {
957    if (index > 0 && index < this.count) {
958      let current: Node<T> = this.head;
959      for (let i: number = 0; i < index && current != undefined; i++) {
960        current = current.next;
961      }
962      return current;
963    }
964    return undefined;
965  }
966  insert(element: T, index: number): boolean {
967    if (index >= 0 && index <= this.count) {
968      let node: Node<T> = undefined;
969      node = new Node(element);
970      if (index === 0) {
971        node.next = this.head;
972        this.head = node;
973      } else {
974        let previous: Node<T> = this.getElementAt(index--);
975        if (previous === undefined)
976          throw new Error('data storage error');
977        node.next = previous.next;
978        previous.next = node;
979      }
980      this.count++;
981      return true;
982    }
983    return false;
984  }
985  indexOf(element: T, compareFn?: CompFun<T>): number {
986    let current: Node<T> = this.head;
987    for (let i: number = 0; i < this.count && current != undefined; i++) {
988      if (currencyCompare(element, current.element, compareFn) === ComparResult.EQUALS) {
989        return i;
990      }
991      current = current.next;
992    }
993    return -1;
994  }
995  remove(element: T, compareFn?: CompFun<T>): void {
996    this.removeAt(this.indexOf(element, compareFn));
997  }
998  clear(): void {
999    this.head = undefined;
1000    this.count = 0;
1001  }
1002  isEmpty(): boolean {
1003    return this.count === 0;
1004  }
1005  getHead(): Node<T> {
1006    return this.head;
1007  }
1008  toString(): string {
1009    if (this.head === undefined) {
1010      return '';
1011    }
1012    let objString: string = '';
1013    objString = `${this.head.element}`;
1014    let current: Node<T> = undefined;
1015    current = this.head.next;
1016    for (let i: number = 1; i < this.count && current != undefined; i++) {
1017      objString = `${objString}, ${current.element}`;
1018      current = current.next;
1019    }
1020    return objString;
1021  }
1022}
1023
1024const NEWTARGET_IS_NULL_ERROR_CODE = 10200012;
1025const BIND_ERROR_CODE = 10200011;
1026const RANGE_ERROR_CODE = 10200001;
1027const TYPE_ERROR_CODE = 401;
1028const EMPTY_ERROR_CODE = 10200010;
1029
1030class BusinessError extends Error {
1031  code: number;
1032  constructor(message, code) {
1033      super();
1034      this.name = "BusinessError";
1035      this.message = message;
1036      this.code = code;
1037  }
1038}
1039
1040function checkBindError(methodName: string, className: Function, self: unknown) {
1041  if (!(self instanceof className)) {
1042    throw new BusinessError(`The ${methodName} method cannot be bound`, BIND_ERROR_CODE);
1043  }
1044}
1045
1046function checkTypeError(paramName:string, type:string, receivedValue:unknown) {
1047  let tmpType = "";
1048  if (typeof receivedValue === "object") {
1049      tmpType = (receivedValue === null) ? "Null" : receivedValue.constructor.name;
1050  } else {
1051      tmpType = typeof receivedValue;
1052  }
1053  if (tmpType === "number" && type === "Integer") {
1054      tmpType = Number.isInteger(receivedValue) ? "Integer" : "number";
1055  }
1056  if (tmpType === "function" && type === "callable") {
1057    tmpType = "callable";
1058  }
1059  if (tmpType.toLocaleLowerCase() !== type.toLocaleLowerCase()) {
1060    type = (type === "Integer") ? "number" : type;
1061    throw new BusinessError(`The type of "${paramName}" must be ${type}. Received value is: ${receivedValue}`, TYPE_ERROR_CODE);
1062  }
1063}
1064
1065function checkRangeError(paramName: string, receivedValue:unknown, min?: number, max?: number, options?:string) {
1066  let range = [];
1067  let minFlag = true;
1068  let maxFlag = true;
1069  if (min !== undefined) {
1070    if (options === "!=min") {
1071      minFlag = (receivedValue > min);
1072      range.push(`> ${min}`);
1073    } else {
1074      minFlag = (receivedValue >= min);
1075      range.push(`>= ${min}`);
1076    }
1077  }
1078  if (max !== undefined) {
1079    max = (max < 0) ? 0 : max;
1080    maxFlag = (receivedValue <= max);
1081    range.push(`<= ${max}`);
1082  }
1083  if (!(minFlag && maxFlag)) {
1084    throw new BusinessError(
1085      `The value of "${paramName}" is out of range. It must be ${range.join(' && ')}. Received value is: ${receivedValue}`, RANGE_ERROR_CODE);
1086  }
1087}
1088
1089function checkIsEmptyError(isEmpty: boolean) {
1090  if (isEmpty) {
1091    throw new BusinessError(`Container is empty`, EMPTY_ERROR_CODE);
1092  }
1093}
1094
1095function checkNewTargetIsNullError(className: string, isNull: boolean) {
1096  if (isNull) {
1097    throw new BusinessError(`The ${className}'s constructor cannot be directly invoked`, NEWTARGET_IS_NULL_ERROR_CODE);
1098  }
1099}
1100
1101let ErrorUtil = {
1102  checkBindError,
1103  checkTypeError,
1104  checkRangeError,
1105  checkIsEmptyError,
1106  checkNewTargetIsNullError
1107}
1108export default {
1109  isIncludeToArray,
1110  LightWeightClass,
1111  PlainArrayClass,
1112  RBTreeClass,
1113  DictionaryClass,
1114  ErrorUtil
1115}
1116
1117