这可能是我见过最详细的选择排序!

关于选择排序,网上,和维基都有完成的解释,他们都是。。。。。。,俺觉得都是,太过于总结话语在概述一些东西;

而我却从最本质的东西,一步一步的深入;在深入的学习过程中,我得到如下非代码层面上的感悟;

1.一个完整的模式(代码或者其他东西)都是通过没有=>part0=>part1=>part2>version0=>viersion1.......versionN=>perfect  最后达到一个完成的形式;

如果你只是去学习和体会最后的那一个完成的版本,而没有经历整个探索的过程,你的体会也不会太多;

2.有时候要学会抽象化和跳跃化的去思考问题,而不是step by step(这有点不具体,下次我结合具体的实例来解释)

3.帮助别人解决问题;并不是直接给出问题的答案或者结果;而是给别人一些引导和资源,让他自己去解决;(这点来自使用stackoverflow提问的感受)

好了,废话不多了;直接从代码开始;开始之前,想尝试做下面的practice;

1.选择数组的第一个data(target)将数组分成两部分;满足:   minArr<target<=maxArr;

2.选择数组的第一个data(target)将数组分成两部分;满足:   minArr<target<=maxArr; 并将target 放入数组“中间位置“;满足:  target greater than left data and less than right data;

3.找出value 在有序数组中的位置;

4.找出value 在无序数组中的位置;这个位置应该满足,它在有序数组中应该具有的位置;greater than left data and less than right data;

5.在不开辟内存的情况下(使用新的数组来存储值)完成问题2;

