C#排序算法

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

public class Algorithm : MonoBehaviour
{
    //排序算法
    public int[] arr = { 0, 5, 7, 6, 9, 4, 3, 2, 8, 1 };
    private void Update()
    {
        if (Input.GetKeyDown(KeyCode.A))
        {
            BubbleSort();
        } if (Input.GetKeyDown(KeyCode.S))
        {
            SelectionSort();
        } if (Input.GetKeyDown(KeyCode.D))
        {
            InsertionSortFor();
        } if (Input.GetKeyDown(KeyCode.F))
        {
            InsertionSortWhile();
        } if (Input.GetKeyDown(KeyCode.G))
        {
            InsertSortBinary(arr);
        } if (Input.GetKeyDown(KeyCode.H))
        {
            ShellSortHibbard(arr);
        }
    }
    /// <summary>
    /// 三种交换方式
    /// </summary>
    #region 三种交换方式
    // 方法一: 利用临时数tmp
    private void swap(int[] arr, int i, int j)
    {
        /*int tmp = arr[i];
        arr[i] = arr[j+1];
        arr[j+1] = tmp;*/

        int temp = arr[j];
        arr[j] = arr[j + 1];
        arr[j + 1] = temp;
    }
    // 方法二: 利用加减运算
    private void swapCal(int[] arr, int i, int j)
    {
        if (i == j) return; // 若无法保证swapCal被调用时满足 i != j,则需有此句,否则i == j时此数将变为0
        arr[i] = arr[i] + arr[j]; // a = a + b
        arr[j] = arr[i] - arr[j]; // b = a - b
        arr[i] = arr[i] - arr[j]; // a = a - b
    }
    // 方法三: 利用异或运算
    private void swapXOR(int[] arr, int i, int j)
    {
        if (i == j) return; // 若无法保证swapXOR被调用时满足 i != j,则需有此句,否则i == j时此数将变为0
        arr[i] = arr[i] ^ arr[j]; // a = a ^ b,也可写成 arr[i] ^= arr[j];
        arr[j] = arr[i] ^ arr[j]; // b = (a ^ b) ^ b = a ^ (b ^ b) = a ^ 0 = a, 也可写成 arr[j] ^= arr[i];
        arr[i] = arr[i] ^ arr[j]; // a = (a ^ b) ^ a = (a ^ a) ^ b = 0 ^ b = b, 也可写成 arr[i] ^= arr[j];
    }
    #endregion

    /// <summary>
    /// 算法
    /// </summary>
    #region 冒泡排序
    public void BubbleSort()
    {
        for (int i = 0; i < arr.Length - 1; i++)
        {
            for (int j = 0; j < arr.Length - i - 1; j++)
            {
                if (arr[j] > arr[j + 1])
                {
                    /*int temp = arr[j];
                    arr[j] = arr[j + 1];
                    arr[j + 1] = temp;*/
                    swap(arr, i, j);
                }
            }
        }
    }
    #endregion

    #region 选择排序
    public void SelectionSort()
    {
        for (int i = 0; i < arr.Length; i++)
        {
            int minIndex = i;
            int min = arr[i];
            for (int j = i + 1; j < arr.Length; j++)
            {
                if (arr[j] < min)
                {
                    min = arr[j];
                    minIndex = j;
                }
            }
            arr[minIndex] = arr[i];
            arr[i] = min;
        }
    }
    #endregion

    #region 插入排序
    //简单插入排序 内层用 for
    public void InsertionSortFor()
    {
        if (arr.Length < 2)
        {
            return;
        }
        for (int i = 1; i < arr.Length; i++)
        {
            int target = arr[i], j;
            for (j = i - 1; j >= 0; j--)
            {
                if (target < arr[j])
                    arr[j + 1] = arr[j];
                else break;
            }
            arr[j + 1] = target;
        }
    }
    //简单插入排序 内层用 while
    public void InsertionSortWhile()
    {
        if (arr.Length < 2)
        {
            return;
        }
        for (int i = 1; i < arr.Length; i++)
        { // N-1轮次执行
            int target = arr[i], j = i - 1;
            while (j >= 0 && target < arr[j])
            {
                arr[j + 1] = arr[j];
                j--;
            }
            arr[j + 1] = target; // 若发生移动,此时的插入对象数字≥j位置的数字,故插入位置为j + 1,若未移动也成立,无需判断
        }
    }
    //折半插入排序
    private int BinarySearch(int[] arr, int l, int r, int target)
    {
        while (l <= r)
        {
            int c = l + (r - l) / 2;
            if (arr[c] <= target) l = c + 1;
            else r = c - 1;
        }
        return l;
    }
    public int[] InsertSortBinary(int[] arr)
    {
        if (arr.Length < 2) return arr;
        // n - 1 轮次执行
        for (int i = 1; i < arr.Length; i++)
        {
            // 通过二分查找得到插入位置
            int target = arr[i];
            int pos = BinarySearch(arr, 0, i - 1, target);
            for (int j = i; j > pos; j--)
            { // 移动
                arr[j] = arr[j - 1];
            }
            arr[pos] = target; // 插入
        }
        return arr;
    }
    #endregion

