c#排序算法

 /// <summary>
    /// 快速排序,如果你的key值取得是左边的第一个数,则先从右边开始挖坑,如果取得是右边的最后一个数,则从左边开始挖坑
    /// </summary>
    /// <param name="s"></param>
    /// <param name="l"></param>
    /// <param name="r"></param>
    void quick_sort(int [] s, int l, int r)
    {
        if (l < r)
        {
            //Swap(s[l], s[(l + r) / 2]); //将中间的这个数和第一个数交换 参见注1
            int low = l, High = r, x = s[r];
            while (low < High)
            {
                while (low < High && s[low] <= x) // 从左向右找第一个大于等于x的数
                    low++;
                if (low < High)
                    s[High--] = s[low];
                while (low < High && s[High] >= x) // 从右向左找第一个小于x的数
                    High--;
                if (low < High)
                    s[low++] = s[High];
            }
            s[low] = x;
            quick_sort(s, l, low - 1); // 递归调用 
            quick_sort(s, low + 1, r);
        }
    }
    int PartSort1(int[] arr, int left, int right)
    {
        int end = right;
        int begin = left;
        int key = arr[left];
        while (begin < end)
        {
            while (begin < end && arr[begin] <= key)
                begin++;
            while (begin < end && arr[end] >= key)
                end--;
            if (begin < end)
                Swap(arr [begin], arr[end]);
        }
        Swap(arr[begin], arr[right]);
        return begin;
    }

    /// <summary>
    /// 插入排序的思想就是,从右至左,比较一个数和它左边所有的数,如果遇到大于或者小于这个数的,就把他左边的数往左移或者往右移,最后把该数插入到结尾的位置,实现交换
    /// </summary>
    /// <param name="arry"></param>
    /// <param name="sortIndex"></param>
    public void InsertSort(int[] arry, int sortIndex)
    {
        if (arry.Length > 1)
        {
            int j = 0;

            for (int i = 1; i < sortIndex; i++)//从第二个数开始
            {
                int temp = arry[i];
                for (j = i - 1; j >= 0; j--)//依次比较这个数和它左边的数
                {
                    if (temp >= arry[j])//如果遇到比这个数小地数,则把这个数往后移一位,依次查询,直到最后一个或者是一个不小于这个数的数,因为插入排序要插入的数的左边都是已经排列好了的
                    {                   //大于等于是从大到小排列,小于等于是从小往大排列
                        arry[j + 1] = arry[j];//从这个小于的数开始,依次往后移
                    }
                    else
                        break;
                }
                arry[j + 1] = temp;//把要插入的值插入到移动完空缺的那个位置上
            }
        }
        foreach (var item in arry)
        {
            print(item);
        }
    }

    /// <summary>
    /// 二分法排序,不是二分法查找,思想是先跟据要排列的数的索引找到一个中间值,把这个值和中间值比较,直到找到低位大于高位的时候,把从低位开始或者高位开始的值,依次往左或者往右移动,最后把要排列的数插入到空缺的位置
    /// </summary>
    /// <param name="arry">插入排序是依次和它左边的值作比较,这个是依次和左边的中间值作比较,所以查找的次数要小于插入排序</param>
    /// <param name="size"></param>
    public void BinarySort(int[] arry, int size)
    {
        for (int i = 1; i < size; i++)
        {
            int low = 0;
            int high = i - 1;
            int mid;
            int j;
            int temp = arry[i];
            while (low <= high)//一直找到low>high的时候,这样
            {
                mid = (low + high) / 2;
                if (temp > arry[mid])//
                {
                    high = mid - 1;
                }
                else
                {
                    low = mid + 1;
                }
            }
            for (j = i - 1; j > high; j--)//这里大于high或者大于等于low都是一样的,因为他俩是相邻的
            {
                arry[j + 1] = arry[j];
            }
            arry[j + 1] = temp;
        }

        foreach (var item in arry)
        {
            print(item);
        }
    }
    /// <summary>
    /// 二分法查找,必须是有序数组,而且
    /// </summary>
    /// <param name="arry"></param>
    /// <param name="find"></param>
    /// <returns></returns>
    public int BinaryFind(int[] arry, int find)
    {
        int low = 0;
        int high = arry.Length;
        int mid = (low + high) / 2;
        while (low < high)
        {
            mid = (low + high) / 2;
            if (find > arry[mid])
            {
                low = mid + 1;
            }
            else if (find < arry[mid])
            {
                high = mid - 1;
            }
            else
            {
                return mid;
            }
        }
        return -1;
    }

    /// <summary>
    /// 乱序算法,思想:从数组里面随机取出一个数,和数组中的第一个数字交换位置,然后再从除了第一个数字之外随机取一个位置,和第二个数交换位置
    /// </summary>
    /// <param name="arry"></param>
    public void Disorder(int[] arry)
    {
        for (int i = 0; i < arry.Length; i++)
        {
            int temp = Random.Range(i, arry.Length);
            int tempIndex = arry[i];
            arry[i] = arry[temp];
            arry[temp] = tempIndex;
        }
        foreach (var item in arry)
        {
            Debug.Log(item);
        }
    }
