Skip to content

Commit a3e4b5c

Browse files
author
Oskar Widmark
committed
feat: recursive odd-even mergesort
1 parent 67a2d3f commit a3e4b5c

File tree

3 files changed

+61
-7
lines changed

3 files changed

+61
-7
lines changed

src/Options.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ const getAlgorithmOptionFields = (
1313
): (keyof AlgorithmOptions)[] => {
1414
switch (sortName) {
1515
case SortName.BitonicSort:
16+
case SortName.OddEvenMergesort:
1617
return ['type'];
1718
case SortName.RadixSortLSD:
1819
case SortName.RadixSortMSD:

src/SideDrawer.tsx

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -71,14 +71,17 @@ export function SideDrawer({
7171
setBackgroundColor,
7272
setHighlightColor,
7373
}: SideDrawerProps) {
74-
const isBitonicSort = chosenSortAlg === SortName.BitonicSort;
74+
// Bitonic Sort and recursive Odd-even mergesort requires a power of two
75+
const requiresPowerOfTwoColumns =
76+
chosenSortAlg === SortName.BitonicSort ||
77+
(chosenSortAlg === SortName.OddEvenMergesort &&
78+
algorithmOptions.type === 'recursive');
7579

7680
useEffect(() => {
77-
// Bitonic Sort requires a power of two
78-
if (isBitonicSort) {
81+
if (requiresPowerOfTwoColumns) {
7982
changeColumnNbr(undefined, 2 ** Math.floor(Math.log2(columnNbr)));
8083
}
81-
}, [isBitonicSort, changeColumnNbr, columnNbr]);
84+
}, [requiresPowerOfTwoColumns, changeColumnNbr, columnNbr]);
8285

8386
return (
8487
<Drawer
@@ -137,9 +140,9 @@ export function SideDrawer({
137140
valueLabelDisplay="auto"
138141
min={8}
139142
max={1024}
140-
step={isBitonicSort ? null : 1}
143+
step={requiresPowerOfTwoColumns ? null : 1}
141144
marks={
142-
isBitonicSort
145+
requiresPowerOfTwoColumns
143146
? POWERS_OF_TWO.map((value) => ({
144147
value,
145148
}))

src/sorting-algorithms.ts

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,8 +97,17 @@ export class SortingAlgorithms {
9797
}
9898
}
9999

100+
public async oddEvenMergesort(arr: SortValue[], options: AlgorithmOptions) {
101+
switch (options.type) {
102+
case 'iterative':
103+
return await this.iterOddEvenMergesort(arr);
104+
case 'recursive':
105+
return await this.recOddEvenMergesort(arr, 0, this._columnNbr);
106+
}
107+
}
108+
100109
// TODO: make "parallel"(?)
101-
public async oddEvenMergesort(arr: SortValue[]) {
110+
public async iterOddEvenMergesort(arr: SortValue[]) {
102111
for (let p = 1; p < arr.length; p *= 2) {
103112
for (let k = p; k > 0; k = Math.floor(k / 2)) {
104113
for (let j = k % p; j < arr.length - k; j += 2 * k) {
@@ -116,6 +125,47 @@ export class SortingAlgorithms {
116125
}
117126
}
118127

128+
private async recOddEvenMergesort(
129+
arr: SortValue[],
130+
start: number,
131+
end: number,
132+
) {
133+
if (end - start <= 1) return;
134+
135+
const mid = Math.floor((start + end) / 2);
136+
await this.recOddEvenMergesort(arr, start, mid);
137+
await this.recOddEvenMergesort(arr, mid, end);
138+
139+
await this.oddEvenMerge(arr, start, end, 1);
140+
}
141+
142+
private async oddEvenMerge(
143+
arr: SortValue[],
144+
start: number,
145+
end: number,
146+
dist: number,
147+
) {
148+
const newDist = dist * 2;
149+
if (end - start <= newDist && start + dist < arr.length) {
150+
if (await this.compare(arr, start, '>', start + dist)) {
151+
await this.drawAndSwap(arr, start, start + dist);
152+
}
153+
return;
154+
}
155+
156+
// Even indices
157+
await this.oddEvenMerge(arr, start, end, newDist);
158+
// Odd indices
159+
await this.oddEvenMerge(arr, start + dist, end, newDist);
160+
161+
for (let i = start + dist; i < end - dist; i += newDist) {
162+
const j = i + dist;
163+
if (await this.compare(arr, i, '>', j)) {
164+
await this.drawAndSwap(arr, i, j);
165+
}
166+
}
167+
}
168+
119169
public async combSort(arr: SortValue[], options: AlgorithmOptions) {
120170
let gap = this._columnNbr;
121171
const { shrinkFactor } = options;

0 commit comments

Comments
 (0)