C # implements various sorting algorithms

C # implements various sorts

Key points and implementation of each sort

In this article, the parameter func < T, t, bool > comp means that there can be no comp(list[j], list[i]) for any I < J after sorting

Bubble sorting

  • Each cycle puts the maximum value to the front or last
  • Reverse order, only need to access list.Count once (optional)
  • Use the sorted boolean variable. If you have sorted halfway, you don't need to continue sorting (optional)
  • Stable, the maximum value floats stably
public static void BubbleSort<T>(IList<T> list)
    where T : IComparable<T>
{
    for (int i = list.Count; i > 0; i--)
    {
        bool sorted = true;
        for (int j = 1; j < i; j++)
        {
            if (list[j].CompareTo(list[j - 1]) < 0)
            {
                T swap = list[j - 1];
                list[j - 1] = list[j];
                list[j] = swap;
                sorted = false;
            }
        }
        if (sorted)
            return;
    }
}
public static void BubbleSort<T>(IList<T> list, Func<T, T, bool> comp)
{
    for (int i = list.Count; i > 0; i--)
    {
        bool sorted = true;
        for (int j = 1; j < i; j++)
        {
            if (comp(list[j], list[j - 1]))
            {
                T swap = list[j - 1];
                list[j - 1] = list[j];
                list[j] = swap;
                sorted = false;
            }
        }
        if (sorted)
            return;
    }
}

Select sort

  • Each time, the most value of the unordered segment is selected and added to the sorted segment
  • Reverse order, only need to access list.Count once (optional)
  • Unstable. When the maximum value is put into the sorting segment, the position of the number exchanged with the maximum value changes
public static void SelectionSort<T>(IList<T> list)
    where T : IComparable<T>
{
    for (int i = list.Count - 1; i > 0; i--)
    {
        int maxIndex = i;
        T maxValue = list[i];
        for (int j = i - 1; j >= 0; j--)
        {
            T value = list[j];
            if (maxValue.CompareTo(value) < 0)
            {
                maxValue = value;
                maxIndex = j;
            }
        }
        T swap = list[i];
        list[i] = list[maxIndex];
        list[maxIndex] = swap;
    }
}
public static void SelectionSort<T>(IList<T> list, Func<T, T, bool> comp)
{
    for (int i = list.Count - 1; i > 0; i--)
    {
        int maxIndex = i;
        T maxValue = list[i];
        for (int j = i - 1; j >= 0; j--)
        {
            T value = list[j];
            if (comp(maxValue, value))
            {
                maxValue = value;
                maxIndex = j;
            }
        }
        T swap = list[i];
        list[i] = list[maxIndex];
        list[maxIndex] = swap;
    }
}

Insert sort

  • Inserts a new value into a sorted segment
  • The sorting segment is sorted, and you can use binary search to find the insertion position (other methods can be used)
  • Stable, the same value is encountered during insertion, and the relative position is maintained
public static void InsertionSort<T>(IList<T> list)
    where T : IComparable<T>
{
    int count = list.Count;
    for (int i = 1; i < count; i++)
    {
        T insert = list[i];
        int low = -1, high = i;
        do
        {
            int mid = ((high - low) >> 1) + low;
            if (insert.CompareTo(list[mid]) < 0)
                high = mid;
            else
                low = mid;
        } while (low + 1 != high);
        for (int j = i; j > high; j--)
            list[j] = list[j - 1];
        list[high] = insert;
    }
}
public static void InsertionSort<T>(IList<T> list, Func<T, T, bool> comp)
{
    int count = list.Count;
    for (int i = 1; i < count; i++)
    {
        T insert = list[i];
        int low = -1, high = i;
        do
        {
            int mid = ((high - low) >> 1) + low;
            if (comp(insert, list[mid]))
                high = mid;
            else
                low = mid;
        } while (low + 1 != high);
        for (int j = i; j > high; j--)
            list[j] = list[j - 1];
        list[high] = insert;
    }
}

Shell Sort

  • At the end of each cycle, the values separated by an interval are regarded as a group, which is orderly
  • The interval size and the multiple of each interval reduction can be selected
  • Unstable, the value may jump to another interval
public static void ShellSort<T>(IList<T> list)
    where T : IComparable<T>
{
    int count = list.Count;
    int seg = (count >> 1) + 1;
    while (seg > 0)
    {
        for (int i = seg; i < count; i++)
        {
            for (int j = i;
                 j >= seg && list[j].CompareTo(list[j - seg]) < 0;
                 j -= seg)
            {
                T swap = list[j];
                list[j] = list[j - seg];
                list[j - seg] = swap;
            }
        }
        seg /= 2;
    }
}
public static void ShellSort<T>(IList<T> list, Func<T, T, bool> comp)
{
    int count = list.Count;
    int seg = (count >> 1) + 1;
    while (seg > 0)
    {
        for (int i = seg; i < count; i++)
        {
            for (int j = i;
                 j >= seg && comp(list[j], list[j - seg]);
                 j -= seg)
            {
                T swap = list[j];
                list[j] = list[j - seg];
                list[j - seg] = swap;
            }
        }
        seg /= 2;
    }
}

Heap sort

  • array → \rightarrow → pile → \rightarrow → sorted array
  • Heap is a complete binary tree, which can be realized by array
  • Computers tend to load the values of adjacent addresses at the same time. The index jumps too much in the array, so it is difficult to use this function
  • Unstable, values move in the heap, and the relative position of the same values is affected by the values between them
