最近看了一句话,说的是在现实生活中,会写字的人不见得会写出好文章,学习编程语言就像是学会了写字,学会了编程语言并不一定能写出好程序。

我觉得就是很有道理,以前读书的时候,基本学完了C#中的语法知识,算是入了个门,但是一到写程序就毫无头绪,做出来的程序就像是小学生日记,仅仅只是用一些简单的api把功能拼凑起来,没有一点逻辑性,毫不美观优雅。

所以我决定慢慢的开始学习算法知识,虽然我数学很烂,逻辑能力差到极点,看这些算法的代码看的我是心态爆炸,真的头皮发麻,只有长期坚持学习,一点一点的慢慢进步了。

快速排序是分治法中的一种常见排序算法,主要运用递归求解。

算法思想是将一个数组分为小于等于基准数的子数组和大于基准数的子数组,然后通过递归调用,不断对这两个子数组进行排序,直到数组元素只有0个或1个元素时,停止递归,再将各个排好序的子数组加起来,最终就得到了排好序的数组。

步骤如下:

1. 选择一个基准值

2. 将数组分为两个子数组:小于基准值的元素和大于基准值的元素

3. 对这两个子数组进行排序

接着对子数组重复以上3步,直到子数组无法分解(子数组只有0个或1个元素时)

可以使用函数递归重复上述过程,在递归函数中必须满足2个条件

1.基线条件——指满足某个条件以后,函数不在调用自身进行递归

2.递归条件——满足递归条件就调用自身函数进行递归

我看的书举例是使用Python代码实现的快速排序,代码如下:

 def quicksort(array):
if len(array) < 2: #基线条件:为空或者只包含一个元素的数组是“有序”的
return array
else:#递归条件
pivot = array[0]
less = [i for i in array[1:] if i<= pivot]#由所有小于等于基准值的元素组成的数组
greater = [i for i in array[1:] if i> pivot]#由所有大于基准值的元素组成的子数组
return quicksort(less) + [pivot] + quicksort(greater) print(quicksort([10, 5, 2, 3]))

在这段代码里,首先满足递归条件时,取得一个基准数,基准数通常为数组的第一个元素,然后分成两个子数组,一个是小于等于基准数的子数组和大于基准数的子数组,不断进行递归调用对这两个子数组进行排序,最后得到排序好的数组。

书中讲解看完后,头脑里很快就有了思绪,但是当我想把上面的代码转换成C#时,就摸不着头脑,打脑壳的遭不住,因为在C#里并不能像上面一样简简单单的就实现,最主要的就是C#中数组不能通过直接相加来合并。

所以还是在网上看了不少C#快速排序的详解后写出了以下代码:

         /// <summary>
/// 快速排序对数组进行升序排序
/// </summary>
/// <param name="array">要排序的数组</param>
/// <param name="leftIndex">从左边遍历的第一个数的索引</param>
/// <param name="rightIndex">从右边遍历的第一个数的索引</param>
public static void QuickSort(int[] array, int leftIndex, int rightIndex)
{
if (leftIndex >= rightIndex)//基线条件
return;
int n = leftIndex;
int m = rightIndex;
int pivot = array[leftIndex];
while (n != m)
{
for (; n < m; m--)
{
if (array[m] < pivot)
{
array[n] = array[m];//交换位置
break;
}
}
for (; n < m; n++)
{
if (array[n] > pivot)
{
array[m] = array[n];
break;
}
}
}
array[n] = pivot;//循环完成后已经按照小于基准数和大于基准数左右排好序,基准数放中间。
QuickSort(array, leftIndex, n - );//对着两个子数组进行递归
QuickSort(array, n + , rightIndex);
}

网上快速排序的思路如上,甚至来说基线条件和我在书中看见的都已经完全不一样,并且和书中的逻辑也不太相同,只是依旧是分治法解决问题。

不仅是分出两个子数组,而是对当前的数组进行排序,排序过程也不好理解,从右至左循环,找出比基准数大的数,再从左至右循环,找出比基准数小的数,然后将两个数字调换位置,到最后只剩一个数的时候,就是基准数该在的位置,把基准数放到这个位置。

所以我足足想了2天,才能够独立写出上面的快速排序代码,不过我已经不知道我到底是真真切切理解了排序的思路,还是说因为看了太久,已经把排序的方式背在脑中了,真是悲哀,聪明的小伙伴一定一下就能学会,我却想了两天连自己也不清楚到底想明白没有了。

最后,我依旧有一个疑问,快速排序的时间复杂度是O(nlogn),那么上面的Python代码依旧是O(nlogn)吗?

新声明数组,然后将他们赋值,再合并,这样的操作会影响时间复杂度吗?

甚至我想用Linq语法

             int[] less = (from i in array where i < pivot select i).ToArray();
int[] greater = (from i in array where i > pivot select i).ToArray();

