用菜鸟的思维学习算法 -- 马桶排序、冒泡排序和快速排序

【博主】反骨仔    【来源】http://www.cnblogs.com/liqingwen/p/4994261.html   

目录

  • 马桶排序(令人作呕的排序)
  • 冒泡排序(面试都要问的算法)
  • 快速排序(见证亚当和夏娃的爱情之旅)

马桶排序(令人作呕的排序)

  一、场景:期末考试完了,老师要将同学们的分数从高到低排序。假设班上有 5 名同学,分别考了 5 分、3 分、5 分、2 分和 8 分【满分:10 分】,排序后的结果就是 8 5 5 3 2,现在,让我们先思考 10 分钟吧!
 
  二、思路:
    (1)先创建一个数组 int scores[11],就有 scores[0]~scores[10] 共 11 个变量。我们用变量值为 0 表示没有人得到该分数,即 scores [0]=0 表示没有人得 0 分,scores [10]=0 表示没有人得 10 分,而 scores [8]=1 表示有一个人得到 8 分。
 
    
    (2)第 1 个数为 5,所以在 scores[5]=0 的基础上+1,即 scores[5]=1 表示有 1 人得到 5 分
 
    
    (3)第 2 个数为 3,所以在 scores[3]=0 的基础上+1,即 scores[3]=1 表示有 1 人得到 3 分
 
    
    (4)第 3 个数为 5,所以在 scores[5]=1 的基础上+1,即 scores[5]=2 表示有 2 人得到 5 分
 
         
      ... ...
    (5)依此类推,处理第 4 和第 5 个数,最终的结果图如下:
 
 
    
    (6)我们发现,scores[0]~scores[10] 内对应的值就是 0~10 分中每个分数所出现的次数。现在,只需将结果打印即可,出现几次就打印机次。
 
 
     我们暂且称它为“马桶排序”,这个算法就相当于有 11 个马桶,编号从 0~10。每出现一个数,就在对应编号的马桶中放一个旗子。
 
图:这里有 11 个马桶
 
 
   三、思考:现在分别有 5 个人的名字和分数:小A 5、小二 3、小三 5、小妞 2 和王大锤 8,请按照分数从高到低,输出他们的名字?
 
       【特点】
         假设需要排序的范围 0~20000000,则需要 new int[20000001],非常浪费空间,即便只给 2 个数排序(1,19999999 );
         如果排序的数是小数也不行,如:3.141 5926 5358 9793 2384 6264 3383 2795 0238;
 
  这里使用 C# 给出简单的算法过程。
         static void Main(string[] args)
{
var scores = new int[] { , , , , };
var newScores = new int[]; for (int i = ; i < scores.Length; i++)
{
var score = scores[i];
newScores[score]++;
} for (int i = newScores.Length - ; i >= ; i--)
{
var num = newScores[i];
for (int j = ; j <= num; j++)
{
Console.Write($"{i} ");
}
} Console.WriteLine();
Console.Read();
}
}

冒泡排序(面试都要问的算法)

  一、基本思想:每次比较相邻的两个 元素,按需调整顺序
 
  二、题目:要求将 12 35 99 18 76 这 5 个数进行从大到小排序
 
  三、思路:
    (1)先比较第 1 位和第 2 位的大小,12<35,因为希望越小越靠后,所以要调整两者顺序,交换后的结果:35 12 99 18 76
    (2)现在比较第 2 位和第 3 位的大小,12<99,所以需要交换位置,交换后的结果为:35 99 12 18 76
    (3)接着比较第 3 位和第 4 位的大小,12<18,交换后的结果为:35 99 18 12 76
    (4)最后比较第 4 位和第 5 位的大小,12<76,交换后的结果为:35 99 18 76 12
 
 
    
    (5)经过 4 次后我们发现 5 个数中最小的一个数已经就位,每将一个数归位我们称其为“一趟”;
    (6)现在我们开始第二趟,目标将第 2 小的数归位,根据之前逻辑,还是从第 1 个数和第 2 个数开始比较上:
            35 99 18 76 12 --①--> 99 35 18 76 12 --②--> 99 35 18 76 12 --③--> 99 35 76 18 12
            在第一趟比较就知道第 5 位是最小的,所以第 4 位不用和第 5 位比较,这一趟只需比较 3 次
    (7)第3趟:99 35 76 18 12 --> 99 35 76 18 12 --> 99 76 35 18 12 (比较 2 次)
    (8)第4趟:99 76 35 18 12 --> 99 76 35 18 12 ,有4个数已经就位,那么最后一个数无须比较,它就是最大的
 
  【总结】如果有 n 个数进行排序,只需将 n-1 个数归位,即要进行 n-1 趟操作,而每一趟开始都从第 1 位进行相邻的两个数 进行比较,将小的那个数放在后面,已经归位的就不用进行比较。
  
  【特点】冒泡算法的核心部分是双重嵌套循环,可以看出时间复杂度是 O(N²),这是一个非常高的时间复杂度。
 
  这里使用 C# 给出简单的算法过程。 
         static void Main(string[] args)
{
var nums = new int[] { , , , , };
Output(nums); for (int j = ; j < nums.Length - ; j++)
{
for (int i = ; i < nums.Length - ; i++)
{
if (nums[i] < nums[i + ])
{
var temp = nums[i];
nums[i] = nums[i + ];
nums[i + ] = temp;
}
} Output(nums);
} Console.Read();
} /// <summary>
/// 控制台输出
/// </summary>
/// <param name="nums"></param>
static void Output(int[] nums)
{
foreach (var num in nums)
{
Console.Write($"{num} ");
} Console.WriteLine();
}