6.关于递归的学习和使用(具体看这篇文章的后半部分:http://www.cnblogs.com/mc67/p/5114008.html)

7.三种方式来实现我们的额快速排序;(本质的区别只有两种)

关于前面的 5个问题,我就直接上代码;你细细品味(建议在没有看代码前,完成上面的问题)

 /// <summary>
        /// 最基本的;将数组分成两部分;一部分比target小,一部分比target大;
        /// </summary>
        /// <param name="arr"></param>
        static void SplitArray(int[] arr)
        {
            int len = arr.Length;
            int target = arr[0];
            List<int> min = new List<int>(len); //为了方便,这里我使用List
            List<int> max = new List<int>(len); //为了方便,这里我使用List
            for (int i = 1; i < len; i++) //从第二个元素开始查找;
            {
                if (arr[i] < target)
                {
                    min.Add(arr[i]);
                }
                else
                {
                    max.Add(arr[i]);  // as euqual condition,I put it into max;
                }
            }

        }
        /// <summary>
        /// split the arr and put the target in the right position(greater than left ,less than right)
        /// </summary>
        /// <param name="arr"></param>
        static void SplitArray1(int[] arr)
        {
            int len = arr.Length;
            int target = arr[0];
            List<int> min = new List<int>(len); //为了方便,这里我使用List
            List<int> max = new List<int>(len); //为了方便,这里我使用List
            for (int i = 1; i < len; i++) //从第二个元素开始查找;
            {
                if (arr[i] < target)
                {
                    min.Add(arr[i]);
                }
            }
            //put it in the last of min, that can make sure target greater than min(left)
            min.Add(target);
            for (int i = 1; i < len; i++) //从第二个元素开始查找;
            {
                if (arr[i] > target)
                {
                    max.Add(arr[i]);
                }
            }

            min.AddRange(max); //that can make sure  min<target<max
        }

        /// <summary>
        /// optimze the SplitArray1
        /// 上面的代码,还是有问题的,如果有重复的值,那么,将在判断max的时候丢掉;
        /// 那么问题来了,如果相等的如何判断呢;
        /// </summary>
        /// <param name="arr"></param>
        static void SplitArray2(int[] arr)
        {
            int len = arr.Length;
            int target = arr[0];
            List<int> min = new List<int>(len); //为了方便,这里我使用List
            List<int> max = new List<int>(len); //为了方便,这里我使用List
            for (int i = 1; i < len; i++) //从第二个元素开始查找;
            {
                if (arr[i] < target)
                {
                    min.Add(arr[i]);
                }
            }
            //put it in the last of min, that can make sure target greater than min(left)
            min.Add(target);
            for (int i = 1; i < len; i++) //从第二个元素开始查找;
            {
                if (arr[i] >= target) //我们把等于符号加上,就解决问了???? 对于本例子,是从arr[0] 开始的;//那如果是从别的位置开始呢;
                {
                    max.Add(arr[i]);
                }
            }

        }

        /// <summary>
        /// start from random index;
        /// </summary>
        /// <param name="arr"></param>
        static void SplitArray3(int[] arr)
        {
            int len = arr.Length;
            int randomIndex = 2;
            int target = arr[randomIndex]; //假设,我们从index=2 开始,这里,我们肯定满足arr.length>=2;

            List<int> min = new List<int>(len); //为了方便,这里我使用List
            List<int> max = new List<int>(len); //为了方便,这里我使用List
            for (int i = 0; i < len; i++) //这里,我们就要从0 开始了,遍历整个数组;
            {
                if (arr[i] < target)
                {
                    min.Add(arr[i]);
                }
            }
            min.Add(target);
            for (int i = 0; i < len; i++) //这里,我们就要从0 开始了,遍历整个数组;
            {
                if (arr[i] >= target && i != randomIndex) //加上这个条件,我们就可以过滤到我们的 randomIndex 避免重复添加的问题;
                {
                    max.Add(arr[i]);
                }
            }

            //最后,我们的数组,就是符合我们要求的数组;
        }

        //上面的做法;可以满足  min<target<=max
        /// <summary>
        /// 我们来找出元素所在的位置 index 首先是我们的有序数组中
        /// 通过值相等来进行判断的话,可以满足;
        /// 不管值有序 还是 无序的值;
        /// </summary>
        static void FindIndex(int[] arr, int value)
        {

            int len = arr.Length;
            int index = -1;
            for (int i = 0; i < len; i++)
            {
                if (arr[i] == value)
                {
                    index = i;
                    break;
                }
            }
        }

        /// <summary>
        /// 两种思维方式,
        /// 两种思维方式;第二种,更接近普通人的表达方式;
        /// </summary>
        /// <param name="arr"></param>
        /// <param name="value"></param>
        static void FindIndex1(int[] arr, int value)
        {

            int len = arr.Length;
            int index;
            bool isExist = false;
            for (int i = 0; i < len; i++)
            {
                if (arr[i] == value)
                {
                    index = i;
                    isExist = true;
                    break;
                }
            }
            if (isExist == false) { index = 1; }
        }

        /// <summary>
        /// 上面的方法是找到,value,在数组中的第一个index 值; 不管它是否有序;
        /// 现在我们要找一个元素,在有序列表中的(应该插入的值,但是我们不插入)
        /// </summary>
        static void FindIndex2(int[] arr, int value)
        {

            int len = arr.Length;
            int index = -1;
            for (int i = 0; i < len; i++)
            {
                //你可以这么想;
                //如果找到大于大的数就停止;否则就继续
                if (arr[i] >= value)  //考虑到取等情况;
                {
                    index = i; //这个时候,我们的数据,就可以插入在改元素的的后面;
                    index = index - 1;  //这样就返回了可以直接插入的位置;
                    //并且停止我们的循环;
                    break;    //前提是有序的数组列表中
                }
            }

            //在插入的时候,就必须把后面的元素往后面挪动;
            //插入的时候,
        }

        /// <summary>
        /// 上面的方法是找到,value,在数组中的第一个index 值; 不管它是否有序;
        /// 现在我们要找一个元素,在有序列表中的(应该插入的值,但是我们不插入)
        ///  2 和 3 两种不同的想法,写出来的code 就不太一样;
        /// </summary>
        static void FindIndex3(int[] arr, int value)
        {

            int len = arr.Length;
            int index = -1;
            for (int i = 0; i < len; i++)
            {
                //我们可以可以这么想;
                if (arr[i] <= value)
                {
                    index++;  //小于它的值,我们的index 就 keep move forward;  还没考虑,我们取等的情况滴呀;
                }
                else
                {
                    //遇到,不满足的情况,我们就退出
                    //原本的我们的index 是落后于我们的i,出去的时候;再加一次,
                    index++;
                    break;
                }
            }

            //这样就找到了我们的index;在一个可以插入的位置;
        }

        /// <summary>
        /// 先这样来想,找出小于 value的count,那么value在的位置应该就是在我们的count+1;
        /// </summary>
        /// <param name="arr"></param>
        /// <param name="value"></param>
        static void FindCountLessThan(int[] arr, int value)
        {
            int len = arr.Length;
            int count = 0;
            for (int i = 0; i < len; i++)
            {
                if (arr[i] <= value)
                {
                    count++;
                }
            }

            //这样,我们就能够找出小于count的数量;那么 我们value所在的位置就是我们count+1
        }

        /// <summary>
        /// 关键的来了:找到value 应该在的位置;在一个无序的数组中;
        /// </summary>
        /// <param name="arr"></param>
        /// <param name="value"></param>
        static void FindIndexInUnSortArr(int[] arr, int value)
        {
            int len = arr.Length;
            int rightPosition = 0;  //初始化,默认我们的指针在0位置;
            for (int i = 0; i < len; i++)
            {
                //通过遍历来查找;
                if (arr[i] <= value)
                {
                    rightPosition++;
                }
            }
        }

        /// <summary>
        /// 找到index在的位置,并将小于value的数据放在左边,大于value的数据放在右边
        /// </summary>
        /// <param name="arr"></param>
        /// <param name="value"></param>
        static void FindeAndSwap(int[] arr)
        {

            int len = arr.Length;
            int middleIndex = 1;
            int value = arr[0];//target;

            // i 能找到一个小于value的值;
            //middleIndex 始终指向一个大于或等于 value的值;
            for (int i = 1; i < len; i++)
            {
                if (arr[i] <= value) //当找到一个小于value的值之后,进行交换,和那个值进行交换呢;(原则:小的值移动到左边,大的值移动到右边;)
                {                    //现在,我们找到了小的值,那么大的值呢;????
                    if (i == middleIndex)
                    {
                        //不进行交换; keep move
                    }
                    else
                    {
                        Swap(arr, middleIndex, i);
                    }
                    middleIndex++;
                }
            }

            //最后出来后,我们要将第一个元素和中间的元素进行交换,也就是讲value放在middle的位置;
            Swap(arr, 0, middleIndex - 1);
        }

        /// <summary>
        ///  上面的代码,基本上已经满足了我们额基本要求;
        ///  完美的代码,解决了这个问题;
        /// </summary>
        /// <param name="arr"></param>
        static int FindeAndSwap1(int[] arr, int start, int end)
        {
            int middlePosition = start + 1;
            int pivot = arr[start];

            for (int i = start + 1; i <= end; i++)
            {

                if (arr[i] <= pivot)
                {
                    if (i == middlePosition)
                    {
                        //there is need to swap
                    }
                    else
                    {
                        Swap(arr, middlePosition, i);
                    }
                    middlePosition++;
                }

            }
            //put the arr[start] in "middle position"(greater than left,less than right)
            int position = middlePosition - 1;
            Swap(arr, arr[start], position);
            return position;
        }

        /// <summary>
        /// 同样,我们又第二种方式来实现,
        /// </summary>
        /// <param name="arr"></param>
        /// <param name="low"></param>
        /// <param name="high"></param>
        static void FindeAndSwap2(int[] arr, int low,int high)
        {

            int l = low-1;  //make sure pointer move firstly (before take value from arr to compare with pviot)
            int h = high+1; //make sure pointer move firstly (before take value from arr to compare with pviot)
            int pviot = arr[low];
            while (l<h)
            {
                while (arr[--h]> pviot) //find some value less than pvoit
                {

                }
                while (arr[++l] <= pviot) //find some value greater than pvoit   we use <= instead of <;beacause we don‘t let arr[start] swap
                {

                }
                if (l < h)
                {
                  Swap(arr, h, l);  //swap
                }
            }
            Swap(arr, low, h);    //put the povit in the "middle" Position

        }

        /// <summary>
        /// 同样,我们也有第三种写法;
        /// </summary>
        /// <param name="arr"></param>
        /// <param name="low"></param>
        /// <param name="high"></param>
        static int FindeAndSwap3(int[] arr, int low, int high)
        {
            int l = low;
            int h = high;
            int pviot = arr[low];

            while (l < h)
            {
                while (arr[h] >= pviot) //chose >= instead of >; beca if the first value arr[h] equal  pviot ,this will enter endless loop;(don‘t enter {} do h--;)
                {
                    h--;
                }
                while (arr[l] <= pviot)  //we chose <= instead of < to make sure pviot don‘t take part in swap, we will swap in the last step with "middle" position
                {
                    l++;
                }
                if (l >= h)
                    break;
                Swap(arr,l,h);
            }
            int middlePosition = h;
            Swap(arr,low, middlePosition);
            return middlePosition;
        }

        /// <summary>
        /// 当然,就有了,我们的第四种方法;
        /// 你会发现,前面的方法都是,先找到一个小于的index  high 然后找到一个大于的index low
        /// 然后进行交换;
        /// 然后有没有其他的方式呢?
        /// 答案是有的;
        /// 而且,你会发现,我们的额pvoit 是没有参与swap的,直到我们的最后一步,然后将起放在 middle position(这一步,是不可避免滴呀)
        /// </summary>
        /// <param name="arr"></param>
        /// <param name="low"></param>
        /// <param name="high"></param>
        /// <returns></returns>
        static int FindeAndSwap4(int[] arr, int low, int high)
        {
            int pviot = arr[low];

            while (low < high)
            {
                while(arr[high]>=pviot && low < high)
                {
                    high--;
                }
                //一旦,找到了,我们就替换;
                arr[low] = arr[high];  //这样,会覆盖我们的第一个值,不过,在最后,我们会将第一个值,放在“中间”位置;
                while (arr[low] <= pviot && low < high)
                {
                    low++;
                } //这样做的话,在没有,进行到最后一步,数组中会有一个重复的值,不过,我们最后将被我们pviot
                arr[high] = arr[low];
            }
            arr[low] = pviot;
            return high;
        }

        //到了这一步,我们的基本核心的单元,算是基本基本完整了;
        //然后,我们这里,再实现,三个版本的快速排序;方法;

        /// <summary>
        /// 交换
        /// </summary>
        /// <param name="arr"></param>
        /// <param name="i"></param>
        /// <param name="j"></param>
        static void Swap(int[] arr, int i, int j)
        {
            int temp = arr[i];
            arr[i] = arr[j];
            arr[j] = temp;
        }

然后是快速排序的第一种实现方式:

然后是快速排序的第二种实现方式:

原文地址:https://www.cnblogs.com/mc67/p/8259734.html

时间: 2024-10-29 14:30:17

这可能是我见过最详细的选择排序!的相关文章

数据结构 - 只需选择排序(simple selection sort) 详细说明 和 代码(C++)

数据结构 - 只需选择排序(simple selection sort) 本文地址: http://blog.csdn.net/caroline_wendy/article/details/28601965 选择排序(selection sort) : 每一趟在n-i+1个记录中选取keyword最小的记录作为有序序列中第i个记录. 简单选择排序(simple selection sort) : 通过n-i次keyword之间的比較, 从n-i+1个记录中选出keyword最小的记录, 并和第i

超级详细解读基本排序算法(不看后悔)

排序与我们日常生活中息息相关,比如,我们要从电话簿中找到某个联系人首先会按照姓氏排序.买火车票会按照出发时间或者时长排序.买东西会按照销量或者好评度排序.查找文件会按照修改时间排序等等.在计算机程序设计中,排序和查找也是最基本的算法,很多其他的算法都是以排序算法为基础,在一般的数据处理或分析中,通常第一步就是进行排序,比如说二分查找,首先要对数据进行排序.在Donald Knuth 的计算机程序设计的艺术这四卷书中,有一卷是专门介绍排序和查找的. 排序的算法有很多,在维基百科上有这么一个分类,另

vim插件详细安装过程

1 写在前面   Linux下编程一直被诟病的一点是: 没有一个好用的IDE, 但是听说Linux牛人, 黑客之类的也都不用IDE. 但是对我等从Windows平台转移过来的Coder来说, 一个好用的IDE是何等的重要啊, 估计很多人就是卡在这个门槛上了, "工欲善其事, 必先利其器"嘛, 我想如果有一个很好用的IDE, 那些Linux牛人也会欢迎的. 这都是劳动人民的美好愿望罢了, 我今天教大家把gvim改装成一个简易IDE, 说它"简易"是界面上看起来&quo

jqGrid属性中文详细说明

jqGrid属性中文详细说明 jqGrid的属性很多,其实很大部分的属性,使用其默认值就可以了.但是详细了解一下属性的含义以及作用,对我们定制自己的grid是有帮助的. 以下内容描述格式是:属性名称 参数值类型    描述内容(可能有多行)    默认值    是否可修改(表示grid创建完成之后,该属性是否能够被修改.也就是说,是否grid的初始化的属性值能够被修改)————详细属性列表———— ajaxGridOptions object    本选项用来设置全局的Ajax设置.注意:这个选

vim配置及插件安装管理(超级详细)

vim配置及插件安装管理(超级详细) 分类: Linux 相关2012-07-26 09:34 97079人阅读 评论(18) 收藏 举报 vimsearchbuffertags浏览器microsoft 1 写在前面   Linux下编程一直被诟病的一点是: 没有一个好用的IDE, 但是听说Linux牛人, 黑客之类的也都不用IDE. 但是对我等从Windows平台转移过来的Coder来说, 一个好用的IDE是何等的重要啊, 估计很多人就是卡在这个门槛上了, "工欲善其事, 必先利其器"

vim配置及插件安装管理(超级详细)[转]

1 写在前面   Linux下编程一直被诟病的一点是: 没有一个好用的IDE, 但是听说Linux牛人, 黑客之类的也都不用IDE. 但是对我等从Windows平台转移过来的Coder来说, 一个好用的IDE是何等的重要啊, 估计很多人就是卡在这个门槛上了, "工欲善其事, 必先利其器"嘛, 我想如果有一个很好用的IDE, 那些Linux牛人也会欢迎的. 这都是劳动人民的美好愿望罢了, 我今天教大家把gvim改装成一个简易IDE, 说它"简易"是界面上看起来&quo

关闭iis 错误页面显示详细内容

关闭iis 错误页面显示详细内容,为安全起见,防止黑客通过iis错误信息获取有用信息,隐藏iis错误页面的详细形象 打开iis功能视图,打开 错误页点击编辑功能设置默认为 详细错误 选择自定义错误

序列(两)密钥索引、桶排序、位图、失败者树(照片详细解释--失败者树)

序列(两) 以上排序算法都有一个性质:在排序的终于结果中,各元素的次序依赖于它们之间的比較.我们把这类排序算法称为比較排序. 不论什么比較排序的时间复杂度的下界是nlgn. 下面排序算法是用运算而不是比較来确定排序顺序的.因此下界nlgn对它们是不适用的. 键索引计数法(计数排序) 计数排序如果n个输入元素中的每个都是在0到k区间的一个整数,当中k为某个整数. 思想:对每个输入元素x,确定小于x的元素个数.利用这一信息,就能够直接把x放到它在输出数组中的位置了. 比如: 学生被分为若干组,标号为

安全配置,关闭iis 错误页面显示详细内容

为web安全,防止黑客通过web错误页面信息获取有用信息,关闭iis 错误页面显示详细内容 1.打开iis功能视图,打开 错误页点击编辑功能设置默认为 详细错误选择自定义错误