C# 十种排序方法

using System;
using System.Collections.Generic;
using UnityEngine;

/// <summary>
/// 排序逻辑控制器
/// </summary>
public class SortController : MonoBehaviour
{
    private static SortController _instance;

    public static SortController GetInstance()
    {
        return _instance;
    }

    void Awake()
    {
        if (_instance == null)
        {
            _instance = this;
            DontDestroyOnLoad(gameObject);
        }
        else
        {
            if (_instance != this)
            {
                Debug.Log("warning: multiple Manager creating!");
                GameObject.Destroy(gameObject);
            }
        }
    }

    #region 选择排序

    /// <summary>
    /// 选择排序
    /// </summary>
    /// <param name="arr">需要排序的数组值</param>
    /// <returns></returns>
    public int[] SelectSort(int[] arr)
    {
        int n = arr.Length;
        for (int i = 0; i < n - 1; i++)
        {
            int min = i;
            for (int j = i + 1; j < n; j++)
            {
                if (arr[min] > arr[j]) min = j;
            }

            //交换
            int temp = arr[i];
            arr[i] = arr[min];
            arr[min] = temp;
        }

        return arr;
    }

    #endregion

    #region 插入排序

    /// <summary>
    /// 插入排序
    /// </summary>
    /// <param name="arr">需要排序的数组值</param>
    /// <returns></returns>
    public int[] InsertSort(int[] arr)
    {
        if (arr == null || arr.Length < 2)
            return arr;

        int n = arr.Length;
        for (int i = 1; i < n; i++)
        {
            int temp = arr[i];
            int k = i - 1;
            while (k >= 0 && arr[k] > temp)
                k--;
            //腾出位置插进去,要插的位置是 k + 1;
            for (int j = i; j > k + 1; j--)
                arr[j] = arr[j - 1];
            //插进去
            arr[k + 1] = temp;
        }

        return arr;
    }

    #endregion

    #region 冒泡排序

    /// <summary>
    /// 冒泡排序
    /// </summary>
    /// <param name="arr">需要排序的数组值</param>
    /// <returns></returns>
    public int[] BubbleSort(int[] arr)
    {
        if (arr == null || arr.Length < 2)
        {
            return arr;
        }

        int n = arr.Length;
        for (int i = 0; i < n; i++)
        {
            for (int j = 0; j < n - i - 1; j++)
            {
                if (arr[j + 1] < arr[j])
                {
                    int t = arr[j];
                    arr[j] = arr[j + 1];
                    arr[j + 1] = t;
                }
            }
        }

        return arr;
    }

    #endregion

    #region 希尔排序

    /// <summary>
    /// 希尔排序
    /// </summary>
    /// <param name="arr">需要排序的数组值</param>
    /// <returns></returns>
    public int[] ShellSort(int[] arr)
    {
        if (arr == null || arr.Length < 2) return arr;
        int n = arr.Length;
        // 对每组间隔为 h的分组进行排序,刚开始 h = n / 2;
        for (int h = n / 2; h > 0; h /= 2)
        {
            //对各个局部分组进行插入排序
            for (int i = h; i < n; i++)
            {
                // 将arr[i] 插入到所在分组的正确位置上
                InsertIValue(arr, h, i);
            }
        }

        return arr;
    }

    /// <summary>
    /// 将arr[i]插入到所在分组的正确位置上,arr[i]] 所在的分组为 ... arr[i-2*h],arr[i-h], arr[i+h] ...
    /// </summary>
    /// <param name="arr"></param>
    /// <param name="h"></param>
    /// <param name="i"></param>
    private void InsertIValue(int[] arr, int h, int i)
    {
        int temp = arr[i];
        int k;
        for (k = i - h; k > 0 && temp < arr[k]; k -= h)
        {
            arr[k + h] = arr[k];
        }

        arr[k + h] = temp;
    }

    #endregion

    #region 归并排序

    /// <summary>
    /// 归并排序(递归式)
    /// </summary>
    /// <param name="arr">需要排序的数组值</param>
    /// <param name="left">左半部分索引</param>
    /// <param name="right">右半部分索引</param>
    /// <returns></returns>
    public int[] MergeSort(int[] arr, int left, int right)
    {
        // 如果 left == right,表示数组只有一个元素,则不用递归排序
        if (left < right)
        {
            // 把大的数组分隔成两个数组
            int mid = (left + right) / 2;
            // 对左半部分进行排序
            arr = MergeSort(arr, left, mid);
            // 对右半部分进行排序
            arr = MergeSort(arr, mid + 1, right);
            //进行合并
            Merge(arr, left, mid, right);
        }

        return arr;
    }

    /// <summary>
    /// 归并排序(非递归式)
    /// </summary>
    /// <param name="arr"></param>
    /// <returns></returns>
    public int[] MergeNonFuncSort(int[] arr)
    {
        int n = arr.Length;
        //子数组的大小分别为1,2,4,8...,合并的数组大小是1,接着是2,接着4...
        for (int i = 1; i < n; i += i)
        {
            //进行数组进行划分
            int left = 0;
            int mid = left + i - 1;
            int right = mid + i;
            //进行合并,对数组大小为 i 的数组进行两两合并
            while (right < n)
            {
                //合并函数和递归式的合并函数一样
                Merge(arr, left, mid, right);
                left = right + 1;
                mid = left + i - 1;
                right = mid + i;
            }

            // 剩余数组合并
            if (left < n && mid < n)
            {
                Merge(arr, left, mid, n - 1);
            }
        }

        return arr;
    }