    #region 希尔排序 (增量递减排序)
    //Shell增量  采用Shell增量 N / 2^k
    public int[] ShellSortShell(int[] arr)
    {
        if (arr.Length < 2) return arr;
        int n = arr.Length;
        for (int gap = n / 2; gap > 0; gap /= 2)
        { // gap 初始为 n/2,缩小gap直到1
            for (int start = 0; start < gap; start++)
            { // 步长增量是gap,当前增量下需要对gap组序列进行简单插入排序
                for (int i = start + gap; i < n; i += gap)
                { // 此for及下一个for对当前增量序列执行简单插入排序
                    int target = arr[i], j = i - gap;
                    for (; j >= 0; j -= gap)
                    {
                        if (target < arr[j]) arr[j + gap] = arr[j];
                        else break;
                    }
                    arr[j + gap] = target;
                }
            }
        }
        return arr;
    }

    //Hibbard增量  
    // 希尔排序: 采用Hibbard增量 {1, 3, 7, 15,...}
    public int[] ShellSortHibbard(int[] arr)
    {
        if (arr.Length < 2) return arr;
        int n = arr.Length, gap = 1;
        while (gap < n / 2) gap = gap * 2 + 1; // 初始化gap (Hibbard增量序列)
        for (; gap > 0; gap /= 2)
        { // 缩小gap直到1
            for (int start = 0; start < gap; start++)
            { // 步长增量是gap,当前增量下需要对gap组序列进行简单插入排序
                for (int i = start + gap; i < arr.Length; i += gap)
                { // 此for及下一个for对当前增量序列执行简单插入排序
                    int target = arr[i], j = i - gap;
                    for (; j >= 0; j -= gap)
                    {
                        if (target < arr[j]) arr[j + gap] = arr[j];
                        else break;
                    }
                    arr[j + gap] = target;
                }
            }
        }
        return arr;
    }

    //Knuth 增量
    public int[] ShellSortKnuth(int[] arr)
    {
        if (arr.Length < 2) return arr;
        int n = arr.Length, gap = 1;
        while (gap < n / 3) gap = gap * 3 + 1;//初始化gap(Knuth增量序列)
        for (; gap > 0; gap /= 3)
        {
            //缩小gap到1
            for (int start = 0; start < gap; start++)
            {
                //步长增量是gap,当前增量下需要对gap组序列进行简单插入排序
                for (int i = start + gap; i < arr.Length; i += gap)
                {
                    //此for及下一个for对当前增量序列执行简单插入排序
                    int target = arr[i], j = i - gap;
                    for (; j >= 0; j -= gap)
                    {
                        if (target < arr[j]) arr[j + gap] = arr[j];
                        else break;
                    }
                    arr[j + gap] = target;
                }
            }
        }
        return arr;
    }

    //Sedgewick增量
    /*public int[] shellSortSedgewick(int[] arr)
    {
        if (arr.Length < 2) return arr;
        int n = arr.Length, gap = 1;
        List<Integer> gaps = new ArrayList<>();
        gaps.add(gap);
        for (int k = 1; gap < n; k++)
        { // 计算增量序列
            gap = (int)(Math.pow(4, k) + 3 * Math.pow(2, k - 1) + 1);
            gaps.add(gap);
        }
        for (int idx = gaps.size() - 1; idx >= 0; --idx)
        { // 缩小 gap 直到 1
            gap = gaps.get(idx);
            for (int start = 0; start < gap; start++)
            { // 步长增量是 gap ,当前增量下需要对 gap 组序列进行简单插入排序
                for (int i = start + gap; i < n; i += gap)
                { // 此 for 及下一个 for 对当前增量序列执行简单插入排序
                    int target = arr[i], j = i - gap;
                    for (; j >= 0; j -= gap)
                    {
                        if (target < arr[j]) arr[j + gap] = arr[j];
                        else break;
                    }
                    arr[j + gap] = target;
                }
            }
        }
        return arr;
    }*/
    #endregion

