MinHeap.ts 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546
  1. import { IllegalStateException, cast_java_lang_IllegalStateException } from '../../../java/lang/IllegalStateException';
  2. import { MinHeapIterator, cast_de_nrw_schule_svws_core_adt_tree_MinHeapIterator } from '../../../core/adt/tree/MinHeapIterator';
  3. import { StringBuilder, cast_java_lang_StringBuilder } from '../../../java/lang/StringBuilder';
  4. import { JavaString, cast_java_lang_String } from '../../../java/lang/JavaString';
  5. import { System, cast_java_lang_System } from '../../../java/lang/System';
  6. import { Comparator, cast_java_util_Comparator } from '../../../java/util/Comparator';
  7. import { JavaInteger, cast_java_lang_Integer } from '../../../java/lang/JavaInteger';
  8. import { NullPointerException, cast_java_lang_NullPointerException } from '../../../java/lang/NullPointerException';
  9. import { JavaIterator, cast_java_util_Iterator } from '../../../java/util/JavaIterator';
  10. import { Collection, cast_java_util_Collection } from '../../../java/util/Collection';
  11. import { Cloneable, cast_java_lang_Cloneable } from '../../../java/lang/Cloneable';
  12. import { JavaObject, cast_java_lang_Object } from '../../../java/lang/JavaObject';
  13. import { Arrays, cast_java_util_Arrays } from '../../../java/util/Arrays';
  14. import { Queue, cast_java_util_Queue } from '../../../java/util/Queue';
  15. import { IllegalArgumentException, cast_java_lang_IllegalArgumentException } from '../../../java/lang/IllegalArgumentException';
  16. import { NoSuchElementException, cast_java_util_NoSuchElementException } from '../../../java/util/NoSuchElementException';
  17. import { CloneNotSupportedException, cast_java_lang_CloneNotSupportedException } from '../../../java/lang/CloneNotSupportedException';
  18. export class MinHeap<T> extends JavaObject implements Queue<T>, Cloneable {
  19. private _size : number = 0;
  20. private _nodes : Array<T | null> = Array(0).fill(null);
  21. private readonly _comparator : Comparator<T>;
  22. private readonly _initialCapacity : number;
  23. protected _modCount : number = 0;
  24. /**
  25. * Erzeugt einen neuen Minimum-Heap mit dem übergebenen {@link Comparator} und
  26. * der übergebenen initialen Kapazität.
  27. *
  28. * @param comparator das Objekt zum Vergleich von zwei Objekten des Typ T
  29. * @param initialCapacity die initiale Kapazität des Baums
  30. */
  31. public constructor(comparator : Comparator<T>, initialCapacity : number);
  32. /**
  33. * Erzeugt einen neuen Minimum-Heap mit dem übergebenen {@link Comparator} und
  34. * einer initialen Kapazität von 63.
  35. *
  36. * @param comparator das Objekt zum Vergleich von zwei Objekten des Typ T
  37. */
  38. public constructor(comparator : Comparator<T>);
  39. /**
  40. * Erstellt eine Kopie des als Parameter übergebenen Heaps.
  41. *
  42. * @param original Das zu kopierende Original
  43. */
  44. public constructor(original : MinHeap<T>);
  45. /**
  46. * Implementation for method overloads of 'constructor'
  47. */
  48. public constructor(__param0 : Comparator<T> | MinHeap<T>, __param1? : number) {
  49. super();
  50. if (((typeof __param0 !== "undefined") && ((typeof __param0 !== 'undefined') && (__param0 instanceof Object) && (__param0 !== null) && ('compare' in __param0) && (typeof __param0.compare === 'function')) || (__param0 === null)) && ((typeof __param1 !== "undefined") && typeof __param1 === "number")) {
  51. let comparator : Comparator<T> = cast_java_util_Comparator(__param0);
  52. let initialCapacity : number = __param1 as number;
  53. if (initialCapacity <= 0)
  54. throw new IllegalArgumentException("Die initiale Kapazität muss größer als 0 sein.")
  55. this._comparator = comparator;
  56. this._initialCapacity = initialCapacity;
  57. this._modCount = 0;
  58. } else if (((typeof __param0 !== "undefined") && ((typeof __param0 !== 'undefined') && (__param0 instanceof Object) && (__param0 !== null) && ('compare' in __param0) && (typeof __param0.compare === 'function')) || (__param0 === null)) && (typeof __param1 === "undefined")) {
  59. let comparator : Comparator<T> = cast_java_util_Comparator(__param0);
  60. this._comparator = comparator;
  61. this._initialCapacity = 63;
  62. this._modCount = 0;
  63. } else if (((typeof __param0 !== "undefined") && ((__param0 instanceof JavaObject) && (__param0.isTranspiledInstanceOf('de.nrw.schule.svws.core.adt.tree.MinHeap'))) || (__param0 === null)) && (typeof __param1 === "undefined")) {
  64. let original : MinHeap<T> = cast_de_nrw_schule_svws_core_adt_tree_MinHeap(__param0);
  65. this._comparator = original._comparator;
  66. this._initialCapacity = original._initialCapacity;
  67. this._nodes = Arrays.copyOf(original._nodes, original._nodes.length);
  68. this._size = original._size;
  69. this._modCount = original._modCount;
  70. } else throw new Error('invalid method overload');
  71. }
  72. public add(e : T) : boolean {
  73. if (e === null)
  74. return false;
  75. if (this._nodes.length === 0)
  76. this._nodes = this.newArray(e, this._initialCapacity);
  77. if (this._size === this._nodes.length)
  78. this.grow();
  79. this._nodes[this._size] = e;
  80. this.heapifyUp(this._size++);
  81. this._modCount++;
  82. return true;
  83. }
  84. public element() : T {
  85. if ((this._size === 0) || (this._nodes[0] === null))
  86. throw new NoSuchElementException()
  87. return this._nodes[0];
  88. }
  89. public offer(e : T) : boolean {
  90. return this.add(e);
  91. }
  92. public peek() : T | null {
  93. return this._nodes.length === 0 ? null : this._nodes[0];
  94. }
  95. public poll() : T | null {
  96. if (this._size === 0)
  97. return null;
  98. let elem : T | null = this._nodes[0];
  99. this._nodes[0] = this._nodes[--this._size];
  100. this._nodes[this._size] = null;
  101. this.heapifyDown(0);
  102. this._modCount++;
  103. return elem;
  104. }
  105. public remove() : T;
  106. public remove(o : unknown | null) : boolean;
  107. /**
  108. * Implementation for method overloads of 'remove'
  109. */
  110. public remove(__param0? : null | unknown) : T | boolean {
  111. if ((typeof __param0 === "undefined")) {
  112. let result : T | null = this.poll();
  113. if (result === null)
  114. throw new NoSuchElementException()
  115. return result;
  116. } else if (((typeof __param0 !== "undefined") && ((__param0 instanceof Object) || ((__param0 instanceof JavaObject) && (__param0.isTranspiledInstanceOf('java.lang.Object')))) || (__param0 === null))) {
  117. let o : unknown | null = (__param0 instanceof JavaObject) ? cast_java_lang_Object(__param0) : __param0;
  118. if (o === null)
  119. return false;
  120. let index : number = this.findIndex(o);
  121. if (index === -1)
  122. return false;
  123. this._size--;
  124. this._modCount++;
  125. if (index === this._size)
  126. return true;
  127. this._nodes[index] = this._nodes[this._size];
  128. this._nodes[this._size] = null;
  129. this.heapifyUp(index);
  130. this.heapifyDown(index);
  131. return true;
  132. } else throw new Error('invalid method overload');
  133. }
  134. public size() : number {
  135. return this._size;
  136. }
  137. public isEmpty() : boolean {
  138. return this._size === 0;
  139. }
  140. public contains(o : unknown | null) : boolean {
  141. if (o === null)
  142. return false;
  143. for (let i : number = 0; i < this._size; i++){
  144. if (JavaObject.equalsTranspiler(this._nodes[i], (o)))
  145. return true;
  146. }
  147. return false;
  148. }
  149. public containsAll(c : Collection<unknown> | null) : boolean {
  150. if (c === null)
  151. return true;
  152. if (this as unknown === c as unknown)
  153. return true;
  154. for (let o of c)
  155. if (!this.contains(o))
  156. return false;
  157. return true;
  158. }
  159. public addAll(c : Collection<T> | null) : boolean {
  160. if (c === null)
  161. return false;
  162. if (this as unknown === c as unknown) {
  163. if (this._size === 0)
  164. return false;
  165. let tmp : Array<T | null> = Arrays.copyOf(this._nodes, this._size);
  166. for (let t of tmp)
  167. if (t !== null)
  168. this.add(t);
  169. return true;
  170. }
  171. let result : boolean = false;
  172. for (let t of c) {
  173. if (this.add(t))
  174. result = true;
  175. }
  176. return result;
  177. }
  178. public removeAll(c : Collection<unknown> | null) : boolean {
  179. if (c === null)
  180. return false;
  181. if (this as unknown === c as unknown) {
  182. if (this.size() === 0)
  183. return false;
  184. this.clear();
  185. return true;
  186. }
  187. let result : boolean = false;
  188. for (let o of c) {
  189. if (this.remove(o)) {
  190. result = true;
  191. while (this.remove(o)) ;
  192. }
  193. }
  194. return result;
  195. }
  196. public retainAll(c : Collection<unknown> | null) : boolean {
  197. if (this._size === 0)
  198. return false;
  199. if (c === null) {
  200. this.clear();
  201. return true;
  202. }
  203. if (this as unknown === c as unknown)
  204. return false;
  205. let tmp : Array<T | null> = this.newArray(this._nodes[0], this._nodes.length);
  206. if (tmp === null)
  207. return false;
  208. let i : number = 0;
  209. let elem : T | null;
  210. let changed : boolean = false;
  211. while ((elem = this.poll()) !== null) {
  212. if (c.contains(elem))
  213. tmp[i++] = elem; else
  214. changed = true;
  215. }
  216. this._nodes = tmp;
  217. this._size = i;
  218. this._modCount++;
  219. return changed;
  220. }
  221. public clear() : void {
  222. this._nodes = Array(0).fill(null);
  223. this._size = 0;
  224. this._modCount++;
  225. }
  226. public toArray() : Array<unknown>;
  227. public toArray<U>(a : Array<U>) : Array<U>;
  228. /**
  229. * Implementation for method overloads of 'toArray'
  230. */
  231. public toArray<U>(__param0? : Array<U>) : Array<U> | Array<unknown> {
  232. if ((typeof __param0 === "undefined")) {
  233. return this.copyNodes();
  234. } else if (((typeof __param0 !== "undefined") && Array.isArray(__param0))) {
  235. let a : Array<U> = __param0;
  236. if (a.length < this._size)
  237. return this.copyNodes();
  238. System.arraycopy(this._nodes, 0, a, 0, this._size);
  239. Arrays.fill(a, this._size, a.length, null);
  240. return a;
  241. } else throw new Error('invalid method overload');
  242. }
  243. public iterator() : JavaIterator<T> {
  244. return new MinHeapIterator(this._nodes, this);
  245. }
  246. public clone() : unknown {
  247. return new MinHeap(this);
  248. }
  249. /**
  250. * Gibt den {@link Comparator} des Minimum Heaps zurück.
  251. *
  252. * @return der Comparator
  253. */
  254. public comparator() : Comparator<T> {
  255. return this._comparator;
  256. }
  257. /**
  258. * Gibt die aktuelle Kapazität des Arrays zurück.
  259. *
  260. * @return die aktuelle Kapazität des Arrays zurück
  261. */
  262. public capacity() : number {
  263. return (this._nodes.length === 0) ? this._initialCapacity : this._nodes.length;
  264. }
  265. /**
  266. * Gibt den Inhalt des Minimum Heaps in einem sortierten Array zurück.
  267. *
  268. * @return ein sortiertes Array mit den Elementen des Minimum Heaps.
  269. */
  270. public toSortedArray() : Array<T> {
  271. if (this._size === 0)
  272. return Array(0).fill(null);
  273. let copy : MinHeap<T> = new MinHeap(this);
  274. let tmp : Array<T> = this.newArray(this._nodes[0], this._size);
  275. let current : T | null;
  276. let i : number = 0;
  277. while ((current = copy.poll()) !== null)
  278. tmp[i++] = current;
  279. return tmp;
  280. }
  281. /**
  282. * Gibt den Inhalt des Heaps als Array-Repräsentation aus.
  283. *
  284. * @return der Inhalt des Heaps
  285. */
  286. public toString() : String {
  287. let sb : StringBuilder = new StringBuilder();
  288. for (let i : number = 0; i < this._size; i++){
  289. sb.append(this._nodes[i]);
  290. if (i !== this._size - 1)
  291. sb.append(", ");
  292. }
  293. return sb.toString();
  294. }
  295. /**
  296. * Ermittelt eine Hash-Code für dieses Objekt basierend auf den gespeicherten
  297. * Daten im Heap (die konkrete Ordnung des Baumes wird nicht unterschieden).
  298. *
  299. * @return der Hashcode des Minimum Heaps
  300. */
  301. public hashCode() : number {
  302. return Arrays.deepHashCode(this.toSortedArray());
  303. }
  304. /**
  305. * Prüft, ob das übergebene Objekt ein Minimum-Heap ist, der
  306. * die gleichen Elemente mit der gleichen Ordnung beinhaltet.
  307. *
  308. * @param obj das zu vergleichende Objekt
  309. */
  310. public equals(obj : unknown | null) : boolean {
  311. if (this as unknown === obj as unknown)
  312. return true;
  313. if (obj === null)
  314. return false;
  315. if (((obj instanceof JavaObject) && (obj.isTranspiledInstanceOf('de.nrw.schule.svws.core.adt.tree.MinHeap')))) {
  316. let other : MinHeap<unknown> | null = cast_de_nrw_schule_svws_core_adt_tree_MinHeap(obj);
  317. return Arrays.deepEquals(this.toSortedArray(), other.toSortedArray());
  318. }
  319. return false;
  320. }
  321. /**
  322. * Liefert zum Index i den Index des Elter zurück.
  323. *
  324. * @param i
  325. *
  326. * @return den Index des Elter
  327. */
  328. private static getParentIndex(i : number) : number {
  329. return (i <= 0) ? -1 : Math.trunc((i - 1) / 2);
  330. }
  331. /**
  332. * Liefert zum Index i den Index des linken Kindes zurück.
  333. *
  334. * @param i
  335. *
  336. * @return den Index des linken Kindes
  337. */
  338. private static getLeftChildIndex(i : number) : number {
  339. return 2 * i + 1;
  340. }
  341. /**
  342. * Liefert zum Index i den Index des rechten Kindes zurück.
  343. *
  344. * @param i
  345. *
  346. * @return den Index des rechten Kindes
  347. */
  348. private static getRightChildIndex(i : number) : number {
  349. return 2 * i + 2;
  350. }
  351. /**
  352. * Tauscht die Elemente an den Stellen i und j im Array
  353. *
  354. * @param i
  355. * @param j
  356. */
  357. private swap(i : number, j : number) : void {
  358. let elem : T | null = this._nodes[i];
  359. this._nodes[i] = this._nodes[j];
  360. this._nodes[j] = elem;
  361. }
  362. /**
  363. * Stellt die Minimum Heap Eigenschaft vom Index i aus im Baum abwärts her.
  364. *
  365. * @param i ab diesem Index wird im Baum abwärts geprüft.
  366. */
  367. private heapifyDown(i : number) : void {
  368. let left : number = MinHeap.getLeftChildIndex(i);
  369. let right : number = MinHeap.getRightChildIndex(i);
  370. if (left >= this._size)
  371. return;
  372. let child : number = right;
  373. if (right === this._size) {
  374. child = left;
  375. } else {
  376. let nodeLeft : T | null = this._nodes[left];
  377. let nodeRight : T | null = this._nodes[right];
  378. if ((nodeLeft === null) || (nodeRight === null))
  379. return;
  380. if (this._comparator.compare(nodeLeft, nodeRight) < 0)
  381. child = left;
  382. }
  383. let nodeCurrent : T | null = this._nodes[i];
  384. let nodeChild : T | null = this._nodes[child];
  385. if ((nodeCurrent === null) || (nodeChild === null))
  386. throw new NullPointerException()
  387. if (this._comparator.compare(nodeCurrent, nodeChild) <= 0)
  388. return;
  389. this.swap(i, child);
  390. this.heapifyDown(child);
  391. }
  392. /**
  393. * Stellt die Minimum-Heap-Eigenschaft des Arrays ab Position i aufwärts wieder her.
  394. *
  395. * @param i ab diesem Index wird überprüft
  396. */
  397. private heapifyUp(i : number) : void {
  398. let parentIndex : number = MinHeap.getParentIndex(i);
  399. if (parentIndex < 0)
  400. return;
  401. let nodeCurrent : T | null = this._nodes[i];
  402. let nodeParent : T | null = this._nodes[parentIndex];
  403. if ((nodeCurrent === null) || (nodeParent === null) || (this._comparator.compare(nodeCurrent, nodeParent) >= 0))
  404. return;
  405. this.swap(i, parentIndex);
  406. this.heapifyUp(parentIndex);
  407. }
  408. /**
  409. * Erstellt ein neues Array vom Typ T mit der angegebenen Länge.
  410. *
  411. * @param elem Ein Element vom Typ T, welches als Vorlage für die Elemente des Arrays dient
  412. * @param length die Länge des neuen Arrays
  413. *
  414. * @return das neue Array
  415. */
  416. private newArray(elem : T | null, length : number) : Array<T> {
  417. if (elem === null)
  418. return Array(length).fill(null);
  419. return Array(length).fill(null);
  420. }
  421. /**
  422. * Erzeugt eine Kopie des internen Arrays _nodes.
  423. *
  424. * @return die Kopie des _nodes-Array.
  425. */
  426. private copyNodes() : Array<T> {
  427. let result : Array<T> = this.newArray(this._size <= 0 ? null : this._nodes[0], this._size);
  428. System.arraycopy(this._nodes, 0, result, 0, this._size);
  429. return result;
  430. }
  431. /**
  432. * Lässt den dem Baum zu Grunde liegenden Baum wachsen. Verdoppelt die Menge der Elemente, die im Heap
  433. * gespeichert werden können.
  434. *
  435. * Falls der Heap durch das Wachsen auf mehr als {@link Integer.MAX_VALUE} Elemente ansteigen würde,
  436. * wird eine IllegalStateException geworfen.
  437. *
  438. * @throws IllegalStateException
  439. */
  440. private grow() : void {
  441. if (this._nodes.length === Number.MAX_VALUE)
  442. throw new IllegalStateException("Der Minimum-Heap kann nicht mehr als " + Number.MAX_VALUE + " Elemente beinhalten.")
  443. let newLength : number = this._nodes.length * 2 + 1;
  444. if (newLength < 0)
  445. newLength = Number.MAX_VALUE;
  446. let tmp : Array<T> = this.newArray(this._nodes[0], newLength);
  447. System.arraycopy(this._nodes, 0, tmp, 0, this._size);
  448. this._nodes = tmp;
  449. }
  450. /**
  451. * Findet den Index an dem das Element t im dem dem Heap zu Grunde liegendem Array gespeichert ist.
  452. * Gibt -1 zurück, falls das Element nicht vorhanden ist.
  453. *
  454. * @param t zu diesem Element soll der Index gefunden werden
  455. *
  456. * @return der Index, falls das Element enthalten ist, ansonsten -1
  457. */
  458. private findIndex(obj : unknown | null) : number {
  459. if (obj === null)
  460. return -1;
  461. for (let i : number = 0; i < this._size; i++){
  462. if (JavaObject.equalsTranspiler(this._nodes[i], (obj)))
  463. return i;
  464. }
  465. return -1;
  466. }
  467. /**
  468. * Gibt die Anzahl der Operationen zurück, die diese Datenstruktur
  469. * verändert haben.
  470. *
  471. * @return die Anzahl der Operationen
  472. */
  473. getModCount() : number {
  474. return this._modCount;
  475. }
  476. isTranspiledInstanceOf(name : string): boolean {
  477. return ['java.lang.Cloneable', 'de.nrw.schule.svws.core.adt.tree.MinHeap', 'java.util.Collection', 'java.util.Queue', 'java.lang.Iterable'].includes(name);
  478. }
  479. public [Symbol.iterator](): Iterator<T> {
  480. let iter : JavaIterator<T> = this.iterator();
  481. const result : Iterator<T> = {
  482. next() : IteratorResult<T> {
  483. if (iter.hasNext())
  484. return { value : iter.next(), done : false };
  485. return { value : null, done : true };
  486. }
  487. };
  488. return result;
  489. }
  490. }
  491. export function cast_de_nrw_schule_svws_core_adt_tree_MinHeap<T>(obj : unknown) : MinHeap<T> {
  492. return obj as MinHeap<T>;
  493. }