返回的数组甚至还是排好序的,那我直接用将这两个数组和基准数加起来不是更简单吗?我已经完全懵逼了,不知道时间复杂度是如何计算的,学习的长路真是漫漫啊!

c#中快速排序的学习的更多相关文章

  1. PHP中的Libevent学习

    wangbin@2012,1,3 目录 Libevent在php中的应用学习 1.      Libevent介绍 2.      为什么要学习libevent 3.      Php libeven ...

  2. JS中childNodes深入学习

    原文:JS中childNodes深入学习 <html xmlns="http://www.w3.org/1999/xhtml"> <head> <ti ...

  3. CNCC2017中的深度学习与跨媒体智能

    CNCC2017中的深度学习与跨媒体智能 转载请注明作者:梦里茶 目录 机器学习与跨媒体智能 传统方法与深度学习 图像分割 小数据集下的深度学习 语音前沿技术 生成模型 基于贝叶斯的视觉信息编解码 珠 ...

  4. 图解BERT(NLP中的迁移学习)

    目录 一.例子:句子分类 二.模型架构 模型的输入 模型的输出 三.与卷积网络并行 四.嵌入表示的新时代 回顾一下词嵌入 ELMo: 语境的重要性 五.ULM-FiT:搞懂NLP中的迁移学习 六.Tr ...

  5. python中confIgparser模块学习

    python中configparser模块学习 ConfigParser模块在python中用来读取配置文件,配置文件的格式跟windows下的ini配置文件相似,可以包含一个或多个节(section ...

  6. Scala中的类学习

    Scala中的类学习 从java了解类的情况下,了解Scala的类并不难.Scala类中的字段自动带getter和setter方法,用@BeanProperty注解生成javaBean对象的getXX ...

  7. Deep learning for visual understanding: A review 视觉理解中的深度学习:回顾 之一

    Deep learning for visual understanding: A review 视觉理解中的深度学习:回顾 ABSTRACT: Deep learning algorithms ar ...

  8. Java:类集框架中集合的学习

    Java:类集框架中集合的学习 集合 Java:Set的学习 Set是类集框架中的集合类.集合是不按特定的方式排序,并且没有重复对象的一种类. Q:Set如何操作?Set中的不按特定方式排序是怎么排序 ...

  9. OpenCV中Camshitf算法学习(补充)

    结合OpenCV中Camshitf算法学习,做一些简单的补充,包括: 实现全自动跟随的一种方法 参考opencv中的相关demo,可以截取目标物体的图片,由此预先计算出其色彩投影图,用于实际的目标跟随 ...

随机推荐

  1. IOS 小新兵

    2017-07-02 lipo -info BaiduOAuthSDK.a  查看a文件支持的架构 第一个坎: 报错:  未找到模块baiduLogin对应的类BaiduLoginModule.若是自 ...

  2. mac install brew

    $ ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)" ...

  3. msgs no .h file

    1.单独编译包,catkin_make --pkg 包名,failed,则 2.进入build下对应的msgs包中,使用make,以及make install,failed,则 3.使用catkin_ ...

  4. Mercurial和Git的主要区别(zz)

    Mercurial和Git的主要区别 17 August 2008 1.Mercurial用Python开发,Git用C开发,相对来说,Git比较快,但是Mercurial的性能也不差 2.Mercu ...

  5. 通过flask中的Response返回json数据

    使用flask的过程中,发现有时需要生成一个Response并返回.网上查了查,看了看源码,找到了两种办法: from flask import Response, json Response(jso ...

  6. mybatis-mysql类型映射

    JDBC Type Java Type CHAR String VARCHAR String LONGVARCHAR String NUMERIC java.math.BigDecimal DECIM ...

  7. NOIP2016原题终结测试(2017081801)

    NOIP2016还有几道原题没有写掉,今天就一并布置掉. 答案的问题,有部分会先放到NOIP题解中,是单独发布的. 最后会汇总放在答案中,各位不要急. 还有,后期会有原创题测试,这个不急,反正11月才 ...

  8. 55.UIbutton点击切换颜色

    #import "ViewController.h" #define width_w     [UIScreen mainScreen].bounds.size.width #de ...

  9. thinkphp5 数据库和模型

    1.Db和模型的存在只是ThinkPHP5.0架构设计中的职责和定位不同,Db负责的只是数据(表)访问,模型负责的是业务数据和业务逻辑.2.Db和模型最明显的一个区别就是Db查询返回的数据类型为数组( ...

  10. Tomcat架构解析(四)-----Coyote、HTTP、AJP、HTTP2等协议

    Connector是Tomcat中非常重要的一个组成部分,说白了,就是如何从客户端获取到相应的请求信息.这部分主要包括的难点有这样几个部分: 1.客户端与服务端的协议 客户端与服务端的协议是多种多样的 ...