各种算法总结二

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

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

 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;
        }

 

posted @ 2016-12-21 15:39  咕-咚  阅读(127)  评论(0)    收藏  举报