• 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(element);
19  let hash = 0;
20  if (hash === 0 && str.length > 0) {
21    for (let i = 0; i < str.length; i++) {
22      let char = str.charCodeAt(i);
23      hash = ((hash << 5) - hash) + char;
24      hash = hash & hash;
25    }
26  }
27  return hash;
28}
29
30function insert<T>(a: Array<T>, index: number, value: T) {
31  for (let i = a.length; i > index; i--) {
32    a[i] = a[i - 1];
33  }
34  a[index] = value;
35}
36
37enum ComparResult {
38  LESS_THAN = -1,
39  BIGGER_THAN = 1,
40  EQUALS = 0
41}
42
43function compareToString(string1: String, string2: String) {
44  let len1 = string1.length;
45  let len2 = string2.length;
46  let lim = (len1 > len2 ? len2 : len1);
47  let k = 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 function run error");
59}
60
61function currencyCompare(a: any, b: any, compareFn?: CompFun<any>): number {
62  if (a === b) return ComparResult.EQUALS;
63  if (a instanceof Pair && b instanceof Pair) {
64    return currencyCompare(a.key, b.key, compareFn);
65  }
66  if (compareFn != undefined) {
67    return compareFn(a, b) ? ComparResult.BIGGER_THAN : ComparResult.LESS_THAN;
68  }
69  if (typeof a === "number" && typeof b === "number") {
70    if (a > b) {
71      return ComparResult.BIGGER_THAN;
72    } else {
73      return ComparResult.LESS_THAN;
74    }
75  } else if (typeof a === "string" && typeof b === "string") {
76    return compareToString(a, b);
77  } else if (typeof a === "string" && typeof b === "number") {
78    return ComparResult.BIGGER_THAN;
79  } else if (typeof a === "number" && typeof b === "string") {
80    return ComparResult.LESS_THAN;
81  }
82  throw new Error("This form of comparison is not supported");
83}
84
85function isIncludeToArray(array1: Array<any>, array2: Array<any>): boolean {
86  let newlist = array1.filter((val) => {
87    return array2.indexOf(val) > -1;
88  })
89  if (newlist.length == array2.length) return true;
90  return false;
91}
92
93class Pair<K, V>{
94  key: K;
95  value: V;
96  constructor(key: K, value: V = key as unknown as V) {
97    this.key = key;
98    this.value = value;
99  }
100
101  entry(): [K, V] {
102    return [this.key, this.value];
103  }
104
105  toString() {
106    return `[#${this.key}: ${this.value}]`;
107  }
108}
109
110class PlainArrayMembers<T> {
111  keys: Array<number>;
112  values: Array<T>;
113  constructor() {
114    this.keys = [];
115    this.values = [];
116  }
117}
118class PlainArrayClass<T> {
119  protected memberNumber: number;
120  protected members: PlainArrayMembers<T>;
121  constructor() {
122    this.memberNumber = 0;
123    this.members = new PlainArrayMembers<T>();
124  }
125
126  protected addmember(key: number, value: T) {
127    let index = this.binarySearchAtPlain(key);
128    if (index >= 0) {
129      this.members.keys[index] = key;
130      this.members.values[index] = value;
131    } else {
132      index = ~index;
133      insert(this.members.keys, index, key);
134      insert(this.members.values, index, value);
135      this.memberNumber++;
136    }
137  }
138
139  protected deletemember(index: number, safeSize: number = 1): T {
140    this.memberNumber -= safeSize;
141    this.members.keys.splice(index, safeSize);
142    let removeValue = this.members.values.splice(index, safeSize)[0];
143    return removeValue;
144  }
145
146  protected binarySearchAtPlain(key: number, startIndex: number = 0, endIndex: number = this.memberNumber): number {
147    let low = startIndex;
148    let high = endIndex - 1;
149    while (low <= high) {
150      let mid = (low + high) >>> 1;
151      let midVal = this.members.keys[mid];
152      if (midVal < key) {
153        low = mid + 1;
154      } else {
155        if (midVal <= key) {
156          return mid;
157        }
158        high = mid - 1;
159      }
160    }
161    return -(low + 1);
162  }
163}
164
165class LightWeightMembers<K, V> {
166  hashs: Array<number>;
167  keys: Array<K>;
168  values: Array<V>;
169  constructor() {
170    this.hashs = [];
171    this.keys = [];
172    this.values = [];
173  }
174}
175class LightWeightClass<K, V> {
176  protected memberNumber: number;
177  protected members: LightWeightMembers<K, V>;
178  protected capacity: number = 8;
179  constructor() {
180    this.memberNumber = 0;
181    this.members = new LightWeightMembers<K, V>();
182  }
183
184  protected addmember(key: K, value: V = key as unknown as V) {
185    let hash = hashCode(key);
186    let index = this.binarySearchAtLightWeight(hash);
187    if (index >= 0) {
188      this.members.keys[index] = key;
189      this.members.values[index] = value;
190    } else {
191      index = ~index;
192      insert(this.members.hashs, index, hash);
193      insert(this.members.keys, index, key);
194      insert(this.members.values, index, value);
195      this.memberNumber++;
196    }
197    if (this.capacity < this.memberNumber) this.ensureCapacity(1);
198  }
199
200  protected getIndexByKey(key: K): number {
201    let hash = hashCode(key);
202    let index = this.binarySearchAtLightWeight(hash);
203    // js ( A negative number indicates an inverted number in the array )
204    if (index < 0 || index >= this.memberNumber) return -1;
205    return index;
206  }
207
208  protected deletemember(key: K): V {
209    let result: any = undefined;
210    let index = this.getIndexByKey(key);
211    if (index < 0) return result;
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
218  protected ensureCapacity(addCapacity: number = 1) {
219    let tempCapacity = this.capacity + addCapacity;
220    while (this.capacity < tempCapacity) {
221      this.capacity = 2 * this.capacity;
222    }
223  }
224
225  protected getIndex(key: K): number {
226    let hash = hashCode(key);
227    let index = this.binarySearchAtLightWeight(hash);
228    if (index < 0) index = ~index;
229    return index;
230  }
231
232  protected keyValueStringArray(): Array<string> {
233    let resultArray: Array<string> = [];
234    for (let i = 0; i < this.memberNumber; i++) {
235      resultArray.push(JSON.stringify(this.members.keys[i]) + ":" + JSON.stringify(this.members.values[i]));
236    }
237    return resultArray;
238  }
239
240  protected binarySearchAtLightWeight(hash: number, startIndex: number = 0, endIndex: number = this.memberNumber): number {
241    let low = startIndex;
242    let high = endIndex - 1;
243    while (low <= high) {
244      let mid = (low + high) >>> 1;
245      let midVal = this.members.hashs[mid];
246      if (midVal < hash) {
247        low = mid + 1;
248      } else {
249        if (midVal <= hash) {
250          return mid;
251        }
252        high = mid - 1;
253      }
254    }
255    return -(low + 1);
256  }
257}
258
259type RBTreeNodeColor = 0 | 1;
260const BLACK = 0;
261const RED = 1;
262class RBTreeNode<K, V> extends Pair<K, V>{
263  color: RBTreeNodeColor;
264  left: RBTreeNode<K, V> | undefined;
265  right: RBTreeNode<K, V> | undefined;
266  parent: RBTreeNode<K, V> | undefined;
267  constructor(key: K,
268    value?: V,
269    color: RBTreeNodeColor = RED,
270    parent?: RBTreeNode<K, V>,
271    left?: RBTreeNode<K, V>,
272    right?: RBTreeNode<K, V>) {
273    super(key, value);
274    this.color = color;
275    this.left = left;
276    this.right = right;
277    this.parent = parent;
278  }
279}
280class RBTreeClass<K, V> {
281  private root: RBTreeNode<K, V> | undefined;
282  public memberNumber: number;
283  private isChange: boolean;
284  private treeNodeArray: Array<RBTreeNode<K, V>>;
285  private compFun: CompFun<K> | undefined;
286  constructor(comparator?: CompFun<K>, root?: RBTreeNode<K, V>) {
287    this.root = root;
288    this.compFun = comparator;
289    this.memberNumber = 0;
290    this.isChange = true;
291    this.treeNodeArray = [];
292  }
293
294  get keyValueArray() {
295    let result = this.recordByMinToMax();
296    return result;
297  }
298
299  addNode(key: K, value: V = key as unknown as V): RBTreeClass<K, V> {
300    if (this.root === undefined) {
301      this.root = new RBTreeNode<K, V>(key, value);
302      this.setColor(BLACK, this.root);
303      this.memberNumber++;
304      this.isChange = true;
305    } else {
306      this.addProcess(key, value)
307    }
308    return this;
309  }
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
340  removeNode(key: K): V | undefined {
341    const removeNode = this.getNode(key);
342    if (removeNode === undefined) {
343      return undefined;
344    } else {
345      let result = removeNode.value;
346      this.removeNodeProcess(removeNode);
347      return result;
348    }
349  }
350
351  removeNodeProcess(removeNode: RBTreeNode<K, V>) {
352    if (removeNode.left !== undefined && removeNode.right !== undefined) {
353      let successor = removeNode.right;
354      while (successor.left !== undefined) {
355        successor = successor.left;
356      }
357      removeNode.key = successor.key;
358      removeNode.value = successor.value;
359      this.removeNodeProcess(successor); // only once
360      return;
361    } else {  // one or zero child
362      let 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
398  getNode(key: K): RBTreeNode<K, V> | undefined {
399    if (this.root === undefined)
400      return undefined;
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
409  findNode(value: V): RBTreeNode<K, V> | undefined {
410    let tempNode: RBTreeNode<K, V> | undefined = undefined;
411    this.recordByMinToMax();
412    for (let i = 0; i < this.memberNumber; i++) {
413      if (this.treeNodeArray[i].value === value) {
414        tempNode = this.treeNodeArray[i];
415        break;
416      }
417    }
418    return tempNode;
419  }
420
421  firstNode(): RBTreeNode<K, V> | undefined {
422    let tempNode: RBTreeNode<K, V> | undefined = this.root;
423    while (tempNode !== undefined && tempNode.left !== undefined) {
424      tempNode = tempNode.left;
425    }
426    return tempNode;
427  }
428
429  lastNode(): RBTreeNode<K, V> | undefined {
430    let tempNode: RBTreeNode<K, V> | undefined = this.root;
431    while (tempNode !== undefined && tempNode.right !== undefined) {
432      tempNode = tempNode.right;
433    }
434    return tempNode;
435  }
436
437  isEmpty(): boolean {
438    return this.root === undefined;
439  }
440
441  setAll(map: RBTreeClass<K, V>) {
442    let tempArray = map.recordByMinToMax();
443    for (let i = 0; i < map.memberNumber; i++) {
444      this.addNode(tempArray[i].key, tempArray[i].value);
445    }
446  }
447
448  clearTree() {
449    this.root = undefined;
450    this.memberNumber = 0;
451  }
452
453  private recordByMinToMax(): Array<RBTreeNode<K, V>> {
454    if (!this.isChange) return this.treeNodeArray;
455    let stack = [];
456    this.treeNodeArray = [];
457    let node = this.root;
458    while (node != undefined || stack.length) {
459      while (node != undefined) {
460        stack.push(node);
461        node = node.left;
462      }
463      let tempNode = stack.pop();
464      if (tempNode === undefined || tempNode === undefined)
465        throw new Error("this function run error");
466      node = tempNode;
467      this.treeNodeArray.push(node);
468      node = node.right;
469    }
470    this.isChange = false;
471    this.memberNumber = this.treeNodeArray.length;
472    return this.treeNodeArray;
473  }
474
475  private lRotate(datumPointNode: RBTreeNode<K, V>): RBTreeClass<K, V> {
476    let newTopNode = datumPointNode.right;
477    if (newTopNode === undefined)
478      throw new Error("[rotate right error]: the right child node of the base node === undefined")
479    datumPointNode.right = newTopNode.left;
480    datumPointNode.right !== undefined ? datumPointNode.right.parent = datumPointNode : "";
481    newTopNode.parent = datumPointNode.parent;
482    if (datumPointNode.parent === undefined) {
483      this.root = newTopNode;
484    } else if (datumPointNode.parent.left === datumPointNode) {
485      datumPointNode.parent.left = newTopNode;
486    } else if (datumPointNode.parent.right === datumPointNode) {
487      datumPointNode.parent.right = newTopNode;
488    }
489    datumPointNode.parent = newTopNode;
490    newTopNode.left = datumPointNode;
491    return this;
492  }
493
494  private rRotate(datumPointNode: RBTreeNode<K, V>): RBTreeClass<K, V> {
495    const newTopNode = datumPointNode.left;
496    if (newTopNode === undefined) {
497      throw new Error("[rotate right error]: the left child node of the base node === undefined")
498    }
499    datumPointNode.left = newTopNode.right;
500    datumPointNode.left !== undefined ? datumPointNode.left.parent = datumPointNode : "";
501    newTopNode.parent = datumPointNode.parent
502    if (datumPointNode.parent === undefined) {
503      this.root = newTopNode;
504    } else if (datumPointNode === datumPointNode.parent.left) {
505      datumPointNode.parent.left = newTopNode;
506    } else if (datumPointNode === datumPointNode.parent.right) {
507      datumPointNode.parent.right = newTopNode;
508    }
509    datumPointNode.parent = newTopNode;
510    newTopNode.right = datumPointNode;
511    return this;
512  }
513
514  private insertRebalance(fixNode: RBTreeNode<K, V>): RBTreeClass<K, V> {
515    let parentNode = fixNode.parent;
516    while (this.getColor(parentNode) === RED &&
517      parentNode !== undefined &&
518      parentNode.parent !== undefined) {
519      let grandpaNode = parentNode && parentNode.parent;
520      if (parentNode === grandpaNode.left &&
521        this.getColor(grandpaNode.right) === BLACK &&
522        fixNode === parentNode.left) {
523        this
524          .setColor(BLACK, parentNode)
525          .setColor(RED, grandpaNode)
526          .rRotate(grandpaNode)
527        break;
528      } else if (parentNode === grandpaNode.left &&
529        this.getColor(grandpaNode.right) === BLACK &&
530        fixNode === parentNode.right) {
531        this
532          .setColor(BLACK, fixNode)
533          .setColor(RED, grandpaNode)
534          .lRotate(parentNode)
535          .rRotate(grandpaNode)
536        break;
537      } else if (parentNode === grandpaNode.right &&
538        this.getColor(grandpaNode.left) === BLACK &&
539        fixNode === parentNode.left) {
540        this
541          .setColor(BLACK, fixNode)
542          .setColor(RED, grandpaNode)
543          .rRotate(parentNode)
544          .lRotate(grandpaNode)
545        break;
546      } else if (parentNode === grandpaNode.right &&
547        this.getColor(grandpaNode.left) === BLACK &&
548        fixNode === parentNode.right) {
549        this
550          .setColor(BLACK, parentNode)
551          .setColor(RED, grandpaNode)
552          .lRotate(grandpaNode)
553        break;
554      } else if ((parentNode === grandpaNode.right && this.getColor(grandpaNode.left) === RED) ||
555        (parentNode === grandpaNode.left && this.getColor(grandpaNode.right) === RED)) {
556        this
557          .setColor(BLACK, parentNode)
558          .setColor(BLACK, parentNode === grandpaNode.left ? grandpaNode.right : grandpaNode.left)
559          .setColor(RED, grandpaNode)
560        fixNode = grandpaNode;
561        parentNode = fixNode.parent;
562      } else {
563        throw new Error("Exceptions after adding")
564      }
565    }
566    this.root ? this.root.color = BLACK : "";
567    return this;
568  }
569
570  private deleteRebalance(fixNode: RBTreeNode<K, V>) {
571    while (this.getColor(fixNode) === BLACK && fixNode !== this.root && fixNode.parent) {
572      let sibling: RBTreeNode<K, V> | undefined;
573      if (fixNode === fixNode.parent.left) {
574        sibling = fixNode.parent.right;
575        if (this.getColor(sibling) === RED) {
576          this
577            .setColor(RED, fixNode.parent)
578            .setColor(BLACK, sibling)
579            .lRotate(fixNode.parent)
580          sibling = fixNode.parent.right;
581        }
582        if (sibling === undefined) {
583          throw new Error('Error sibling node is undefined')
584        }
585        if (this.getColor(sibling.left) === BLACK && this.getColor(sibling.right) === BLACK) {
586          this.setColor(RED, sibling)
587          fixNode = fixNode.parent
588        } else if (this.getColor(sibling.left) === RED && this.getColor(sibling.right) === BLACK) {
589          this
590            .setColor(RED, sibling)
591            .setColor(BLACK, sibling.left)
592            .rRotate(sibling);
593          sibling = fixNode.parent.right
594          if (sibling === undefined) {
595            throw new Error('Error sibling node is empty')
596          }
597          this
598            .setColor(fixNode.parent.color, sibling)
599            .setColor(BLACK, fixNode.parent)
600            .setColor(BLACK, sibling.right)
601            .lRotate(fixNode.parent);
602          break;
603        } else if (this.getColor(sibling.right) === RED) {
604          this
605            .setColor(fixNode.parent.color, sibling)
606            .setColor(BLACK, fixNode.parent)
607            .setColor(BLACK, sibling.right)
608            .lRotate(fixNode.parent);
609          break;
610        } else {
611          throw new Error("Adjust the error after the error is deleted")
612        }
613      } else {
614        sibling = fixNode.parent.left;
615        if (this.getColor(sibling) === RED) {
616          this
617            .setColor(BLACK, sibling)
618            .setColor(RED, fixNode.parent)
619            .rRotate(fixNode.parent);
620          sibling = fixNode.parent.left;
621        }
622        if (sibling === undefined) {
623          throw new Error('Error sibling node is undefined')
624        }
625        if (this.getColor(sibling.left) === BLACK && this.getColor(sibling.right) === BLACK) {
626          this
627            .setColor(RED, sibling)
628          fixNode = fixNode.parent;
629        } else if (this.getColor(sibling.left) === BLACK && this.getColor(sibling.right) === RED) {
630          this
631            .setColor(RED, sibling)
632            .setColor(BLACK, sibling.right)
633            .lRotate(sibling);
634          sibling = fixNode.parent.left;
635          if (sibling === undefined) {
636            throw new Error('Adjust the error after the error is deleted')
637          }
638          this
639            .setColor(fixNode.parent.color, sibling)
640            .setColor(BLACK, fixNode.parent)
641            .setColor(BLACK, sibling.left)
642            .rRotate(fixNode.parent);
643          break;
644        } else if (this.getColor(sibling.left) === RED) {
645          this
646            .setColor(fixNode.parent.color, sibling)
647            .setColor(BLACK, fixNode.parent,)
648            .setColor(BLACK, sibling.left)
649            .rRotate(fixNode.parent);
650          break;
651        } else {
652          throw new Error("Adjust the error after the error is deleted")
653        }
654      }
655    }
656    this.setColor(BLACK, fixNode)
657  }
658
659  private getColor(node: RBTreeNode<K, V> | undefined): RBTreeNodeColor {
660    return node === undefined ? BLACK : node.color;
661  }
662
663  private setColor(color: RBTreeNodeColor, node: RBTreeNode<K, V> | undefined): RBTreeClass<K, V> {
664    if (node === undefined) {
665      throw new Error("Wrong color setting")
666    } else {
667      node.color = color
668    }
669    return this;
670  }
671}
672
673const MAXcapacity = 1 << 30;
674const LOADER_FACTOR = 0.75;
675class DictionaryClass<K, V>  {
676  private tableLink: { [hashIndex: number]: LinkedList<Pair<K, V>> | RBTreeClass<K, V> };
677  protected memberNumber: number;
678  private isChange: boolean;
679  private memberArray: Array<Pair<K, V>>;
680  private capacity: number;
681  constructor() {
682    this.tableLink = {};
683    this.memberNumber = 0;
684    this.isChange = true;
685    this.memberArray = [];
686    this.capacity = 16;
687  }
688
689  get keyValueArray() {
690    let result = this.keyValues();
691    return result;
692  }
693
694  protected getHashIndex(key: K): number {
695    let h;
696    let hash = ((key === null) ? 0 : ((h = hashCode(key)) ^ (h >>> 16)));
697    if (this.expandCapacity()) {
698      this.keyValues();
699      this.memberNumber = 0;
700      this.tableLink = {};
701      this.isChange = true;
702      for (let item of this.memberArray) {
703        this.put(item.key, item.value);
704      }
705      this.memberNumber++;
706    }
707    let n = this.power(this.capacity);
708    return (n - 1) & hash;
709  }
710
711  private power(size: number) {
712    let n = 1;
713    let temp = size;
714    while (temp >>> 1 != 1) {
715      n++;
716      temp = temp >>> 1;
717    }
718    return n;
719  }
720
721  private keyValues(): Pair<K, V>[] {
722    if (!this.isChange) return this.memberArray;
723    this.memberArray = [];
724    const keys = Object.keys(this.tableLink).map((item) => parseInt(item));
725    for (let i = 0; i < keys.length; i++) {
726      const members = this.tableLink[keys[i]];
727      if (members instanceof RBTreeClass) {
728        let tempArray = members.keyValueArray;
729        for (let i = 0; i < members.memberNumber; i++) {
730          this.memberArray.push(new Pair(tempArray[i].key, tempArray[i].value));
731        }
732      } else {
733        if (members != undefined && !members.isEmpty()) {
734          let current = members.getHead();
735          while (current != undefined) {
736            this.memberArray.push(current.element);
737            current = current.next;
738          }
739        }
740      }
741    }
742    this.memberNumber = this.memberArray.length;
743    let valuePairs = this.memberArray;
744    return valuePairs;
745  }
746
747  protected expandCapacity() {
748    let capacityChange = false;
749    while (this.capacity < this.memberNumber / LOADER_FACTOR && this.capacity < MAXcapacity) {
750      this.capacity = 2 * this.capacity;
751      capacityChange = true;
752    }
753    return capacityChange;
754  }
755
756  protected put(key: K, value: V = key as unknown as V): boolean {
757
758    this.isChange = true;
759    if (!this.hasKey(key)) this.memberNumber++;
760    const position = this.getHashIndex(key);
761    let members = this.tableLink[position];
762    if (members instanceof LinkedList && members.count >= 8) {
763      let newElement = new RBTreeClass<K, V>();
764      let current = members.getHead();
765      while (current != null || current != undefined) {
766        if (!(current.element instanceof Pair)) return false;
767        newElement.addNode(current.element.key, current.element.value);
768        current = current.next;
769      }
770      newElement.addNode(key, value);
771      this.tableLink[position] = newElement;
772      return true;
773    } else if (members instanceof RBTreeClass) {
774      members.addNode(key, value);
775      this.tableLink[position] = members;
776      return true;
777    } else {
778      if (this.tableLink[position] == undefined) {
779        members = new LinkedList<Pair<K, V>>();
780      }
781      if (!this.replaceMember(key, value)) {
782        members.push(new Pair(key, value));
783        this.tableLink[position] = members;
784      }
785      return true;
786    }
787  }
788
789  protected replaceMember(key: K, value: V = key as unknown as V): boolean {
790    const position = this.getHashIndex(key);
791    const members = this.tableLink[position] as LinkedList<Pair<K, V>>;
792    if (members === null || members === undefined) return false;
793    let 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
804  protected getValueByKey(key: K): V | undefined {
805    const position = this.getHashIndex(key);
806    const members = this.tableLink[position];
807    if (members instanceof RBTreeClass) {
808      let resultNode = members.getNode(key);
809      if (resultNode === undefined) return undefined;
810      return resultNode.value;
811    } else {
812      if (members != undefined && !members.isEmpty()) {
813        members as LinkedList<Pair<K, V>>;
814        let current = members.getHead();
815        while (current != undefined) {
816          if (current.element.key === key) {
817            return current.element.value;
818          }
819          current = current.next;
820        }
821      }
822    }
823    return undefined;
824  }
825
826  protected removeMember(key: K): V | undefined {
827    const position = this.getHashIndex(key);
828    const members = this.tableLink[position];
829    if (members instanceof RBTreeClass) {
830      let result = members.removeNode(key);
831      if (result != undefined) {
832        this.isChange = true;
833        this.memberNumber--;
834        return result;
835      }
836    } else {
837      if (members != undefined && !members.isEmpty()) {
838        let current = members.getHead();
839        while (current != undefined) {
840          if (current.element.key === key) {
841            const result = current.element.value;
842            members.remove(current.element);
843            if (members.isEmpty()) {
844              delete this.tableLink[position];
845            }
846            this.isChange = true;
847            this.memberNumber--;
848            return result;
849          }
850          current = current.next;
851        }
852      }
853    }
854    return undefined;
855  }
856
857  protected clear() {
858    this.tableLink = {};
859    this.memberNumber = 0;
860    this.isChange = true;
861    this.capacity = 16;
862  }
863
864  protected hasKey(key: K): boolean {
865    const position = this.getHashIndex(key);
866    const members = this.tableLink[position];
867    if (members === undefined || members === undefined) return false;
868    if (members instanceof RBTreeClass) {
869      return members.getNode(key) !== undefined;
870    }
871    let current = members.getHead();
872    while (current != undefined && current != undefined) {
873      if (current.element.key === key) {
874        return true;
875      }
876      current = current.next;
877    }
878    return false;
879  }
880
881  protected setAll(map: DictionaryClass<K, V>): void {
882    let memebers = map.keyValues();
883    for (let i = 0; i < memebers.length; i++) {
884      this.put(memebers[i].key, memebers[i].value);
885    }
886  }
887
888  protected Values(): V[] {
889    const values = [];
890    const valuePairs = this.keyValues();
891    for (let i = 0; i < valuePairs.length; i++) {
892      values.push(valuePairs[i].value);
893    }
894    return values;
895  }
896}
897
898class Node<T> {
899  element: T;
900  next: Node<T> | undefined;
901  constructor(element: T, next?: Node<T>) {
902    this.element = element;
903    this.next = next;
904  }
905}
906class LinkedList<T> {
907  public count: number;
908  protected next: Node<T> | undefined;
909  protected head: Node<T> | undefined;
910  constructor() {
911    this.count = 0;
912    this.next = undefined;
913    this.head = undefined;
914  }
915
916  push(element: T) {
917    const node = new Node(element);
918    let current;
919    if (this.head == undefined) {
920      this.head = node;
921    } else {
922      current = this.head;
923      while (current.next != undefined) {
924        current = current.next;
925      }
926      current.next = node;
927    }
928    this.count++;
929  }
930
931  removeAt(index: number) {
932    if (index >= 0 && index < this.count) {
933      let current = this.head;
934      if (index === 0 && current != undefined) {
935        this.head = current.next;
936      } else {
937        const previous = this.getElementAt(index--);
938        if (previous !== undefined) {
939          current = previous.next;
940          previous.next = (current === undefined ? undefined : current.next);
941        }
942      }
943      if (current !== undefined) {
944        this.count--;
945        return current.element;
946      }
947    }
948    return undefined;
949  }
950
951  getElementAt(index: number) {
952    if (index > 0 && index < this.count) {
953      let current = this.head;
954      for (let i = 0; i < index && current != undefined; i++) {
955        current = current.next;
956      }
957      return current;
958    }
959    return undefined;
960  }
961
962  insert(element: T, index: number) {
963    if (index >= 0 && index <= this.count) {
964      const node = new Node(element);
965      if (index === 0) {
966        node.next = this.head;
967        this.head = node;
968      } else {
969        const previous = this.getElementAt(index--);
970        if (previous === undefined)
971          throw new Error("data storage error");
972        node.next = previous.next;
973        previous.next = node;
974      }
975      this.count++;
976      return true;
977    }
978    return false;
979  }
980
981  indexOf(element: T, compareFn?: CompFun<T>) {
982    let current = this.head;
983    for (let i = 0; i < this.count && current != undefined; i++) {
984      if (currencyCompare(element, current.element, compareFn) === ComparResult.EQUALS) {
985        return i;
986      }
987      current = current.next;
988    }
989    return -1;
990  }
991
992  remove(element: T, compareFn?: CompFun<T>) {
993    this.removeAt(this.indexOf(element, compareFn));
994  }
995
996  clear() {
997    this.head = undefined;
998    this.count = 0;
999  }
1000
1001  isEmpty() {
1002    return this.count === 0;
1003  }
1004
1005  getHead() {
1006    return this.head;
1007  }
1008
1009  toString() {
1010    if (this.head == undefined) {
1011      return "";
1012    }
1013    let objString = `${this.head.element}`;
1014    let current = this.head.next;
1015    for (let i = 1; i < this.count && current != undefined; i++) {
1016      objString = `${objString}, ${current.element}`;
1017      current = current.next;
1018    }
1019    return objString;
1020  }
1021}
1022
1023export default {
1024  isIncludeToArray,
1025  LightWeightClass,
1026  PlainArrayClass,
1027  RBTreeClass,
1028  DictionaryClass
1029}
1030
1031