Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
87 changes: 87 additions & 0 deletions Algorithms.Tests/Sorters/Comparison/BasicTeamSorterTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
using Algorithms.Sorters.Comparison;
using FluentAssertions;
using NUnit.Framework;
using System;
using System.Collections.Generic;

namespace Algorithms.Tests.Sorters.Comparison
{
[TestFixture]
public class BasicTimSorterTests
{
private readonly BasicTimSorter<int> sorter = new(Comparer<int>.Default);

[Test]
public void Sort_EmptyArray_DoesNotThrow()
{
var array = Array.Empty<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 }));
}

[Test]
public void Sort_LargeArray_SortsCorrectly()
{
var array = new int[1000];
for (var i = 0; i < 1000; i++)
{
array[i] = 1000 - i;
}
sorter.Sort(array);
array.Should().BeInAscendingOrder();
}

[Test]
public void Sort_LargeRandomArray_SortsCorrectly()
{
var array = new int[1000];
var random = new Random();
for (var i = 0; i < 1000; i++)
{
array[i] = random.Next(1, 1001);
}
sorter.Sort(array);
array.Should().BeInAscendingOrder();
}
}
}
120 changes: 120 additions & 0 deletions Algorithms/Sorters/Comparison/BasicTimSorter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
using System;
using System.Collections;
using System.Collections.Generic;

namespace Algorithms.Sorters.Comparison
{
/// <summary>
/// A basic implementation of the TimSort algorithm for sorting arrays.
/// </summary>
/// <typeparam name="T">The type of elements in the array.</typeparam>
public class BasicTimSorter<T>
{
private readonly int minRuns = 32;
private readonly IComparer<T> comparer;

/// <summary>
/// Initializes a new instance of the <see cref="BasicTimSorter{T}"/> class.
/// </summary>
/// <param name="comparer">The comparer to use for comparing elements.</param>
public BasicTimSorter(IComparer<T> comparer)
{
this.comparer = comparer ?? Comparer<T>.Default;
}

/// <summary>
/// Sorts the specified array using the TimSort algorithm.
/// </summary>
/// <param name="array">The array to sort.</param>
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);
}
}
}
}

/// <summary>
/// Sorts a portion of the array using the Insertion Sort algorithm.
/// </summary>
/// <param name="array">The array to sort.</param>
/// <param name="left">The starting index of the portion to sort.</param>
/// <param name="right">The ending index of the portion to sort.</param>
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;

// Move elements of array[0..i-1], that are greater than key,
// to one position ahead of their current position
while (j >= left && comparer.Compare(array[j], key) > 0)
{
array[j + 1] = array[j];
j--;
}

array[j + 1] = key;
}
}

/// <summary>
/// Merges two sorted subarrays into a single sorted subarray.
/// </summary>
/// <param name="array">The array containing the subarrays to merge.</param>
/// <param name="left">The starting index of the first subarray.</param>
/// <param name="mid">The ending index of the first subarray.</param>
/// <param name="right">The ending index of the second subarray.</param>
private void Merge(T[] array, int left, int mid, int right)
{
// Create segments for left and right subarrays
var leftSegment = new ArraySegment<T>(array, left, mid - left + 1);
var rightSegment = new ArraySegment<T>(array, mid + 1, right - mid);

// Convert segments to arrays
var leftArray = leftSegment.ToArray();
var rightArray = rightSegment.ToArray();

var i = 0;
var j = 0;
var k = left;

// Merge the two subarrays back into the main array
while (i < leftArray.Length && j < rightArray.Length)
{
array[k++] = comparer.Compare(leftArray[i], rightArray[j]) <= 0 ? leftArray[i++] : 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++];
}
}
}
}
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ find more than one implementation for the same objective but using different alg
* [Selection Sort](./Algorithms/Sorters/Comparison/SelectionSorter.cs)
* [Shell Sort](./Algorithms/Sorters/Comparison/ShellSorter.cs)
* [Tim Sort](./Algorithms/Sorters/Comparison/TimSorter.cs)
* [Simplified Tim Sort](./Algorithms/Sorters/Comparison/BasicTimSorter.cs)
* [External](./Algorithms/Sorters/External)
* [Merge Sort](./Algorithms/Sorters/External/ExternalMergeSorter.cs)
* [Integer](./Algorithms/Sorters/Integer)
Expand Down
Loading