    #region 归并排序

    #region 自顶向下 非原地归并
    public int[] Mergesort(int[] arr)
    {
        if (arr.Length < 2) return arr;
        int[] tmpArr = new int[arr.Length];
        Mergesort1(arr, tmpArr, 0, arr.Length - 1);
        return arr;
    }
    //递归方法
    private void Mergesort1(int[] arr, int[] tmpArr,int l,int r)
    {
        if (l < r)
        {
            int c = l + (r - 1) / 2;
            Mergesort1(arr, tmpArr, l, c);
            Mergesort1(arr, tmpArr, c + 1, r);

            Merge(arr, tmpArr, l, c, r);
        }
    }
    //非原地合并方法
    private void Merge(int[] arr, int[] tmpArr, int l, int c, int r)
    {
        // lh: left head, rh: right head, h: tmpArr head
        int lh = l, rh = c + 1, h = l; 
        while (lh <= c && rh <= r)
        {
            tmpArr[h++] = arr[lh] <= arr[rh] ? arr[lh++] : arr[rh++];
        }
        while (lh <= c) tmpArr[h++] = arr[lh++]; // 左半边还有剩余,加入 tmpArr 末尾
        while (rh <= r) tmpArr[h++] = arr[rh++]; // 右半边还有剩余,加入 tmpArr 末尾
        for (; l <= r; l++) arr[l] = tmpArr[l]; // 将 tmpArr 拷回 arr 中
    }
    #endregion 自顶向下 原地归并

    #region

    #endregion

    #endregion

    #region 快速排序

    #endregion
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
C# 中常用的排序算法有以下几种: 1. 冒泡排序 冒泡排序是一种简单的排序算法,每次比较相邻两个元素的大小并交换位置,重复进行直到数组有序。具体实现如下: ```csharp public static void BubbleSort(int[] arr) { int n = arr.Length; for (int i = 0; i < n - 1; i++) { for (int j = 0; j < n - i - 1; j++) { if (arr[j] > arr[j + 1]) { int temp = arr[j]; arr[j] = arr[j + 1]; arr[j + 1] = temp; } } } } ``` 2. 插入排序 插入排序是一种简单且有效的排序算法,将未排序的元素依次插入到已排序的序列中,直到所有元素都有序。具体实现如下: ```csharp public static void InsertionSort(int[] arr) { int n = arr.Length; for (int i = 1; i < n; i++) { int key = arr[i]; int j = i - 1; while (j >= 0 && arr[j] > key) { arr[j + 1] = arr[j]; j--; } arr[j + 1] = key; } } ``` 3. 选择排序 选择排序是一种简单的排序算法,每次选择数组中最小的元素并将其放到已排序的序列的末尾,直到所有元素都有序。具体实现如下: ```csharp public static void SelectionSort(int[] arr) { int n = arr.Length; for (int i = 0; i < n - 1; i++) { int minIndex = i; for (int j = i + 1; j < n; j++) { if (arr[j] < arr[minIndex]) { minIndex = j; } } int temp = arr[minIndex]; arr[minIndex] = arr[i]; arr[i] = temp; } } ``` 4. 快速排序 快速排序是一种高效的排序算法,它使用分治的思想将数组分成两个子数组,然后递归地对这两个子数组进行排序,最后合并两个有序数组。具体实现如下: ```csharp public static void QuickSort(int[] arr, int left, int right) { if (left < right) { int pivotIndex = Partition(arr, left, right); QuickSort(arr, left, pivotIndex - 1); QuickSort(arr, pivotIndex + 1, right); } } private static int Partition(int[] arr, int left, int right) { int pivot = arr[right]; int i = left - 1; for (int j = left; j < right; j++) { if (arr[j] < pivot) { i++; int temp = arr[i]; arr[i] = arr[j]; arr[j] = temp; } } int temp1 = arr[i + 1]; arr[i + 1] = arr[right]; arr[right] = temp1; return i + 1; } ```

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值