diff --git a/src/app/pages/algorithms/sorting/sorting.component.scss b/src/app/pages/algorithms/sorting/sorting.component.scss
new file mode 100644
index 0000000..b911eac
--- /dev/null
+++ b/src/app/pages/algorithms/sorting/sorting.component.scss
@@ -0,0 +1,62 @@
+.sorting-container {
+ display: flex;
+ justify-content: center;
+ align-items: flex-start;
+ padding: 20px;
+ height: 100%;
+ box-sizing: border-box;
+
+ .sorting-card {
+ width: 100%;
+ max-width: 1200px;
+ padding: 20px;
+
+ .controls-panel {
+ display: flex;
+ gap: 10px;
+ margin-bottom: 20px;
+ align-items: center;
+ flex-wrap: wrap;
+
+ mat-form-field {
+ width: 200px;
+ }
+ }
+
+ .visualization-area {
+ display: flex;
+ align-items: flex-end;
+ height: 300px; /* Max height for bars */
+ border-bottom: 1px solid #ccc;
+ margin-bottom: 20px;
+ gap: 1px;
+ background-color: #f0f0f0;
+
+ .bar {
+ flex-grow: 1;
+ background-color: #424242; /* Default unsorted color */
+ transition: height 0.05s ease-in-out, background-color 0.05s ease-in-out;
+ width: 10px; /* Default width, flex-grow will adjust */
+ min-width: 1px; /* Ensure bars are always visible */
+
+ &.unsorted {
+ background-color: #424242;
+ }
+
+ &.comparing {
+ background-color: #ffeb3b; /* Yellow for comparing */
+ }
+
+ &.sorted {
+ background-color: #4caf50; /* Green for sorted */
+ }
+ }
+ }
+
+ .info-panel {
+ margin-top: 10px;
+ font-size: 0.9em;
+ color: #FFFFFF;
+ }
+ }
+}
diff --git a/src/app/pages/algorithms/sorting/sorting.component.ts b/src/app/pages/algorithms/sorting/sorting.component.ts
new file mode 100644
index 0000000..8cbca5d
--- /dev/null
+++ b/src/app/pages/algorithms/sorting/sorting.component.ts
@@ -0,0 +1,143 @@
+import {ChangeDetectorRef, Component, OnInit} from '@angular/core';
+import { CommonModule } from '@angular/common';
+import {MatCardModule} from "@angular/material/card";
+import {MatFormFieldModule} from "@angular/material/form-field";
+import {MatSelectModule} from "@angular/material/select";
+import {MatButtonModule} from "@angular/material/button";
+import {MatIconModule} from "@angular/material/icon";
+import {TranslateModule} from "@ngx-translate/core";
+import { SortingService } from './service/sorting.service';
+import {SortData, SortSnapshot} from './sorting.models';
+import { FormsModule } from '@angular/forms';
+import {MatInput} from '@angular/material/input';
+import {UrlConstants} from '../../../constants/UrlConstants';
+@Component({
+ selector: 'app-sorting',
+ standalone: true,
+ imports: [CommonModule, MatCardModule, MatFormFieldModule, MatSelectModule, MatButtonModule, MatIconModule, TranslateModule, FormsModule, MatInput],
+ templateUrl: './sorting.component.html',
+ styleUrls: ['./sorting.component.scss']
+})
+export class SortingComponent implements OnInit {
+
+ readonly MAX_ARRAY_SIZE: number = 200;
+ readonly MIN_ARRAY_SIZE: number = 20;
+
+ private timeoutIds: any[] = [];
+ sortArray: SortData[] = [];
+ unsortedArrayCopy: SortData[] = [];
+ arraySize: number = 100;
+ maxArrayValue: number = 100;
+ animationSpeed: number = 50; // Milliseconds per step
+
+ // Placeholder for available sorting algorithms
+ availableAlgorithms: { name: string; value: string }[] = [
+ { name: 'Bubble Sort', value: 'bubbleSort' },
+ { name: 'Quick Sort', value: 'quickSort' },
+ { name: 'Heap Sort', value: 'heapSort' },
+ ];
+ selectedAlgorithm: string = this.availableAlgorithms[0].value;
+ executionTime: number = 0;
+
+ constructor(private readonly sortingService: SortingService, private readonly cdr: ChangeDetectorRef) { }
+
+ ngOnInit(): void {
+ this.generateNewArray();
+ }
+
+ newArraySizeSet()
+ {
+ if (this.arraySize == this.sortArray.length)
+ {
+ return;
+ }
+ this.generateNewArray();
+ }
+
+ generateNewArray(): void {
+ this.resetSorting();
+ this.executionTime = 0;
+ this.unsortedArrayCopy = [];
+ this.sortArray = [];
+
+ for (let i = 0; i < this.arraySize; i++) {
+ const randomValue = Math.floor(Math.random() * this.maxArrayValue) + 1;
+ this.sortArray.push({
+ value: randomValue,
+ state: 'unsorted'
+ });
+
+ this.unsortedArrayCopy.push({
+ value: randomValue,
+ state: 'unsorted'
+ });
+ }
+ }
+
+ private resetSortState() {
+ for (let i = 0; i < this.sortArray.length; i++) {
+ let element = this.sortArray[i];
+ let unsortedElement = this.unsortedArrayCopy[i];
+ element.value = unsortedElement.value;
+ element.state = 'unsorted';
+ }
+ }
+
+ async startSorting(): Promise {
+ this.resetSorting();
+ const startTime = performance.now();
+ let snapshots: SortSnapshot[] = [];
+
+ switch (this.selectedAlgorithm) {
+ case 'bubbleSort':
+ snapshots = this.sortingService.bubbleSort(this.sortArray);
+ break;
+ case 'quickSort':
+ snapshots = this.sortingService.quickSort(this.sortArray);
+ break;
+ case 'heapSort':
+ snapshots = this.sortingService.heapSort(this.sortArray);
+ break;
+ }
+
+ const endTime = performance.now();
+ this.executionTime = parseFloat((endTime - startTime).toFixed(4));
+
+ console.log(snapshots.length);
+ this.animateSorting(snapshots);
+ }
+
+ private animateSorting(snapshots: SortSnapshot[]): void {
+ snapshots.forEach((snapshot, index) => {
+ const id = setTimeout(() => {
+ for (let i = 0; i < this.sortArray.length; i++) {
+ if (snapshot.array[i]) {
+ this.sortArray[i].value = snapshot.array[i].value;
+ this.sortArray[i].state = snapshot.array[i].state;
+ }
+ }
+
+ this.cdr.detectChanges();
+
+ if (index === snapshots.length - 1) {
+ this.sortArray.forEach(item => item.state = 'sorted');
+ this.cdr.detectChanges();
+ }
+ }, index * this.animationSpeed);
+
+ this.timeoutIds.push(id);
+ });
+ }
+
+ private stopAnimations(): void {
+ this.timeoutIds.forEach(id => clearTimeout(id));
+ this.timeoutIds = [];
+ }
+
+ resetSorting(): void {
+ this.stopAnimations();
+ this.resetSortState();
+ }
+
+ protected readonly UrlConstants = UrlConstants;
+}
diff --git a/src/app/pages/algorithms/sorting/sorting.models.ts b/src/app/pages/algorithms/sorting/sorting.models.ts
new file mode 100644
index 0000000..e4d8bce
--- /dev/null
+++ b/src/app/pages/algorithms/sorting/sorting.models.ts
@@ -0,0 +1,8 @@
+export interface SortData {
+ value: number;
+ state: 'sorted' | 'comparing' | 'unsorted';
+}
+
+export interface SortSnapshot {
+ array: SortData[];
+}
diff --git a/src/assets/i18n/de.json b/src/assets/i18n/de.json
index d30988a..a50598d 100644
--- a/src/assets/i18n/de.json
+++ b/src/assets/i18n/de.json
@@ -317,15 +317,41 @@
},
"ALERT": {
"START_END_NODES": "Bitte wählen Sie einen Start- und Endknoten aus, bevor Sie den Algorithmus starten."
+ },
+ "GRID_HEIGHT": "Höhe",
+ "GRID_WIDTH": "Beite"
+ },
+ "SORTING": {
+ "TITLE": "Sortieralgorithmen",
+ "ALGORITHM": "Algorithmen",
+ "START": "Sortierung starten",
+ "RESET": "Zurücksetzen",
+ "GENERATE_NEW_ARRAY": "Neues Array generieren",
+ "EXECUTION_TIME": "Ausführungszeit",
+ "ARRAY_SIZE": "Anzahl der Balken",
+ "EXPLANATION": {
+ "TITLE": "Algorithmen",
+ "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.",
+ "NOTE": "HINWEIS",
+ "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).",
+ "DISCLAIMER_2": "Average Case: Der statistische Normalfall.",
+ "DISCLAIMER_3": "Worst Case: Die Daten sind maximal ungünstig angeordnet (hier bricht Quick Sort ohne Optimierung ein, während Heap Sort stabil bleibt).",
+ "DISCLAIMER_4": "Zusätzlich gibt es fast immer einen Time-Space Trade-off (Zeit-Speicher-Kompromiss): Algorithmen, die extrem schnell sind (wie Merge Sort), benötigen oft viel zusätzlichen Arbeitsspeicher. Algorithmen, die direkt im vorhandenen Speicher arbeiten (wie Heap Sort), sparen Platz, sind aber manchmal komplexer oder minimal langsamer. Es gibt also keine \"One-Size-Fits-All\"-Lösung."
}
},
"ALGORITHM": {
"TITLE": "Algorithmen",
"PATHFINDING": {
"TITLE": "Wegfindung",
- "DESCRIPTION": "Vergleich von Dijkstra vs. A*.",
- "GRID_HEIGHT": "Höhe",
- "GRID_WIDTH": "Beite"
+ "DESCRIPTION": "Vergleich von Dijkstra vs. A*."
+ },
+ "SORTING": {
+ "TITLE": "Sortierung",
+ "DESCRIPTION": "Visualisierung verschiedener Sortieralgorithmen."
+
}
}
}
diff --git a/src/assets/i18n/en.json b/src/assets/i18n/en.json
index 71e8757..7e754c2 100644
--- a/src/assets/i18n/en.json
+++ b/src/assets/i18n/en.json
@@ -317,15 +317,40 @@
},
"ALERT": {
"START_END_NODES": "Please select a start and end node before running the algorithm."
+ },
+ "GRID_HEIGHT": "Height",
+ "GRID_WIDTH": "Width"
+ },
+ "SORTING": {
+ "TITLE": "Sorting Algorithms",
+ "ALGORITHM": "Algorithm",
+ "START": "Start Sorting",
+ "RESET": "Reset",
+ "GENERATE_NEW_ARRAY": "Generate New Array",
+ "EXECUTION_TIME": "Execution Time",
+ "ARRAY_SIZE": "Number of Bars",
+ "EXPLANATION": {
+ "TITLE": "Algorithms",
+ "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.",
+ "NOTE": "NOTE",
+ "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.",
+ "DISCLAIMER_3": "Worst Case: The data is arranged in the most unfavorable way possible (Quick Sort performs poorly here without optimization, while Heap Sort remains stable).",
+ "DISCLAIMER_4": "Additionally, there is almost always a Time-Space Trade-off: Algorithms that are extremely fast (like Merge Sort) often require a lot of additional working memory. Algorithms that work directly in existing memory (like Heap Sort) save space but are sometimes more complex or slightly slower. Thus, there is no \"one-size-fits-all\" solution."
}
},
"ALGORITHM": {
"TITLE": "Algorithms",
"PATHFINDING": {
"TITLE": "Pathfinding",
- "DESCRIPTION": "Comparing of Dijkstra vs. A*.",
- "GRID_HEIGHT": "Height",
- "GRID_WIDTH": "Width"
+ "DESCRIPTION": "Comparing of Dijkstra vs. A*."
+ },
+ "SORTING": {
+ "TITLE": "Sorting",
+ "DESCRIPTION": "Visualizing various sorting algorithms."
}
}
}
diff --git a/src/styles.scss b/src/styles.scss
index dc63ed5..3a12a96 100644
--- a/src/styles.scss
+++ b/src/styles.scss
@@ -211,3 +211,23 @@ a {
height: 18px;
width: 18px;
}
+
+// algos
+.algo-info {
+ margin: 0 0 1rem 0;
+ padding: 0.75rem 1rem;
+ border: 1px solid #ddd;
+ border-radius: 8px;
+
+ h3 {
+ margin: 0 0 0.5rem 0;
+ }
+
+ p {
+ margin: 0.5rem 0;
+ }
+
+ a {
+ margin-left: 0.25rem;
+ }
+}