bugfix/someImporvements #31

Merged
lobo merged 8 commits from bugfix/someImporvements into main 2026-03-07 17:20:38 +01:00
5 changed files with 114 additions and 0 deletions
Showing only changes of commit 7ff59bf734 - Show all commits

View File

@@ -7,6 +7,7 @@
static readonly QUICK_SORT_WIKI = 'https://de.wikipedia.org/wiki/Quicksort'
static readonly HEAP_SORT_WIKI = 'https://de.wikipedia.org/wiki/Heapsort'
static readonly SHAKE_SORT_WIKI = 'https://de.wikipedia.org/wiki/Shakersort'
static readonly TIM_SORT_WIKI = 'https://de.wikipedia.org/wiki/Timsort'
static readonly CONWAYS_WIKI = 'https://de.wikipedia.org/wiki/Conways_Spiel_des_Lebens'
static readonly PRIMS_WIKI = 'https://de.wikipedia.org/wiki/Algorithmus_von_Prim'
static readonly KRUSKAL_WIKI = 'https://de.wikipedia.org/wiki/Algorithmus_von_Kruskal'

View File

@@ -224,6 +224,103 @@ export class SortingService {
}
}
// --- TIM SORT ---
timSort(array: SortData[]): SortSnapshot[] {
const snapshots: SortSnapshot[] = [];
const arr = array.map(item => ({ ...item }));
const n = arr.length;
const RUN = 32;
snapshots.push(this.createSnapshot(arr));
// Step 1: Sort small runs with insertion sort
for (let i = 0; i < n; i += RUN) {
const end = Math.min(i + RUN - 1, n - 1);
this.insertionSortRange(arr, i, end, snapshots);
}
// Step 2: Merge the sorted runs
for (let size = RUN; size < n; size *= 2) {
for (let left = 0; left < n; left += 2 * size) {
const mid = Math.min(left + size - 1, n - 1);
const right = Math.min(left + 2 * size - 1, n - 1);
if (mid < right) {
this.mergeRanges(arr, left, mid, right, snapshots);
}
}
}
arr.forEach(item => item.state = 'sorted');
snapshots.push(this.createSnapshot(arr));
return snapshots;
}
private insertionSortRange(arr: SortData[], left: number, right: number, snapshots: SortSnapshot[]): void {
for (let i = left + 1; i <= right; i++) {
const tempValue = arr[i].value;
arr[i].state = 'comparing';
snapshots.push(this.createSnapshot(arr));
let j = i - 1;
while (j >= left && arr[j].value > tempValue) {
arr[j].state = 'comparing';
arr[j + 1].value = arr[j].value;
arr[j].state = 'unsorted';
snapshots.push(this.createSnapshot(arr));
j--;
}
arr[j + 1].value = tempValue;
arr[i].state = 'unsorted';
snapshots.push(this.createSnapshot(arr));
}
}
private mergeRanges(arr: SortData[], left: number, mid: number, right: number, snapshots: SortSnapshot[]): void {
const leftPart = arr.slice(left, mid + 1).map(item => ({ ...item }));
const rightPart = arr.slice(mid + 1, right + 1).map(item => ({ ...item }));
let i = 0;
let j = 0;
let k = left;
while (i < leftPart.length && j < rightPart.length) {
// Highlight the write target and the right-side source (arr[mid+1+j] is still
// untouched in the array since k never overtakes it during a merge)
const rightSourceIdx = mid + 1 + j;
arr[k].state = 'comparing';
arr[rightSourceIdx].state = 'comparing';
snapshots.push(this.createSnapshot(arr));
arr[rightSourceIdx].state = 'unsorted';
if (leftPart[i].value <= rightPart[j].value) {
arr[k].value = leftPart[i].value;
i++;
} else {
arr[k].value = rightPart[j].value;
j++;
}
arr[k].state = 'unsorted';
k++;
snapshots.push(this.createSnapshot(arr));
}
while (i < leftPart.length) {
arr[k].value = leftPart[i].value;
i++;
k++;
}
while (j < rightPart.length) {
arr[k].value = rightPart[j].value;
j++;
k++;
}
}
private swap(arr: SortData[], i: number, j: number) {
const temp = arr[i].value;
arr[i].value = arr[j].value;

View File

@@ -49,6 +49,11 @@ export class SortingComponent implements OnInit {
name: 'Heap Sort',
description: 'SORTING.EXPLANATION.HEAP_SORT_EXPLANATION',
link: UrlConstants.HEAP_SORT_WIKI
},
{
name: 'Tim Sort',
description: 'SORTING.EXPLANATION.TIMSORT_EXPLANATION',
link: UrlConstants.TIM_SORT_WIKI
}
],
disclaimer: 'SORTING.EXPLANATION.DISCLAIMER',
@@ -130,6 +135,9 @@ export class SortingComponent implements OnInit {
case 'Cocktail Sort':
snapshots = this.sortingService.cocktailSort(this.sortArray);
break;
case 'Tim Sort':
snapshots = this.sortingService.timSort(this.sortArray);
break;
}
const endTime = performance.now();

