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
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值