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