import { IllegalStateException, cast_java_lang_IllegalStateException } from '../../../java/lang/IllegalStateException'; import { MinHeapIterator, cast_de_nrw_schule_svws_core_adt_tree_MinHeapIterator } from '../../../core/adt/tree/MinHeapIterator'; import { StringBuilder, cast_java_lang_StringBuilder } from '../../../java/lang/StringBuilder'; import { JavaString, cast_java_lang_String } from '../../../java/lang/JavaString'; import { System, cast_java_lang_System } from '../../../java/lang/System'; import { Comparator, cast_java_util_Comparator } from '../../../java/util/Comparator'; import { JavaInteger, cast_java_lang_Integer } from '../../../java/lang/JavaInteger'; import { NullPointerException, cast_java_lang_NullPointerException } from '../../../java/lang/NullPointerException'; import { JavaIterator, cast_java_util_Iterator } from '../../../java/util/JavaIterator'; import { Collection, cast_java_util_Collection } from '../../../java/util/Collection'; import { Cloneable, cast_java_lang_Cloneable } from '../../../java/lang/Cloneable'; import { JavaObject, cast_java_lang_Object } from '../../../java/lang/JavaObject'; import { Arrays, cast_java_util_Arrays } from '../../../java/util/Arrays'; import { Queue, cast_java_util_Queue } from '../../../java/util/Queue'; import { IllegalArgumentException, cast_java_lang_IllegalArgumentException } from '../../../java/lang/IllegalArgumentException'; import { NoSuchElementException, cast_java_util_NoSuchElementException } from '../../../java/util/NoSuchElementException'; import { CloneNotSupportedException, cast_java_lang_CloneNotSupportedException } from '../../../java/lang/CloneNotSupportedException'; export class MinHeap extends JavaObject implements Queue, Cloneable { private _size : number = 0; private _nodes : Array = Array(0).fill(null); private readonly _comparator : Comparator; private readonly _initialCapacity : number; protected _modCount : number = 0; /** * Erzeugt einen neuen Minimum-Heap mit dem übergebenen {@link Comparator} und * der übergebenen initialen Kapazität. * * @param comparator das Objekt zum Vergleich von zwei Objekten des Typ T * @param initialCapacity die initiale Kapazität des Baums */ public constructor(comparator : Comparator, initialCapacity : number); /** * Erzeugt einen neuen Minimum-Heap mit dem übergebenen {@link Comparator} und * einer initialen Kapazität von 63. * * @param comparator das Objekt zum Vergleich von zwei Objekten des Typ T */ public constructor(comparator : Comparator); /** * Erstellt eine Kopie des als Parameter übergebenen Heaps. * * @param original Das zu kopierende Original */ public constructor(original : MinHeap); /** * Implementation for method overloads of 'constructor' */ public constructor(__param0 : Comparator | MinHeap, __param1? : number) { super(); 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")) { let comparator : Comparator = cast_java_util_Comparator(__param0); let initialCapacity : number = __param1 as number; if (initialCapacity <= 0) throw new IllegalArgumentException("Die initiale Kapazität muss größer als 0 sein.") this._comparator = comparator; this._initialCapacity = initialCapacity; this._modCount = 0; } 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")) { let comparator : Comparator = cast_java_util_Comparator(__param0); this._comparator = comparator; this._initialCapacity = 63; this._modCount = 0; } else if (((typeof __param0 !== "undefined") && ((__param0 instanceof JavaObject) && (__param0.isTranspiledInstanceOf('de.nrw.schule.svws.core.adt.tree.MinHeap'))) || (__param0 === null)) && (typeof __param1 === "undefined")) { let original : MinHeap = cast_de_nrw_schule_svws_core_adt_tree_MinHeap(__param0); this._comparator = original._comparator; this._initialCapacity = original._initialCapacity; this._nodes = Arrays.copyOf(original._nodes, original._nodes.length); this._size = original._size; this._modCount = original._modCount; } else throw new Error('invalid method overload'); } public add(e : T) : boolean { if (e === null) return false; if (this._nodes.length === 0) this._nodes = this.newArray(e, this._initialCapacity); if (this._size === this._nodes.length) this.grow(); this._nodes[this._size] = e; this.heapifyUp(this._size++); this._modCount++; return true; } public element() : T { if ((this._size === 0) || (this._nodes[0] === null)) throw new NoSuchElementException() return this._nodes[0]; } public offer(e : T) : boolean { return this.add(e); } public peek() : T | null { return this._nodes.length === 0 ? null : this._nodes[0]; } public poll() : T | null { if (this._size === 0) return null; let elem : T | null = this._nodes[0]; this._nodes[0] = this._nodes[--this._size]; this._nodes[this._size] = null; this.heapifyDown(0); this._modCount++; return elem; } public remove() : T; public remove(o : unknown | null) : boolean; /** * Implementation for method overloads of 'remove' */ public remove(__param0? : null | unknown) : T | boolean { if ((typeof __param0 === "undefined")) { let result : T | null = this.poll(); if (result === null) throw new NoSuchElementException() return result; } else if (((typeof __param0 !== "undefined") && ((__param0 instanceof Object) || ((__param0 instanceof JavaObject) && (__param0.isTranspiledInstanceOf('java.lang.Object')))) || (__param0 === null))) { let o : unknown | null = (__param0 instanceof JavaObject) ? cast_java_lang_Object(__param0) : __param0; if (o === null) return false; let index : number = this.findIndex(o); if (index === -1) return false; this._size--; this._modCount++; if (index === this._size) return true; this._nodes[index] = this._nodes[this._size]; this._nodes[this._size] = null; this.heapifyUp(index); this.heapifyDown(index); return true; } else throw new Error('invalid method overload'); } public size() : number { return this._size; } public isEmpty() : boolean { return this._size === 0; } public contains(o : unknown | null) : boolean { if (o === null) return false; for (let i : number = 0; i < this._size; i++){ if (JavaObject.equalsTranspiler(this._nodes[i], (o))) return true; } return false; } public containsAll(c : Collection | null) : boolean { if (c === null) return true; if (this as unknown === c as unknown) return true; for (let o of c) if (!this.contains(o)) return false; return true; } public addAll(c : Collection | null) : boolean { if (c === null) return false; if (this as unknown === c as unknown) { if (this._size === 0) return false; let tmp : Array = Arrays.copyOf(this._nodes, this._size); for (let t of tmp) if (t !== null) this.add(t); return true; } let result : boolean = false; for (let t of c) { if (this.add(t)) result = true; } return result; } public removeAll(c : Collection | null) : boolean { if (c === null) return false; if (this as unknown === c as unknown) { if (this.size() === 0) return false; this.clear(); return true; } let result : boolean = false; for (let o of c) { if (this.remove(o)) { result = true; while (this.remove(o)) ; } } return result; } public retainAll(c : Collection | null) : boolean { if (this._size === 0) return false; if (c === null) { this.clear(); return true; } if (this as unknown === c as unknown) return false; let tmp : Array = this.newArray(this._nodes[0], this._nodes.length); if (tmp === null) return false; let i : number = 0; let elem : T | null; let changed : boolean = false; while ((elem = this.poll()) !== null) { if (c.contains(elem)) tmp[i++] = elem; else changed = true; } this._nodes = tmp; this._size = i; this._modCount++; return changed; } public clear() : void { this._nodes = Array(0).fill(null); this._size = 0; this._modCount++; } public toArray() : Array; public toArray(a : Array) : Array; /** * Implementation for method overloads of 'toArray' */ public toArray(__param0? : Array) : Array | Array { if ((typeof __param0 === "undefined")) { return this.copyNodes(); } else if (((typeof __param0 !== "undefined") && Array.isArray(__param0))) { let a : Array = __param0; if (a.length < this._size) return this.copyNodes(); System.arraycopy(this._nodes, 0, a, 0, this._size); Arrays.fill(a, this._size, a.length, null); return a; } else throw new Error('invalid method overload'); } public iterator() : JavaIterator { return new MinHeapIterator(this._nodes, this); } public clone() : unknown { return new MinHeap(this); } /** * Gibt den {@link Comparator} des Minimum Heaps zurück. * * @return der Comparator */ public comparator() : Comparator { return this._comparator; } /** * Gibt die aktuelle Kapazität des Arrays zurück. * * @return die aktuelle Kapazität des Arrays zurück */ public capacity() : number { return (this._nodes.length === 0) ? this._initialCapacity : this._nodes.length; } /** * Gibt den Inhalt des Minimum Heaps in einem sortierten Array zurück. * * @return ein sortiertes Array mit den Elementen des Minimum Heaps. */ public toSortedArray() : Array { if (this._size === 0) return Array(0).fill(null); let copy : MinHeap = new MinHeap(this); let tmp : Array = this.newArray(this._nodes[0], this._size); let current : T | null; let i : number = 0; while ((current = copy.poll()) !== null) tmp[i++] = current; return tmp; } /** * Gibt den Inhalt des Heaps als Array-Repräsentation aus. * * @return der Inhalt des Heaps */ public toString() : String { let sb : StringBuilder = new StringBuilder(); for (let i : number = 0; i < this._size; i++){ sb.append(this._nodes[i]); if (i !== this._size - 1) sb.append(", "); } return sb.toString(); } /** * Ermittelt eine Hash-Code für dieses Objekt basierend auf den gespeicherten * Daten im Heap (die konkrete Ordnung des Baumes wird nicht unterschieden). * * @return der Hashcode des Minimum Heaps */ public hashCode() : number { return Arrays.deepHashCode(this.toSortedArray()); } /** * Prüft, ob das übergebene Objekt ein Minimum-Heap ist, der * die gleichen Elemente mit der gleichen Ordnung beinhaltet. * * @param obj das zu vergleichende Objekt */ public equals(obj : unknown | null) : boolean { if (this as unknown === obj as unknown) return true; if (obj === null) return false; if (((obj instanceof JavaObject) && (obj.isTranspiledInstanceOf('de.nrw.schule.svws.core.adt.tree.MinHeap')))) { let other : MinHeap | null = cast_de_nrw_schule_svws_core_adt_tree_MinHeap(obj); return Arrays.deepEquals(this.toSortedArray(), other.toSortedArray()); } return false; } /** * Liefert zum Index i den Index des Elter zurück. * * @param i * * @return den Index des Elter */ private static getParentIndex(i : number) : number { return (i <= 0) ? -1 : Math.trunc((i - 1) / 2); } /** * Liefert zum Index i den Index des linken Kindes zurück. * * @param i * * @return den Index des linken Kindes */ private static getLeftChildIndex(i : number) : number { return 2 * i + 1; } /** * Liefert zum Index i den Index des rechten Kindes zurück. * * @param i * * @return den Index des rechten Kindes */ private static getRightChildIndex(i : number) : number { return 2 * i + 2; } /** * Tauscht die Elemente an den Stellen i und j im Array * * @param i * @param j */ private swap(i : number, j : number) : void { let elem : T | null = this._nodes[i]; this._nodes[i] = this._nodes[j]; this._nodes[j] = elem; } /** * Stellt die Minimum Heap Eigenschaft vom Index i aus im Baum abwärts her. * * @param i ab diesem Index wird im Baum abwärts geprüft. */ private heapifyDown(i : number) : void { let left : number = MinHeap.getLeftChildIndex(i); let right : number = MinHeap.getRightChildIndex(i); if (left >= this._size) return; let child : number = right; if (right === this._size) { child = left; } else { let nodeLeft : T | null = this._nodes[left]; let nodeRight : T | null = this._nodes[right]; if ((nodeLeft === null) || (nodeRight === null)) return; if (this._comparator.compare(nodeLeft, nodeRight) < 0) child = left; } let nodeCurrent : T | null = this._nodes[i]; let nodeChild : T | null = this._nodes[child]; if ((nodeCurrent === null) || (nodeChild === null)) throw new NullPointerException() if (this._comparator.compare(nodeCurrent, nodeChild) <= 0) return; this.swap(i, child); this.heapifyDown(child); } /** * Stellt die Minimum-Heap-Eigenschaft des Arrays ab Position i aufwärts wieder her. * * @param i ab diesem Index wird überprüft */ private heapifyUp(i : number) : void { let parentIndex : number = MinHeap.getParentIndex(i); if (parentIndex < 0) return; let nodeCurrent : T | null = this._nodes[i]; let nodeParent : T | null = this._nodes[parentIndex]; if ((nodeCurrent === null) || (nodeParent === null) || (this._comparator.compare(nodeCurrent, nodeParent) >= 0)) return; this.swap(i, parentIndex); this.heapifyUp(parentIndex); } /** * Erstellt ein neues Array vom Typ T mit der angegebenen Länge. * * @param elem Ein Element vom Typ T, welches als Vorlage für die Elemente des Arrays dient * @param length die Länge des neuen Arrays * * @return das neue Array */ private newArray(elem : T | null, length : number) : Array { if (elem === null) return Array(length).fill(null); return Array(length).fill(null); } /** * Erzeugt eine Kopie des internen Arrays _nodes. * * @return die Kopie des _nodes-Array. */ private copyNodes() : Array { let result : Array = this.newArray(this._size <= 0 ? null : this._nodes[0], this._size); System.arraycopy(this._nodes, 0, result, 0, this._size); return result; } /** * Lässt den dem Baum zu Grunde liegenden Baum wachsen. Verdoppelt die Menge der Elemente, die im Heap * gespeichert werden können. * * Falls der Heap durch das Wachsen auf mehr als {@link Integer.MAX_VALUE} Elemente ansteigen würde, * wird eine IllegalStateException geworfen. * * @throws IllegalStateException */ private grow() : void { if (this._nodes.length === Number.MAX_VALUE) throw new IllegalStateException("Der Minimum-Heap kann nicht mehr als " + Number.MAX_VALUE + " Elemente beinhalten.") let newLength : number = this._nodes.length * 2 + 1; if (newLength < 0) newLength = Number.MAX_VALUE; let tmp : Array = this.newArray(this._nodes[0], newLength); System.arraycopy(this._nodes, 0, tmp, 0, this._size); this._nodes = tmp; } /** * Findet den Index an dem das Element t im dem dem Heap zu Grunde liegendem Array gespeichert ist. * Gibt -1 zurück, falls das Element nicht vorhanden ist. * * @param t zu diesem Element soll der Index gefunden werden * * @return der Index, falls das Element enthalten ist, ansonsten -1 */ private findIndex(obj : unknown | null) : number { if (obj === null) return -1; for (let i : number = 0; i < this._size; i++){ if (JavaObject.equalsTranspiler(this._nodes[i], (obj))) return i; } return -1; } /** * Gibt die Anzahl der Operationen zurück, die diese Datenstruktur * verändert haben. * * @return die Anzahl der Operationen */ getModCount() : number { return this._modCount; } isTranspiledInstanceOf(name : string): boolean { return ['java.lang.Cloneable', 'de.nrw.schule.svws.core.adt.tree.MinHeap', 'java.util.Collection', 'java.util.Queue', 'java.lang.Iterable'].includes(name); } public [Symbol.iterator](): Iterator { let iter : JavaIterator = this.iterator(); const result : Iterator = { next() : IteratorResult { if (iter.hasNext()) return { value : iter.next(), done : false }; return { value : null, done : true }; } }; return result; } } export function cast_de_nrw_schule_svws_core_adt_tree_MinHeap(obj : unknown) : MinHeap { return obj as MinHeap; }