• 各种算法总结二


      今天继续我们的快速排序算法 

      哎,网上大多数的讲解基本上都是你抄我,我抄你的,没有一个完整有道理的讲解滴呀;今天让哥来给你讲个明白;

     ps:如果你对快速排序一点都不了解,那么。。你还是先不要看了,先去看看其他人的........(-_-)

     核心:“找到元素本应该所在的位置”- 任何一个排好顺序的数组中的任何一个数字(x)都应该有这样的规律:x它大于任何一个左边的数,小于任何一个任何一个右边的数,(ps,我这里说的是从小到大的顺序)   

       乱顺实例:              2 5 1 3 8 

       那么本应该的顺序是:1 2 3 5 8,哎,顺便吐槽一哈,网上的答案真的是前篇一律,都没有一个有自己见解的,我艹;然后,参见红色字体的内容;

       在我们的乱序中,我们先找到2 应该锁在的位置: 也就是数组下标1,

       先从右边找,找到第一个比x小的数,然后

       这样在第一次循环号,我们的额乱序数组,就被分成了左右连个区域的呀,然后接着调用递归分区最最大值的结果滴呀;

        代码:

        一些较为有用额注释:

    //再一次的总结我们的各种基本额选择排序算法;
    //今天继续我们的各种算法滴呀;
    //其中一部分的数据比另外一部的数据小弟呀;
    //强烈建议,在比较的时候,不要使用的left 和right 两个变量;
    //用low 和ghi 比较合适,这样不用弄晕滴呀;
    //不用的比喻方式,有的人叫他填坑方法,有的人的叫它归为方法
    //去找到属于它的位置;
    //它只是在描述过程,并没有清楚的讲述清楚原理滴哎呀;
    //找到基准数,本应该锁锁在的位置 这个正确的说法,叫做找到数据本应该说在的位置;

     public static int GetSupposedPosition(int [] s, int l, int r) //返回调整后基准数的位置  
            {
                int i = l, j = r;
                int x = s[l]; //s[l]即s[i]就是第一个坑  
                while (i < j)
                {
                    // 从右向左找小于x的数来填s[i]  
                    while (i < j && s[j] >= x)
                        j--;
                    if (i < j)
                    {
                        s[i] = s[j]; //将s[j]填到s[i]中,s[j]就形成了一个新的坑  
                        i++;
                    }
    
                    // 从左向右找大于或等于x的数来填s[j]  
                    while (i < j && s[i] < x)
                        i++;
                    if (i < j)
                    {
                        s[j] = s[i]; //将s[i]填到s[j]中,s[i]就形成了一个新的坑  
                        j--;
                    }
                }
                //退出时,i等于j。将x填到这个坑中。  
                s[i] = x;
    
                return i; //这样就找到了我们s[i]所在的位置;
            }

    最后上我们完整的代码;

            public static void FuckQuickSort(int [] arr,int l,int r)
            {
                if (l < r)
                {
                    int i = l, j = r,x = arr[l];
                    while (i < j)
                    {
                        while(i<j && arr[j] >= x)
                        {
                            j--; //这个就是继续寻找的意思滴呀;,比我们基准数大的,我们就不动它
                        }
                        if (i < j)
                        {
                            arr[i] = arr[j];
                            i++;
                        }
                       while(i<j && arr[i] < x)
                        {
                            i++; //比我们基准数小的,我们就不动它,让它留在原地;
                        }
                        if (i < j)
                        {
                            arr[j] = arr[i];
                            j--;
                        }
                    }//当退出循环的时候;
                    arr[i] = x;               //第一次排序,就是为了找这个中间值,比中间值大的都在我们的额右边,比中间值小的数据都在我们左边;
                                              //然后再利用我们的递归,分别对左右两边的额数据,进行各种排序滴呀;
                                              //这样额效果还是不错滴呀;
                    FuckQuickSort(arr,l,i-1); //右边的
                    FuckQuickSort(arr,l+1,r); //左边的
                }
            }

    效果是很不错的滴呀;

    然后就是我们快速排序到的各种优化滴呀; 

    方式一: 

            //不管选择哪个方向,都要把我们的基本的算法搞好滴呀;
            //继续我们的 快速排序的各种优化;
            //算法若都能分成两个等长的子序列时,那么分治算法效率会达到最大
            //最理想的方法是,选择的基准恰好能把待排序序列分成两个等长的子序列 
            public static void QsortCommon(int [] arr,int low,int high)
            {
                if (low >= high) return; //递归的出口;
                int index = Partition(arr,low,high);
                QsortCommon(arr,low,index-1); //右边进行排序
                QsortCommon(arr,index+1,high);//左边的进行排序;
            }
    
            public static int Partition(int [] arr,int low,int high)
            {
                int first = low;
                int last = high;
                int key = arr[first];//选择我们的第一个元素最为我们的基准元素滴啊;
                while (first < last)
                {
                     while(first<last && arr[last] >= key)
                    {
                        last--;
                    }
                    //找到小于基准数的值;并且移动到左边
                    arr[first] = arr[last];
                    while(first<last && arr[first] <= key)
                    {
                        first++;
                    }
                    //找到比基准值大的数据,并将其移动到我们的 右边;
                    arr[last] = arr[first];
                }
                //最后得到分区效果,也就是找到我们的基准数,本来应该所在的位置;
                arr[last] = key;
                return last;//返回基准值所在下标;
            }

    选取数组中的任意元素进行:

    //思想:取待排序列中任意一个元素作为基准元。
            //随机基准元素,将确定好的基准元素与第一个元素讲好;//无返回值;
            public static void PartitionRandom(int [] arr,int low,int high)
            {
                Random rd = new Random();
                int randomIndex = rd.Next()%(high-low)+low; //数组中的随机一个数据 与我们的基准数进行交换;
                int temp = arr[0];
                arr[0] = arr[randomIndex];
                arr[randomIndex] = temp;
            }
  • 相关阅读:
    在第一段ionic示例的基础上增加底部导航
    我的第一段ionic代码
    angularjs中ng-repeat的使用
    angular中$location读取url信息
    解决jenkins构建job报错“NoClassDefFoundError” in jenkins/scm/RunWithSCM问题
    完全卸载删除gitlab
    centos7端口永久开放方法
    eclipse解决maven编码UTF-8的不可映射字符
    Apache JMeter压力测试实例
    windows下安装setuptools与pip
  • 原文地址:https://www.cnblogs.com/mc67/p/6207941.html
Copyright © 2020-2023  润新知