c#中快速排序的学习
最近看了一句话,说的是在现实生活中,会写字的人不见得会写出好文章,学习编程语言就像是学会了写字,学会了编程语言并不一定能写出好程序。
我觉得就是很有道理,以前读书的时候,基本学完了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#中快速排序的学习的更多相关文章
- PHP中的Libevent学习
wangbin@2012,1,3 目录 Libevent在php中的应用学习 1. Libevent介绍 2. 为什么要学习libevent 3. Php libeven ...
- JS中childNodes深入学习
原文:JS中childNodes深入学习 <html xmlns="http://www.w3.org/1999/xhtml"> <head> <ti ...
- CNCC2017中的深度学习与跨媒体智能
CNCC2017中的深度学习与跨媒体智能 转载请注明作者:梦里茶 目录 机器学习与跨媒体智能 传统方法与深度学习 图像分割 小数据集下的深度学习 语音前沿技术 生成模型 基于贝叶斯的视觉信息编解码 珠 ...
- 图解BERT(NLP中的迁移学习)
目录 一.例子:句子分类 二.模型架构 模型的输入 模型的输出 三.与卷积网络并行 四.嵌入表示的新时代 回顾一下词嵌入 ELMo: 语境的重要性 五.ULM-FiT:搞懂NLP中的迁移学习 六.Tr ...
- python中confIgparser模块学习
python中configparser模块学习 ConfigParser模块在python中用来读取配置文件,配置文件的格式跟windows下的ini配置文件相似,可以包含一个或多个节(section ...
- Scala中的类学习
Scala中的类学习 从java了解类的情况下,了解Scala的类并不难.Scala类中的字段自动带getter和setter方法,用@BeanProperty注解生成javaBean对象的getXX ...
- Deep learning for visual understanding: A review 视觉理解中的深度学习:回顾 之一
Deep learning for visual understanding: A review 视觉理解中的深度学习:回顾 ABSTRACT: Deep learning algorithms ar ...
- Java:类集框架中集合的学习
Java:类集框架中集合的学习 集合 Java:Set的学习 Set是类集框架中的集合类.集合是不按特定的方式排序,并且没有重复对象的一种类. Q:Set如何操作?Set中的不按特定方式排序是怎么排序 ...
- OpenCV中Camshitf算法学习(补充)
结合OpenCV中Camshitf算法学习,做一些简单的补充,包括: 实现全自动跟随的一种方法 参考opencv中的相关demo,可以截取目标物体的图片,由此预先计算出其色彩投影图,用于实际的目标跟随 ...
随机推荐
- 【jdbcTemplate】baseDao书写规范
今天加班,为了下个月的北京之行,希望父亲身体安康,一切顺利: 老大今天发出来同事的代码,并标记了jdbcTemplate的书写规范,此处查询数据库之前声明对象时,不用new出来,因为在底层源码中已经给 ...
- 1.preparation
1)Evarobot 安装 http://wiki.ros.org/Robots/evarobot/Tutorials/indigo/Evarobot%20Installation 2)PC 安装 a ...
- oracle 笔记DBA
1.1oracle开启归档 关闭数据库 SQL>archive log list; SQL>shutdown immediate; SQL>startup mount ; SQL&g ...
- 提升HTML5的性能体验系列之二 列表流畅滑动
App的顶部一般有titlebar,下面是list.常见的一个需求是要在list滚动时,titlebar不动.这个简单的需求,实现起来其实并不简单. 在普通web上的做法是使用div的滚动条,把lis ...
- 【转】如何用Redis做LRU-Cache
LRU(Least Recently Used)最近最少使用算法是众多置换算法中的一种. Redis中有一个maxmemory概念,主要是为了将使用的内存限定在一个固定的大小.Redis用到的LRU ...
- 2019.01.19 codeforces896C.Willem, Chtholly and Seniorious(ODT)
传送门 ODTODTODT出处(万恶之源) 题目简述: 区间赋值 区间加 区间所有数k次方和 区间第k小 思路:直接上ODTODTODT. 不会的点这里 代码: #include<bits/st ...
- 2018.11.24 poj3693Maximum repetition substring(后缀数组)
传送门 后缀数组好题. 考虑枚举循环节长度lenlenlen. 然后考虑枚举循环节的起点来更新答案. 但是直接枚举每次O(n)O(n)O(n). 考虑枚举len∗k+1len*k+1len∗k+1作为 ...
- 哪些优秀的 Windows 小工具,类似 clover 或 everything
有哪些优秀的 Windows 小工具,类似 clover 或 everything? 目前已知的有everything, listary, total commander, clover, dexpo ...
- SSH三大框架的工作原理
Hibernate工作原理 原理:1.通过Configuration().configure();读取并解析hibernate.cfg.xml配置文件2.由hibernate.cfg.xml中的< ...
- UVa 11762 Race to 1 (数学期望 + 记忆化搜索)
题意:给定一个整数 n ,然后你要把它变成 1,变换操作就是随机从小于等于 n 的素数中选一个p,如果这个数是 n 的约数,那么就可以变成 n/p,否则还是本身,问你把它变成 1 的数学期望是多少. ...