    /// <summary>
    /// 合并函数,把两个有序的数组合并起来。arr[left..mif]表示一个数组,arr[mid+1 .. right]表示一个数组
    /// </summary>
    /// <param name="arr"></param>
    /// <param name="left"></param>
    /// <param name="mid"></param>
    /// <param name="right"></param>
    private void Merge(int[] arr, int left, int mid, int right)
    {
        //临时数组进行合并汇总
        int[] a = new int[right - left + 1];
        int i = left;
        int j = mid + 1;
        int k = 0;
        while (i <= mid && j <= right)
        {
            if (arr[i] < arr[j])
            {
                a[k++] = arr[i++];
            }
            else
            {
                a[k++] = arr[j++];
            }
        }

        while (i <= mid) a[k++] = arr[i++];
        while (j <= right) a[k++] = arr[j++];
        //临时数组复制到原数组
        for (i = 0; i < k; i++)
        {
            arr[left++] = a[i];
        }
    }

    #endregion

    #region 快速排序

    /// <summary>
    /// 快速排序
    /// </summary>
    /// <param name="arr">需要排序的数组值</param>
    /// <param name="left"></param>
    /// <param name="right"></param>
    /// <returns></returns>
    public int[] QuickSort(int[] arr, int left, int right)
    {
        if (left < right)
        {
            //获取中轴元素所处的位置
            int mid = PartPosition(arr, left, right);
            //进行分割
            arr = QuickSort(arr, left, mid - 1);
            arr = QuickSort(arr, mid + 1, right);
        }

        return arr;
    }

    /// <summary>
    /// 获取中轴元素所处的位置
    /// </summary>
    /// <param name="arr"></param>
    /// <param name="left"></param>
    /// <param name="right"></param>
    /// <returns></returns>
    private int PartPosition(int[] arr, int left, int right)
    {
        //选取中轴元素
        int pivot = arr[left];
        int i = left + 1;
        int j = right;
        while (true)
        {
            // 向右找到第一个小于等于 pivot 的元素位置
            while (i <= j && arr[i] <= pivot) i++;
            // 向左找到第一个大于等于 pivot 的元素位置
            while (i <= j && arr[j] >= pivot) j--;
            if (i >= j)
                break;
            //交换两个元素的位置,使得左边的元素不大于pivot,右边的不小于pivot
            int temp = arr[i];
            arr[i] = arr[j];
            arr[j] = temp;
        }

        arr[left] = arr[j];
        // 使中轴元素处于有序的位置
        arr[j] = pivot;
        return j;
    }

    #endregion

    #region 堆排序

    /// <summary>
    /// 堆排序
    /// </summary>
    /// <param name="arr"></param>
    /// <returns></returns>
    public int[] HeadSort(int[] arr)
    {
        int n = arr.Length;
        //构建大顶堆
        for (int i = (n - 2) / 2; i >= 0; i--)
        {
            DownAdjust(arr, i, n - 1);
        }

        //进行堆排序
        for (int i = n - 1; i >= 1; i--)
        {
            // 把堆顶元素与最后一个元素交换
            int temp = arr[i];
            arr[i] = arr[0];
            arr[0] = temp;
            // 把打乱的堆进行调整,恢复堆的特性
            DownAdjust(arr, 0, i - 1);
        }

        return arr;
    }

    /// <summary>
    /// 下沉操作
    /// </summary>
    /// <param name="arr"></param>
    /// <param name="parent"></param>
    /// <param name="n"></param>
    public void DownAdjust(int[] arr, int parent, int n)
    {
        //临时保存要下沉的元素
        int temp = arr[parent];
        //定位左孩子节点的位置
        int child = 2 * parent + 1;
        //开始下沉
        while (child <= n)
        {
            // 如果右孩子节点比左孩子大,则定位到右孩子
            if (child + 1 <= n && arr[child] < arr[child + 1])
                child++;
            // 如果孩子节点小于或等于父节点,则下沉结束
            if (arr[child] <= temp) break;
            // 父节点进行下沉
            arr[parent] = arr[child];
            parent = child;
            child = 2 * parent + 1;
        }

        arr[parent] = temp;
    }

    #endregion

    #region 计算排序

    /// <summary>
    /// 计算排序
    /// </summary>
    /// <param name="arr"></param>
    /// <returns></returns>
    public int[] CountSort(int[] arr)
    {
        if (arr == null || arr.Length < 2) return arr;

        int n = arr.Length;
        int min = arr[0];
        int max = arr[0];
        // 寻找数组的最大值与最小值
        for (int i = 1; i < n; i++)
        {
            if (max < arr[i])
                max = arr[i];
            if (min > arr[i])
                min = arr[i];
        }

        int d = max - min + 1;
        //创建大小为max的临时数组
        int[] temp = new int[d];
        //统计元素i出现的次数
        for (int i = 0; i < n; i++)
        {
            temp[arr[i] - min]++;
        }

        int k = 0;
        //把临时数组统计好的数据汇总到原数组
        for (int i = 0; i < d; i++)
        {
            for (int j = temp[i]; j > 0; j--)
            {
                arr[k++] = i + min;
            }
        }

        return arr;
    }