public static void HeapSort<T>(IList<T> list)
    where T : IComparable<T>
{
    int i = 0, count = list.Count;
    while (++i < count)
    {
        int j = i;
        int up;
        while (j > 0 && list[up = (j - 1) >> 1].CompareTo(list[j]) < 0)
        {
            T swap = list[up];
            list[up] = list[j];
            list[j] = swap;
            j = up;
        }
    }
    while (--i > 0)
    {
        T swap = list[i];
        list[i] = list[0];
        list[0] = swap;
        int j = 0;
        int down;
        while ((down = (j << 1) + 1) < i)
        {
            if (down + 1 < i && list[down].CompareTo(list[down + 1]) < 0)
                down++;
            if (list[down].CompareTo(list[j]) < 0)
                break;
            swap = list[down];
            list[down] = list[j];
            list[j] = swap;
            j = down;
        }
    }
}
public static void HeapSort<T>(IList<T> list, Func<T, T, bool> comp)
{
    int i = 0, count = list.Count;
    while (++i < count)
    {
        int j = i;
        int up;
        while (j > 0 && comp(list[up = (j - 1) >> 1], list[j]))
        {
            var swap = list[up];
            list[up] = list[j];
            list[j] = swap;
            j = up;
        }
    }
    while (--i > 0)
    {
        var swap = list[i];
        list[i] = list[0];
        list[0] = swap;
        int j = 0;
        int down;
        while ((down = (j << 1) + 1) < i)
        {
            if (down + 1 < i && comp(list[down], list[down + 1]))
                down++;
            if (comp(list[down], list[j]))
                break;
            swap = list[down];
            list[down] = list[j];
            list[j] = swap;
            j = down;
        }
    }
}

Merge sort

  • Bottom up merge ordered arrays
  • Use the auxiliary array, use the pointer to exchange the identity of the original array and the auxiliary array many times, and finally put the result back to the original array
  • Stable, do not change the relative position when merging ordered arrays
public static void MergeSort<T>(IList<T> list)
    where T : IComparable<T>
{
    int count = list.Count;
    IList<T> a = list;
    IList<T> b = new T[count];
    for (int seg = 1; seg < count; seg <<= 1)
    {
        for (int low = 0; low < count; low += seg << 1)
        {
            int mid = Math.Min(count, low + seg);
            int high = Math.Min(count, low + (seg << 1));
            int i = low, j = mid, k = low;
            while (i != mid && j != high)
                b[k++] = a[j].CompareTo(a[i]) < 0 ? a[j++] : a[i++];
            while (i != mid)
                b[k++] = a[i++];
            while (j != high)
                b[k++] = a[j++];
        }
        var swap = a;
        a = b;
        b = swap;
    }
    if (!ReferenceEquals(a, list))
        for (int i = 0; i != count; i++)
            list[i] = a[i];
}
public static void MergeSort<T>(IList<T> list, Func<T, T, bool> comp)
{
    int count = list.Count;
    IList<T> a = list;
    IList<T> b = new T[count];
    for (int seg = 1; seg < count; seg <<= 1)
    {
        for (int low = 0; low < count; low += seg << 1)
        {
            int mid = Math.Min(count, low + seg);
            int high = Math.Min(count, low + (seg << 1));
            int i = low, j = mid, k = low;
            while (i != mid && j != high)
                b[k++] = comp(a[j], a[i]) ? a[j++] : a[i++];
            while (i != mid)
                b[k++] = a[i++];
            while (j != high)
                b[k++] = a[j++];
        }
        var swap = a;
        a = b;
        b = swap;
    }
    if (!ReferenceEquals(a, list))
        for (int i = 0; i != count; i++)
            list[i] = a[i];
}

Quick sort

  • Top down split array using base
  • Use random numbers to select the datum (optional)
  • Use the double pointer from front to back and from back to front respectively (other methods can be used)
  • Unstable, the exchange of double pointers will change the order
public static void QuickSort<T>(IList<T> list)
    where T : IComparable<T>
{
    Stack<(int, int)> ranges = new Stack<(int, int)>();
    Random rand = new Random();
    ranges.Push((0, list.Count));
    while (ranges.Count != 0)
    {
        (int low, int high) = ranges.Pop();
        if (high <= low + 1)
            continue;
        int temp = rand.Next(low, high);
        T sep = list[temp];
        list[temp] = list[low];
        list[low] = sep;
        int i = low, j = high;
        for (; ; )
        {
            do
                i++;
            while (i < high && list[i].CompareTo(sep) < 0);
            do
                j--;
            while (sep.CompareTo(list[j]) < 0);
            if (i > j)
                break;
            T swap = list[i];
            list[i] = list[j];
            list[j] = swap;
        }
        list[low] = list[j];
        list[j] = sep;
        ranges.Push((low, j));
        ranges.Push((i, high));
    }
}
public static void QuickSort<T>(IList<T> list, Func<T, T, bool> comp)
{
    Stack<(int, int)> ranges = new Stack<(int, int)>();
    Random rand = new Random();
    ranges.Push((0, list.Count));
    while (ranges.Count != 0)
    {
        (int low, int high) = ranges.Pop();
        if (high - low <= 1)
            continue;
        int temp = rand.Next(low, high);
        T sep = list[temp];
        list[temp] = list[low];
        list[low] = sep;
        int i = low, j = high;
        for (; ; )
        {
            do
                i++;
            while (i < high && comp(list[i], sep));
            do
                j--;
            while (comp(sep, list[j]));
            if (i > j)
                break;
            T swap = list[i];
            list[i] = list[j];
            list[j] = swap;
        }
        list[low] = list[j];
        list[j] = sep;
        ranges.Push((low, j));
        ranges.Push((i, high));
    }
}

Tags: C# Algorithm Permutation

Posted on Sat, 11 Sep 2021 14:14:12 -0400 by djumaka