快速排序(见证亚当和夏娃的爱情之旅)

  一、场景:对 6 1 2 7 9 3 4 5 10 8 这 10 个数进行排序
 
  二、思路:
    先找一个基准数(一个用来参照的数),为了方便,我们选最左边的 6,希望将 >6 的放到 6 的右边,<6 的放到 6 左边。如:3 1 2 5 4 6 9 7 10 8
    先假设需要将 6 挪到的位置为 k,k 左边的数 <6,右边的数 >6
    (1)我们先从初始数列“6 1 2 7 9 3 4 5 10 8 ”的两端开始“探测 ”,先从右边往左找一个 <6 的数,再从左往右找一个 >6 的数,然后交换。我们用变量 i 和变量 j 指向序列的最左边和最右边。刚开始时最左边 i=0 指向 6,最右边 j=9 指向 8
 
 
 
图:亚当 i 和夏娃 j 
 
    (2)现在设置的基准数是最左边的数,所以序列先右往左移动(j--),当找到一个 <6 的数(5)就停下来。接着序列从左往右移动(i++),直到找到一个 >6 的数又停下来(7);
    (3)两者交换,结果:6 1 2 5 9 3 4 7 10 8;
 
 
 
    (4)j 的位置继续向左移动(友情提示:每次都必须先从 j 的位置出发),发现 4 满足要求,接着 i++ 发现 9 满足要求,交换后的结果:6 1 2 5 4 3 9 7 10 8;
 
 
    (5)目前 j 指向的值为 9,i 指向的值为 4,j-- 发现 3 符合要求,接着 i++ 发现 i=j,说明这一轮移动结束啦。现在将基准数 6 和 3 进行交换,结果:3 1 2 5 4 6 9 7 10 8;现在 6 左边的数都是 <6 的,而右边的数都是 >6 的,但游戏还没结束

    

 图:亚当和夏娃终于产生了交集
 
    (6)我们将 6 左边的数拿出来先:3 1 2 5 4,这次以 3 为基准数进行调整,使得 3 左边的数 <3,右边的数 >3,根据之前的模拟,这次的结果:2 1 3 5 4
    (7)再将 2 1 抠出来重新整理,得到的结果: 1 2
    (8)剩下右边的序列:9 7 10 8 也是这样来搞,最终的结果: 1 2 3 4 5 6 7 8 9 10 (具体看下图)
 
 
 
 
    【总结】快速排序的每一轮处理其实就是将这一轮的基准数归位,当所有的基准数归位,排序就结束啦
 
 
 
 

  【参考】文章改编与插图来源《啊哈!算法》