    #endregion

    #region 桶排序

    /// <summary>
    /// 桶排序
    /// </summary>
    /// <param name="arr"></param>
    /// <param name="bucketNum"></param>
    public double[] BucketSort(double[] arr, int bucketNum)
    {
        //创建bucket时,在二维中增加一组标识位,其中bucket[x, 0]表示这一维所包含的数字的个数
        //通过这样的技巧可以少写很多代码
        double[,] bucket = new double[bucketNum, arr.Length + 1];
        foreach (var num in arr)
        {
            int bit = (int) (bucketNum * num);
            bucket[bit, (int) ++bucket[bit, 0]] = num;
        }

        //为桶里的每一行使用插入排序
        for (int j = 0; j < bucketNum; j++)
        {
            //为桶里的行创建新的数组后使用插入排序
            double[] insertion = new double[(int) bucket[j, 0]];
            for (int k = 0; k < insertion.Length; k++)
            {
                insertion[k] = bucket[j, k + 1];
            }

            //调用插入排序
            StraightInsertionSort(insertion);
            //把排好序的结果回写到桶里
            for (int k = 0; k < insertion.Length; k++)
            {
                bucket[j, k + 1] = insertion[k];
            }
        }

        //将所有桶里的数据回写到原数组中
        for (int count = 0, j = 0; j < bucketNum; j++)
        {
            for (int k = 1; k <= bucket[j, 0]; k++)
            {
                arr[count++] = bucket[j, k];
            }
        }

        return arr;
    }

    private void StraightInsertionSort(double[] array)
    {
        //插入排序
        for (int i = 1; i < array.Length; i++)
        {
            double sentinel = array[i];
            int j = i - 1;
            while (j >= 0 && sentinel < array[j])
            {
                array[j + 1] = array[j];
                j--;
            }

            array[j + 1] = sentinel;
        }
    }

    #endregion

    #region 基数排序

    /// <summary>
    /// 基数排序
    /// </summary>
    /// <param name="myArray"></param>
    /// <param name="keyNum"></param>
    public int[] RandixSort(int[] myArray, int keyNum)
    {
        SingleLinkedList<int> listArray = new SingleLinkedList<int>();
        foreach (int i in myArray)
        {
            listArray.AddLast(new SingleLLNode<int>() {Value = i});
        }

        for (int i = 0; i < keyNum; i++)
        {
            // 对每个关键字执行分配和收集操作
            DistributeAndCollect(listArray, i);
        }

        int j = 0;
        while (listArray.First != null)
        {
            myArray[j++] = listArray.First.Value;
            listArray.First = listArray.First.Next;
        }

        return myArray;
    }

    /// <summary>
    /// 分配和收集
    /// </summary>
    /// <param name="listArray"></param>
    /// <param name="i"></param>
    private void DistributeAndCollect(SingleLinkedList<int> listArray, int i)
    {
        int randix = 10; //关键字取值范围
        int divider = (int) Math.Pow(10, i);
        List<SingleLinkedList<int>> subLists = new List<SingleLinkedList<int>>(); //建立子序列
        for (int j = 0; j < randix; j++)
        {
            subLists.Add(new SingleLinkedList<int>());
        }

        // 开始一次分配
        while (listArray.First != null)
        {
            int index = (listArray.First.Value / divider) % 10;

            SingleLLNode<int> tempNode = listArray.First.Next;
            subLists[index].AddLast(listArray.First);
            listArray.First = tempNode;
        }

        // 开始一次收集
        int k = 0;
        for (; k < randix; k++)
        {
            if (subLists[k].First != null)
            {
                // 找到第一个非空子序列以设置总序列的First值
                listArray.First = subLists[k].First;
                listArray.Last = subLists[k].Last;
                break;
            }
        }

        // 找好子序列设置好listArray.First后,开始处理非空子序列的首尾相连
        for (; k < randix; k++)
        {
            if (subLists[k].First != null)
            {
                listArray.Last.Next = subLists[k].First;
                listArray.Last = subLists[k].Last;
            }
        }
    }

    #endregion
}

// 单链表
class SingleLinkedList<T>
{
    public SingleLLNode<T> First { get; set; }

    public SingleLLNode<T> Last { get; set; }

    public void AddLast(SingleLLNode<T> node)
    {
        if (First == null)
        {
            First = node;
            Last = node;
            node.Next = null;
        }
        else
        {
            Last.Next = node;
            Last = node;
            node.Next = null;
        }
    }
}

// 单链表结点
class SingleLLNode<T>
{
    public T Value { get; set; }

    public SingleLLNode<T> Next { get; set; }
}

转载:https://developer.unity.cn/projects/61c307dfedbc2a001f3bb4b7

  • 4
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值