-
Notifications
You must be signed in to change notification settings - Fork 1.5k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add implementation for basic timsorter
- Loading branch information
Showing
3 changed files
with
157 additions
and
0 deletions.
There are no files selected for viewing
60 changes: 60 additions & 0 deletions
60
Algorithms.Tests/Sorters/Comparison/BasicTeamSorterTests.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
using Algorithms.Sorters.Comparison; | ||
using NUnit.Framework; | ||
using System.Collections.Generic; | ||
|
||
namespace Algorithms.Tests.Sorters.Comparison | ||
{ | ||
[TestFixture] | ||
public class BasicTimSorterTests | ||
{ | ||
private BasicTimSorter<int> sorter = new BasicTimSorter<int>(Comparer<int>.Default); | ||
|
||
[Test] | ||
public void Sort_EmptyArray_DoesNotThrow() | ||
{ | ||
var array = new int[] { }; | ||
Assert.DoesNotThrow(() => sorter.Sort(array)); | ||
Assert.That(array, Is.Empty); | ||
} | ||
|
||
[Test] | ||
public void Sort_SingleElementArray_DoesNotChangeArray() | ||
{ | ||
var array = new[] { 1 }; | ||
sorter.Sort(array); | ||
Assert.That(array, Is.EqualTo(new[] { 1 })); | ||
} | ||
|
||
[Test] | ||
public void Sort_AlreadySortedArray_DoesNotChangeArray() | ||
{ | ||
var array = new[] { 1, 2, 3, 4, 5 }; | ||
sorter.Sort(array); | ||
Assert.That(array, Is.EqualTo(new[] { 1, 2, 3, 4, 5 })); | ||
} | ||
|
||
[Test] | ||
public void Sort_UnsortedArray_SortsCorrectly() | ||
{ | ||
var array = new[] { 5, 3, 1, 4, 2 }; | ||
sorter.Sort(array); | ||
Assert.That(array, Is.EqualTo(new[] { 1, 2, 3, 4, 5 })); | ||
} | ||
|
||
[Test] | ||
public void Sort_ReverseSortedArray_SortsCorrectly() | ||
{ | ||
var array = new[] { 5, 4, 3, 2, 1 }; | ||
sorter.Sort(array); | ||
Assert.That(array, Is.EqualTo(new[] { 1, 2, 3, 4, 5 })); | ||
} | ||
|
||
[Test] | ||
public void Sort_ArrayWithDuplicates_SortsCorrectly() | ||
{ | ||
var array = new[] { 3, 1, 2, 3, 1, 2 }; | ||
sorter.Sort(array); | ||
Assert.That(array, Is.EqualTo(new[] { 1, 1, 2, 2, 3, 3 })); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
using System; | ||
using System.Collections; | ||
using System.Collections.Generic; | ||
|
||
namespace Algorithms.Sorters.Comparison | ||
{ | ||
public class BasicTimSorter<T> | ||
{ | ||
private readonly int minRuns = 32; | ||
private readonly IComparer<T> comparer; | ||
|
||
public BasicTimSorter(IComparer<T> comparer) | ||
{ | ||
this.comparer = comparer ?? Comparer<T>.Default; | ||
} | ||
|
||
public void Sort(T[] array) | ||
{ | ||
var n = array.Length; | ||
|
||
// Step 1: Sort small pieces of the array using Insertion Sort | ||
for (var i = 0; i < n; i += minRuns) | ||
{ | ||
InsertionSort(array, i, Math.Min(i + minRuns - 1, n - 1)); | ||
} | ||
|
||
// Step 2: Merge sorted runs using Merge Sort | ||
for (var size = minRuns; size < n; size *= 2) | ||
{ | ||
for (var left = 0; left < n; left += 2 * size) | ||
{ | ||
var mid = left + size - 1; | ||
var right = Math.Min(left + 2 * size - 1, n - 1); | ||
|
||
if (mid < right) | ||
{ | ||
Merge(array, left, mid, right); | ||
} | ||
} | ||
} | ||
} | ||
|
||
private void InsertionSort(T[] array, int left, int right) | ||
{ | ||
for (var i = left + 1; i <= right; i++) | ||
{ | ||
var key = array[i]; | ||
var j = i - 1; | ||
|
||
while (j >= left && comparer.Compare(array[j], key) > 0) | ||
{ | ||
array[j + 1] = array[j]; | ||
j--; | ||
} | ||
|
||
array[j + 1] = key; | ||
} | ||
} | ||
|
||
private void Merge(T[] array, int left, int mid, int right) | ||
{ | ||
var leftSegment = new ArraySegment<T>(array, left, mid - left + 1); | ||
var rightSegment = new ArraySegment<T>(array, mid + 1, right - mid); | ||
|
||
var leftArray = leftSegment.ToArray(); | ||
var rightArray = rightSegment.ToArray(); | ||
|
||
int i = 0, j = 0, k = left; | ||
|
||
// Merge the two subarrays back into the main array | ||
while (i < leftArray.Length && j < rightArray.Length) | ||
{ | ||
if (comparer.Compare(leftArray[i], rightArray[j]) <= 0) | ||
{ | ||
array[k++] = leftArray[i++]; | ||
} | ||
else | ||
{ | ||
array[k++] = rightArray[j++]; | ||
} | ||
} | ||
|
||
// Copy remaining elements from leftArray, if any | ||
while (i < leftArray.Length) | ||
{ | ||
array[k++] = leftArray[i++]; | ||
} | ||
|
||
// Copy remaining elements from rightArray, if any | ||
while (j < rightArray.Length) | ||
{ | ||
array[k++] = rightArray[j++]; | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters