比冒泡算法还简单的排序算法看起来满是Bug的程序,居然是对的
程序bug也能负负得正吗?
还真可以。
比如程序员们再熟悉不过的排序算法,通过两个bug居然能歪打正着,实在令人匪夷所思。
请看这位程序员写的数组升序排序代码:
今天这串代码在HackerNews论坛上突然火了起来,引来大批程序员围观。
乍一看这段代码,你的反应会是什么?会不会觉得这个程序员水平太差了,连基本的冒泡算法都写不好:
不等号方向错了,第二层循环指数j的范围也弄错了。
总之,这段代码绝对不可能正确。
冒泡算法
但如果你真的运行一下会发现,结果还真的是按照升序排列的。
我们再来看一下正确的冒泡算法代码是怎样的:
后者不同之处是ji1且A〔i〕gt;A〔j〕,两段程序大相径庭。
然而我要告诉你一个不可思议的事实,其实第一串代码是对的,而且可以严格证明。
那么它是如何实现正确排序的?为何能歪打正着
仔细一想,其实很容易理解。因为该算法比冒泡排序多一半交换操作,正好可以将降序变成升序。
不过,作者还是给出了严格的证明。
我们定义P是经过i次(1in)外循环后得到的数组。
如果算法正确,那么前i项已经是升序排列,即A〔1〕A〔2〕。。。A〔i〕。
证明该算法正确,实际上就是证明P对于任何n都成立。
根据数学归纳法,我们只要证明P成立,假设P成立,接着再证明Pi1也成立,命题即可得证。
P显然是正确的,而且这一步和普通的冒泡算法降序没有区别,经过第1次外循环,A〔1〕就是整个数组的最大元素。
接着我们假设P成立,然后证明Pi1成立。
我们先定义一个序数k:首先假设A〔k〕(k介于1i之间)满足A〔k〕gt;A〔i1〕最小的一个数,那么A〔k1〕A〔i1〕(k1)。
如果A〔i1〕A〔i〕,那么这样的k不存在,我们就令ki1。
考虑以下三种情况:
1、1jk1
由于A〔i1〕A〔j〕,没有任何元素交换发生。
2、kji(如果ki1,则不存在此步骤)
由于A〔j〕gt;A〔i1〕,所以每次比较后都会有元素交换发生。
我们使用A〔〕和A〔〕来表示交换前和交换后的元素,所以
A〔i1〕A〔k〕,A〔k〕A〔i1〕
经过一系列交换,最大元素最终被放到了A〔i1〕位置上,原来的A〔i1〕变成了最大元素,A〔k〕被插入了大小介于原来A〔k〕和A〔k1〕之间的元素。
3、i1jn
由于最大元素已经交换到前i1个元素中,此过程也没有任何元素交换。
最后,P就是升序排序算法执行完以后的结果。
由于内外两组循环没有任何范围差别,因此这可以说是最简单的排序算法了。
从代码上来看,它很像冒泡算法,但从证明过程中可以看出,这实际上是一种插入算法。
插入算法算法复杂度
显然,该算法总会进行n次比较,接下来计算算法的交换次数。
可以证明交换其次最多为I2(n1),最少为n1。
其中I为初始数字的逆序数,最大为n(n1)2
因此整个算法的复杂度为O(n)。
从证明过程中可以看出,除了i1的循环以外,其余循环里ji1之后的部分完全无效,因此可以将这部分省略,得到简化后的算法。
该算法减少了比较和交换次数,不过算法复杂度依然是O(n)。网友:这个算法我以前见过
比最容易理解的冒泡算法还要简单,这个排序算法在HackerNews上很快引起了网友的围观。
不少人觉得它很眼熟。
有位网友表示,自己曾在奥林匹克数学竞赛中看到一个同学用了一种非常奇怪的排序算法,它可以运行但是效率很低,更像是一种插入排序。
如果我没记错的话,他用的就是这种算法。
事实上,关于这种算法的讨论已久,从2014年开始就不断有人发帖,这次作者将论文上传到arXiv后又引起了广泛热议。
甚至还有乌龙事件发生。
有位网友扫了一眼论文就以为这个算法和自己10年前提出的一样。
留言网友的算法:
乍一看两种算法的代码确实很像,原理上的确有些相似。
都是看起来像冒泡排序,但其实更贴近选择排序。
不过很快有人指出真相:这种算法中ji1ton,并且是当A〔i〕gt;A〔j〕时交换。
而作者提出的算法中j1ton,A〔i〕lt;A〔j〕时交换。
两种算法相比,网友此前提出的更容易被理解为什么可以运行。
当然也有歪楼的,有人就调侃自己刚学编程时写过这个算法。
我百分百确定,在我刚开始学编程、并想要找到最短的排序方法时就写过它。
不过说到实际应用上,这种算法需要的计算时间太长了。
有人就认为,这种算法此前被发现过很多次,但是那些人根本没打算用它。
也有人提出:这种排序没有睡眠排序简单。
睡眠排序就是构造n个线程,让线程和排序的n个数对应。
例如对于〔4,2,3,5,9〕这样一组数字,就创建5个线程,每个线程睡眠4s,2s,3s,5s,9s。这些线程睡醒之后,就把自己对应的数报出来即可。这样等所有线程都醒来,排序就结束了。
但和作者提出的算法一样,睡眠排序由于多线程的问题,在真正实现上也有困难。
此外,这位网友也表示自己看到过这种算法:
我确定我此前看到过这种算法,它没有名字吗?
很快就有人提议说
如果它没有名字的话,我建议称之为‘面试排序’。
参考链接:
〔1〕https:news。ycombinator。comitem?id28758106
〔2〕https:arxiv。orgabs2110。01111
活在当下的我们我是狮子女一枚,今年20整,别看我年纪不大,却已经步入社会2年多了,经历过各种心酸苦辣。也深知人心的善良与险恶。活在当下的我们,每天为了上班不会迟到,早早的就跑出家门,去……
仍然的反义词是什么现代汉语反义词在修辞上具有很重要的作用。反义词的正确辨析与熟练掌握、运用,可以充分发挥词语的表义功能,提高我们运用语言的能力。一个新学期即将又开始,童鞋们将又面临一轮的复习,以……
初中生物教案遗传和变异现象一、教学目标1、知识目标正确表述性状、相对性状、遗传、变异等现象;2、能力目标通过猜谜语、欣赏漫画等活动,培养学生分析、识图能力;能举例说出动物、植物和人的不同性状……
七年级生物上册的教学反思今天下午在3班讲开花和结果一节,先让每组3号同学到黑板对照图说出花的结构,可能是同学能力好加上内容简单,这部分进行比较顺利。又让6号同学说出传粉的过程要求指着图说,我是让学生感……
用不同凡响一词来造句1、即便首相在国内临的困难与麻烦有增无减,他还是想在国际舞台上再出一个不同凡响的举动。2、你可以做最不同凡响的事情,无论发生什么。3、优秀团干部的号召力,果然不同凡……
最新的学生教学反思范文经过将近一个星期的认真备课,还算满意的完成了这次复习课的讲授任务。课后通过和听课老师的交流与请教从中也终结出了一些优点和不足。本节课是以复习曾经学习过的内容为主,把整单元……
爱如茉莉语文老师教学后反思首先说说为什么选择这篇课文,不经意见我发现现在的孩子怨言太多,对父母的抱怨、对老师的抱怨非常的多,除了一些合理的之外,有的时候显得过多的以自我为中心,而不会体谅师长的良苦用心。……
二年级青蛙看海教学反思《青蛙看海》是一篇童话。课文叙述了长期生活在湖边的青蛙,很想看看大海,在苍鹰的指点下,跟着松鼠一个台阶一个台阶地跳,最后终于到达山顶,看到大海的事。说明了只要脚踏实地一步一个脚……
数学教案小小建筑师大班数学活动小小建筑师(认识长方体)活动目标:、认识长方体,感知它的特点,能找到与它相似的物体,能区分长方形和长方体,正方体和长方体。2、学习按形体的明……
巴尔扎克葬词教案教案示例一第一课时教学目标、指导学生诵读课文,把握课文的基本思路和感情脉络。、体会葬词中所表现的情和理融合的特点。、初步走近两位文学大师,了解在他……
热闹背后的冷思考不难发现随着课改的逐步深入,教师的教学观念,教学方式都在发生着变化。我们的课堂教学正呈现欣欣向荣之势。以往那种灌输式,一潭死水式的课堂已不多见了,取而代之的是生机勃勃、热热闹闹……
课文只有一个地球教学反思范文《只有一个地球》是十一册第四单元的一篇科学小品文。本单元的主题是珍惜资源,保护环境。根据单元教学目标确定本课的教学重点是通过深入文本、联系实际,明白人类的生存只有一个地球这样一……