View File

@@ -371,6 +371,7 @@
"BUBBLE_SORT_EXPLANATION":"vergleicht wiederholt benachbarte Elemente und tauscht sie, wenn sie in der falschen Reihenfolge stehen. Das größte Element \"blubbert\" dabei wie eine Luftblase ans Ende der Liste. Vorteil: Extrem einfach zu verstehen und zu implementieren; erkennt bereits sortierte Listen sehr schnell. Nachteil: Sehr ineffizient bei großen Listen (Laufzeit O(n²)). In der Praxis kaum genutzt.",
"QUICK_SORT_EXPLANATION": "folgt dem \"Teile und Herrsche\"-Prinzip. Ein \"Pivot\"-Element wird gewählt, und das Array wird in zwei Hälften geteilt: Elemente kleiner als das Pivot und Elemente größer als das Pivot. Vorteil: Im Durchschnitt einer der schnellsten Sortieralgorithmen (O(n log n)); benötigt keinen zusätzlichen Speicher (In-Place). Nachteil: Im schlechtesten Fall (Worst Case) langsam (O(n²)), wenn das Pivot ungünstig gewählt wird. Ist nicht stabil (ändert Reihenfolge gleicher Elemente).",
"HEAP_SORT_EXPLANATION": "organisiert die Daten zunächst in einer speziellen Baumstruktur (Binary Heap). Das größte Element (die Wurzel) wird entnommen und ans Ende sortiert, dann wird der Baum repariert. Vorteil: Garantiert eine schnelle Laufzeit von O(n log n), selbst im schlechtesten Fall. Benötigt fast keinen zusätzlichen Speicher. Nachteil: In der Praxis oft etwas langsamer als Quick Sort, da die Sprünge im Speicher (Heap-Struktur) den CPU-Cache schlechter nutzen.",
"TIMSORT_EXPLANATION": "ist ein hybrider Sortieralgorithmus, der aus Merge Sort und Insertion Sort kombiniert ist. Er unterteilt das Array in kleine 'Runs' und sortiert jeden davon mit Insertion Sort, um sie anschließend schrittweise mit Merge Sort zusammenzuführen. Vorteil: Extrem effizient bei realen Daten, die oft teilweise sortiert sind O(n log n) im schlechtesten und O(n) im besten Fall. Er ist der Standardalgorithmus in Python und Java. Nachteil: Komplexer zu implementieren als ein reiner Algorithmus und benötigt zusätzlichen Speicher für den Merge-Schritt.",
"COCKTAIL_SORT_EXPLANATION" : "(auch Shaker Sort) ist eine Erweiterung des Bubble Sort. Statt nur von links nach rechts zu gehen, wechselt er bei jedem Durchlauf die Richtung und schiebt abwechselnd das größte Element nach rechts und das kleinste nach links. Vorteil: Schneller als Bubble Sort, da kleine Elemente am Ende schneller nach vorne wandern (\"Schildkröten-Problem\" gelöst). Nachteil: Bleibt in der Laufzeitklasse O(n²), also für große Datenmengen ineffizient.",
"DISCLAIMER": "Die Wahl des \"besten\" Sortieralgorithmus hängt stark von den Daten und den Rahmenbedingungen ab. In der Informatik betrachtet man oft drei Szenarien:",
"DISCLAIMER_1": "Best Case: Die Daten sind schon fast sortiert (hier glänzt z.B. Bubble Sort).",
@@ -483,6 +484,9 @@
"WIND_OFF": "Wind Ausschalten",
"OUTLINE_ON": "Mesh anzeigen",
"OUTLINE_OFF": "Mesh ausschalten",
"STIFFNESS": "Steifigkeit",
"ELONGATION": "Dehnung",
"RESTART_SIMULATION": "Simulation neu starten",
"EXPLANATION": {
"TITLE": "Echtzeit-Stoffsimulation auf der GPU",
"CLOTH_SIMULATION_EXPLANATION_TITLE": "Stoffsimulation",

View File

@@ -371,6 +371,7 @@
"BUBBLE_SORT_EXPLANATION": "repeatedly compares adjacent elements and swaps them if they are in the wrong order. The largest element \"bubbles\" to the end of the list like an air bubble. Advantage: Extremely simple to understand and implement; detects already sorted lists very quickly. Disadvantage: Very inefficient for large lists (runtime O(n²)). Rarely used in practice.",
"QUICK_SORT_EXPLANATION": "follows the \"divide and conquer\" principle. A \"pivot\" element is selected, and the array is divided into two halves: elements smaller than the pivot and elements larger than the pivot. Advantage: On average one of the fastest sorting algorithms (O(n log n)); requires no additional memory (in-place). Disadvantage: Slow in the worst case (O(n²)) if the pivot is chosen poorly. Is not stable (changes order of equal elements).",
"HEAP_SORT_EXPLANATION": "organizes the data initially into a special tree structure (Binary Heap). The largest element (the root) is extracted and sorted to the end, then the tree is repaired. Advantage: Guarantees a fast runtime of O(n log n), even in the worst case. Requires almost no additional memory. Disadvantage: Often slightly slower than Quick Sort in practice because the jumps in memory (heap structure) utilize the CPU cache less effectively.",
"TIMSORT_EXPLANATION": "is a hybrid sorting algorithm derived from Merge Sort and Insertion Sort. It divides the array into small 'runs' and sorts each using Insertion Sort, then merges them step by step using Merge Sort. Advantage: Extremely efficient on real-world data that is often partially sorted — O(n log n) in the worst case and O(n) in the best case. It is the standard sorting algorithm in Python and Java. Disadvantage: More complex to implement than a pure algorithm and requires additional memory for the merge step.",
"DISCLAIMER": "The choice of the \"best\" sorting algorithm depends heavily on the data and the constraints. In computer science, three scenarios are often considered:",
"DISCLAIMER_1": "Best Case: The data is already nearly sorted (Bubble Sort shines here, for example).",
"DISCLAIMER_2": "Average Case: The statistical norm.",
@@ -482,6 +483,9 @@
"WIND_OFF": "Wind Off",
"OUTLINE_ON": "Show Mesh",
"OUTLINE_OFF": "Hide Mesh",
"STIFFNESS": "Stiffness",
"ELONGATION": "Elongation",
"RESTART_SIMULATION": "Restart Simulation",
"EXPLANATION": {
"TITLE": "Real-time Cloth Simulation on the GPU",
"CLOTH_SIMULATION_EXPLANATION_TITLE": "Cloth Simulation",