Add Cocktail Sort algorithm and UI
Introduce Cocktail (Shaker) Sort to the sorting visualizer: implement cocktailSort and a helper switchValuesIfCorrect in the SortingService to generate snapshots for the animation. Add SHAKE_SORT_WIKI URL constant and a UI paragraph (with a link) plus German translation text for the algorithm explanation. Expose the new algorithm in the component (availableAlgorithms and switch handling). Also refactor the component to use Angular's inject() for SortingService and ChangeDetectorRef, tighten some typings (timeoutIds -> number[]), adjust default arraySize, and use const where appropriate.
This commit is contained in:
@@ -12,6 +12,7 @@ export class SortingService {
|
||||
};
|
||||
}
|
||||
|
||||
// --- BUBBLE SORT ---
|
||||
bubbleSort(array: SortData[]): SortSnapshot[] {
|
||||
const snapshots: SortSnapshot[] = [];
|
||||
const arr = array.map(item => ({ ...item }));
|
||||
@@ -46,7 +47,60 @@ export class SortingService {
|
||||
return snapshots;
|
||||
}
|
||||
|
||||
// --- QUICK SORT ---
|
||||
// --- COCKTAIL SORT ---
|
||||
|
||||
cocktailSort(array: SortData[]): SortSnapshot[] {
|
||||
const snapshots: SortSnapshot[] = [];
|
||||
const arr = array.map(item => ({ ...item }));
|
||||
snapshots.push(this.createSnapshot(arr));
|
||||
|
||||
let start = -1;
|
||||
let end = array.length-1;
|
||||
let changed = false;
|
||||
do {
|
||||
changed = false;
|
||||
start += 1;
|
||||
for (let i = start; i < end; i++) {
|
||||
changed = this.switchValuesIfCorrect(arr, i, snapshots, changed);
|
||||
}
|
||||
|
||||
//DONE
|
||||
if (!changed) {
|
||||
break;
|
||||
}
|
||||
|
||||
changed = false;
|
||||
end -= 1;
|
||||
for (let i = end; i >= start; i--) {
|
||||
changed = this.switchValuesIfCorrect(arr, i, snapshots, changed);
|
||||
}
|
||||
} while (changed);
|
||||
|
||||
|
||||
return snapshots;
|
||||
}
|
||||
|
||||
private switchValuesIfCorrect(arr: { value: number; state: "sorted" | "comparing" | "unsorted" }[], i: number, snapshots: SortSnapshot[], changed: boolean) {
|
||||
const firstValue = arr[i];
|
||||
const secondValue = arr[i + 1];
|
||||
|
||||
firstValue.state = 'comparing';
|
||||
secondValue.state = 'comparing';
|
||||
snapshots.push(this.createSnapshot(arr));
|
||||
|
||||
if (firstValue.value > secondValue.value) {
|
||||
const temp = firstValue.value;
|
||||
firstValue.value = secondValue.value;
|
||||
secondValue.value = temp;
|
||||
changed = true;
|
||||
}
|
||||
firstValue.state = 'unsorted';
|
||||
secondValue.state = 'unsorted';
|
||||
snapshots.push(this.createSnapshot(arr));
|
||||
return changed;
|
||||
}
|
||||
|
||||
// --- QUICK SORT ---
|
||||
quickSort(array: SortData[]): SortSnapshot[] {
|
||||
const snapshots: SortSnapshot[] = [];
|
||||
const arr = array.map(item => ({ ...item }));
|
||||
|
||||
@@ -12,6 +12,11 @@
|
||||
<a href="{{UrlConstants.BUBBLE_SORT_WIKI}}" target="_blank" rel="noopener noreferrer">Wikipedia</a>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<strong>Cocktail Sort</strong> {{ 'SORTING.EXPLANATION.COCKTAIL_SORT_EXPLANATION' | translate}}
|
||||
<a href="{{UrlConstants.SHAKE_SORT_WIKI}}" target="_blank" rel="noopener noreferrer">Wikipedia</a>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<strong>Quick Sort</strong> {{ 'SORTING.EXPLANATION.QUICK_SORT_EXPLANATION' | translate}}
|
||||
<a href="{{UrlConstants.QUICK_SORT_WIKI}}" target="_blank" rel="noopener noreferrer">Wikipedia</a>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import {ChangeDetectorRef, Component, OnInit} from '@angular/core';
|
||||
import {ChangeDetectorRef, Component, inject, OnInit} from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import {MatCardModule} from "@angular/material/card";
|
||||
import {MatFormFieldModule} from "@angular/material/form-field";
|
||||
@@ -20,26 +20,28 @@ import {UrlConstants} from '../../../constants/UrlConstants';
|
||||
})
|
||||
export class SortingComponent implements OnInit {
|
||||
|
||||
private readonly sortingService: SortingService = inject(SortingService);
|
||||
private readonly cdr: ChangeDetectorRef = inject(ChangeDetectorRef);
|
||||
|
||||
readonly MAX_ARRAY_SIZE: number = 200;
|
||||
readonly MIN_ARRAY_SIZE: number = 20;
|
||||
|
||||
private timeoutIds: any[] = [];
|
||||
private timeoutIds: number[] = [];
|
||||
sortArray: SortData[] = [];
|
||||
unsortedArrayCopy: SortData[] = [];
|
||||
arraySize: number = 100;
|
||||
maxArrayValue: number = 100;
|
||||
animationSpeed: number = 50; // Milliseconds per step
|
||||
arraySize = 50;
|
||||
maxArrayValue = 100;
|
||||
animationSpeed = 50; // Milliseconds per step
|
||||
|
||||
// Placeholder for available sorting algorithms
|
||||
availableAlgorithms: { name: string; value: string }[] = [
|
||||
{ name: 'Bubble Sort', value: 'bubbleSort' },
|
||||
{ name: 'Cocktail Sort', value: 'cocktailSort' },
|
||||
{ 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) { }
|
||||
executionTime = 0;
|
||||
|
||||
ngOnInit(): void {
|
||||
this.generateNewArray();
|
||||
@@ -76,8 +78,8 @@ export class SortingComponent implements OnInit {
|
||||
|
||||
private resetSortState() {
|
||||
for (let i = 0; i < this.sortArray.length; i++) {
|
||||
let element = this.sortArray[i];
|
||||
let unsortedElement = this.unsortedArrayCopy[i];
|
||||
const element = this.sortArray[i];
|
||||
const unsortedElement = this.unsortedArrayCopy[i];
|
||||
element.value = unsortedElement.value;
|
||||
element.state = 'unsorted';
|
||||
}
|
||||
@@ -98,6 +100,9 @@ export class SortingComponent implements OnInit {
|
||||
case 'heapSort':
|
||||
snapshots = this.sortingService.heapSort(this.sortArray);
|
||||
break;
|
||||
case 'cocktailSort':
|
||||
snapshots = this.sortingService.cocktailSort(this.sortArray);
|
||||
break;
|
||||
}
|
||||
|
||||
const endTime = performance.now();
|
||||
|
||||
Reference in New Issue
Block a user