/// <summary>
    /// 从数组里面找到一个最小的,和第一位交换位置,然后再从第二个数开始找到一个最小的,放在第二个位置,这个和洗牌算法差不多,只不过是洗牌是随机从里面找一个数,和第一位交换位置
    /// </summary>
    /// <param name="arry"></param>
    public void SecletSort(int[] arry)
    {
        for (int i = 0; i < arry.Length; i++)
        {
            int min = i;
            for (int j = i + 1; j < arry.Length; j++)
            {
                if (arry[j] < arry[min])
                {
                    min = j;
                }
            }
            Swap(arry[i], arry[min]);
        }
        DebugItem(arry);
    }
 public void DebugItem(int[] arry)
    {
        foreach (var item in arry)
        {
            Debug.Log(item);
        }
    }

    /// <summary>
    /// 交换两个数
    /// </summary>
    /// <param name="source"></param>
    /// <param name="des"></param>
    public void Swap(int source, int des)
    {
        source = source ^ des;
        des = source ^ des;
        source = source ^ des;//交换两个值,用异或的方法
    }

 

 求数组中第k大的值

利用快排算法,第一次排序,得到一个以key值为中间点,左右两边为小于和大于它的数,然后比较这个key值的索引和K的大小,因为第一次比较之后,key值所在的位置就是第key所在索引大的位置,因为数组是从0开始的,第五大也就是索引为index+1,比如key的索引为3,那它是第3+1=4大的值,如果k>index+1,说明,在key值的右边,则重新对右边进行一次快速排序,得到一个key值所在的索引,继续比较,如果k<index+1,说明K在key值得左边,则重新在左边进行快速排序,直到得到key和index+1相等,返回当前index得值

static int RandPartition(int[] arr, int left, int right) {
 2             Random rd = new Random();
 3             int p = rd.Next(left, right + 1);//随机得到一个key值,增强基值得选择性,避免单一key值,在已经排好序得情况下得浪费比较时间
 4             Swap(ref arr[p], ref arr[left]);//转换成左边值,虽然key值是随机的,但有转换成了和不随机得处理方法
 5             int temp = arr[left];
 6             while (left < right) {
 7                 while (left < right && arr[right] > temp) { right--; count++; }
 8                 arr[left] = arr[right];
 9                 while (left < right && arr[left] <= temp) { left++; count++; }
10                 arr[right] = arr[left];
11             }
12             arr[left] = temp;
13             return left;
14         }
15 
16         static int RandSelect(int[] arr, int left, int right, int k) {
17             if (left == right) {
18                 return arr[left];//如果到最后数组就剩一个数了,说明这个是就是
19             }
20             int index = RandPartition(arr, left, right);
21             int M = index + 1;
22             if (M == k) {
23                 return arr[index];
24             }
25             int result = -1;
26             if (M < k) {
27                 result = RandSelect(arr, index + 1, right, k);
28             }
29             else if (M > k) {
30                 result = RandSelect(arr, left, index - 1, k);
31             }
32             return result;
33         }

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

TO_ZRG

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值