[C#][算法] 用菜鸟的思维学习算法 -- 马桶排序、冒泡排序和快速排序的更多相关文章

  1. 感知机学习算法(PLA)

    Perception Learning Algorithm, PLA 1.感知机 感知机是一种线性分类模型,属于判别模型. 感知机模型给出了由输入空间到输出空间的映射: f(X) = sign(WTX ...

  2. CS229 Lesson 5 生成学习算法

    课程视频地址:http://open.163.com/special/opencourse/machinelearning.html 课程主页:http://cs229.stanford.edu/ 更 ...

  3. 前向分步算法 && AdaBoost算法 && 提升树(GBDT)算法 && XGBoost算法

    1. 提升方法 提升(boosting)方法是一种常用的统计学方法,在分类问题中,它通过逐轮不断改变训练样本的权重,学习多个分类器,并将这些分类器进行线性组合,提高分类的性能 0x1: 提升方法的基本 ...

  4. 1、学习算法和刷题的框架思维——Go版

    前情提示:Go语言学习者.本文参考https://labuladong.gitee.io/algo,代码自己参考抒写,若有不妥之处,感谢指正 关于golang算法文章,为了便于下载和整理,都已开源放在 ...

  5. Stanford大学机器学习公开课(五):生成学习算法、高斯判别、朴素贝叶斯

    (一)生成学习算法 在线性回归和Logistic回归这种类型的学习算法中我们探讨的模型都是p(y|x;θ),即给定x的情况探讨y的条件概率分布.如二分类问题,不管是感知器算法还是逻辑回归算法,都是在解 ...

  6. 深度信任网络的快速学习算法(Hinton的论文)

    也没啥原创,就是在学习深度学习的过程中丰富一下我的博客,嘿嘿. 不喜勿喷! Hinton是深度学习方面的大牛,跟着大牛走一般不会错吧-- 来源:A fast learning algorithm fo ...

  7. 感知机学习算法 python实现

    参考李航<统计学习方法> 一开始的感知机章节,看着不太复杂就实现一下... """ 感知机学习算法的原始形式 例2.1 """ ...

  8. 各大公司广泛使用的在线学习算法FTRL详解

    各大公司广泛使用的在线学习算法FTRL详解 现在做在线学习和CTR常常会用到逻辑回归( Logistic Regression),而传统的批量(batch)算法无法有效地处理超大规模的数据集和在线数据 ...

  9. 各大公司广泛使用的在线学习算法FTRL详解 - EE_NovRain

    转载请注明本文链接:http://www.cnblogs.com/EE-NovRain/p/3810737.html 现在做在线学习和CTR常常会用到逻辑回归( Logistic Regression ...

随机推荐

  1. ArcGIS 10.0紧凑型切片读写方法

    首先介绍一下ArcGIS10.0的缓存机制: 切片方案 切片方案包括缓存的比例级别.切片尺寸和切片原点.这些属性定义缓存边界的存在位置,在某些客户端中叠加缓存时匹配这些属性十分重要.图像格式和抗锯齿等 ...

  2. UWP中实现自定义标题栏

    UWP中实现自定义标题栏 0x00 起因 在UWP开发中,有时候我们希望实现自定义标题栏,例如在标题栏中加入搜索框.按钮之类的控件.搜了下资料居然在一个日文网站找到了一篇介绍这个主题的文章: http ...

  3. Java 征途:行者的地图

    前段时间应因缘梳理了下自己的 Java 知识体系, 成文一篇望能帮到即将走进或正在 Java 世界跋涉的程序员们. 第一张,基础图 大约在 2003 年我开始知道 Java 的(当时还在用 Delph ...

  4. DDD CQRS架构和传统架构的优缺点比较

    明天就是大年三十了,今天在家有空,想集中整理一下CQRS架构的特点以及相比传统架构的优缺点分析.先提前祝大家猴年新春快乐.万事如意.身体健康! 最近几年,在DDD的领域,我们经常会看到CQRS架构的概 ...

  5. 初探Vue

    Vue.js(读音/vju:/,类似于view),是近来比较火的前端框架,但一直没有怎么具体了解.实现过,就知道个啥的MVVM啦,数据驱动啦,等这些关于Vue的虚概念. 由于最近,小生在公司中,负责开 ...

  6. Django

    一.Django 简介 Django 是一个由 Python 写成的开放源代码的 Web 应用框架.它最初是被开发来用于管理劳伦斯出版集团旗下的一些以新闻内容为主的网站的,即是 CMS(内容管理系统) ...

  7. 纯javaScript、jQuery实现个性化图片轮播

    纯javaScript实现个性化图片轮播 轮播原理说明<如上图所示>: 1. 画布部分(可视区域)属性说明:overflow:hidden使得超出画布部分隐藏或说不可见.position: ...

  8. SAP CRM 用户界面对象类型和设计对象

    在CRM中的用户界面对象类型的帮助下,我们可以做这些工作: 进行不同的视图配置 创建动态导航 从设计层控制字段标签.值帮助 控制BOL对象的属性的可视性 从导航栏访问自定义组件 一个用户界面对象类型之 ...

  9. Java 中获取类路径 classpath 的方法

    System.out.println("++++++++++++++++++++++++"); String path = System.getProperty("jav ...

  10. Ubuntu 16.04 安装 arm-linux-gcc 嵌入式交叉编译环境 问题汇总

    闲扯: 实习了将近半年一直在做硬件以及底层的驱动,最近要找工作了发现了对linux普遍要求很高,而且工作岗位也非常多,所以最近一些时间在时不时地接触linux. 正文:(我一时兴起开始写博客,准备不充 ...