自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

比冒泡算法還簡單的排序算法:看起來滿是bug的程序,居然是對的

新聞 前端 算法
程序bug也能負(fù)負(fù)得正嗎?比如程序員們再熟悉不過的排序算法,通過兩個“bug”居然能歪打正著,實在令人匪夷所思。

 本文經(jīng)AI新媒體量子位(公眾號ID:QbitAI)授權(quán)轉(zhuǎn)載,轉(zhuǎn)載請聯(lián)系出處。

[[427437]]

程序bug也能負(fù)負(fù)得正嗎?

還真可以。

比冒泡算法還簡單的排序算法:看起來滿是bug的程序,居然是對的

比如程序員們再熟悉不過的排序算法,通過兩個“bug”居然能歪打正著,實在令人匪夷所思。

請看這位程序員寫的數(shù)組升序排序代碼:

  1. for i = 1 to n do 
  2. for j = 1 to n do 
  3. if A[i] < A[j] then 
  4. swap A[i] and A[j] 

今天這串代碼在Hacker News論壇上突然火了起來,引來大批程序員圍觀。

比冒泡算法還簡單的排序算法:看起來滿是bug的程序,居然是對的

乍一看這段代碼,你的反應(yīng)會是什么?會不會覺得這個程序員水平太差了,連基本的冒泡算法都寫不好:

不等號方向錯了,第二層循環(huán)指數(shù)j的范圍也弄錯了。

總之,這段代碼“絕對不可能正確”。

比冒泡算法還簡單的排序算法:看起來滿是bug的程序,居然是對的

△冒泡算法

但如果你真的運行一下會發(fā)現(xiàn),結(jié)果還真的是按照升序排列的。

我們再來看一下正確的冒泡算法代碼是怎樣的:

  1. for i = 1 to n do 
  2. for j = i + 1 to n do 
  3. if A[i] > A[j] then 
  4. swap A[i] and A[j] 

后者不同之處是j = i + 1且A[i] > A[j] ,兩段程序大相徑庭。

然而我要告訴你一個不可思議的事實,其實第一串代碼是對的,而且可以嚴(yán)格證明。

那么它是如何實現(xiàn)正確排序的?

為何能歪打正著

仔細(xì)一想,其實很容易理解。因為該算法比冒泡排序多一半交換操作,正好可以將降序編程升序。

不過,作者還是給出了嚴(yán)格的證明。

我們定義Pᵢ是經(jīng)過i次(1 ≤ i ≤ n)外循環(huán)后得到的數(shù)組。

如果算法正確,那么前i項已經(jīng)是升序排列,即A[1] ≤ A[2] ≤ . . . ≤ A[i]。

證明該算法正確,實際上就是證明Pₙ對于任何n都成立。

根據(jù)數(shù)學(xué)歸納法,我們只要證明P₁成立,假設(shè)Pᵢ成立,接著再證明Pi+1也成立,命題即可得證。

P₁顯然是正確的,而且這一步和普通的冒泡算法降序沒有區(qū)別,經(jīng)過第1次外循環(huán),A[1]就是整個數(shù)組的最大元素。

接著我們假設(shè)Pᵢ成立,然后證明Pi+1成立。

我們先定義一個序數(shù)k:

首先假設(shè)A[k](k介于1~i之間)滿足A[k]>A[i+1]最小的一個數(shù),那么A[k−1]≤A[i+1](k≠1)。

如果A[i+1]≥A[i],那么這樣的k不存在,我們就令k=i+1。

考慮以下三種情況:

1、1 ≤ j ≤ k−1

由于A[i+1]>A[j],沒有任何元素交換發(fā)生。

2、 k ≤ j ≤ i (如果k=i+1,則不存在此步驟)

由于A[j]>A[i+1],所以每次比較后都會有元素交換發(fā)生。

我們使用A[ ]和A′[ ]來表示交換前和交換后的元素,所以

A′[i+1] = A[k],A′[k]=A[i+1]

經(jīng)過一系列交換,最大元素最終被放到了A[i+1] 位置上,原來的A[i+1]變成了最大元素,A[k]被插入了大小介于原來A[k]和A[k-1]之間的元素。

3、i+1 ≤ j ≤ n

由于最大元素已經(jīng)交換到前i+1個元素中,此過程也沒有任何元素交換。

最后,Pₙ就是升序排序算法執(zhí)行完以后的結(jié)果。

由于內(nèi)外兩組循環(huán)沒有任何范圍差別,因此這可以說是“最簡單”的排序算法了。

從代碼上來看,它很像冒泡算法,但從證明過程中可以看出,這實際上是一種插入算法。

比冒泡算法還簡單的排序算法:看起來滿是bug的程序,居然是對的

△插入算法

算法復(fù)雜度

顯然,該算法總會進行次比較,接下來計算算法的交換次數(shù)。

可以證明交換其次最多為I+2(n-1),最少為n-1。

其中I為初始數(shù)字的逆序數(shù),最大為n(n-1)/2

因此整個算法的復(fù)雜度為O(n²)。

從證明過程中可以看出,除了i=1的循環(huán)以外,其余循環(huán)里j=i-1之后的部分完全無效,因此可以將這部分省略,得到簡化后的算法。

  1. for i = 2 to n do 
  2. for j = 1 to i − 1 do 
  3. if A[i] < A[j] then 
  4. swap A[i] and A[j] 

該算法減少了比較和交換次數(shù),不過算法復(fù)雜度依然是O(n²)。

網(wǎng)友:這個算法我以前見過

比最容易理解的冒泡算法還要簡單,這個排序算法在Hacker News上很快引起了網(wǎng)友的圍觀。

不少人覺得它“很眼熟”。

有位網(wǎng)友表示,自己曾在奧林匹克數(shù)學(xué)競賽中看到一個同學(xué)用了一種非常奇怪的排序算法,它可以運行但是效率很低,更像是一種插入排序。

如果我沒記錯的話,他用的就是這種算法。

比冒泡算法還簡單的排序算法:看起來滿是bug的程序,居然是對的

事實上,關(guān)于這種算法的討論已久,從2014年開始就不斷有人發(fā)帖,這次作者將論文上傳到arXiv后又引起了廣泛熱議。

比冒泡算法還簡單的排序算法:看起來滿是bug的程序,居然是對的

甚至還有烏龍事件發(fā)生。

有位網(wǎng)友掃了一眼論文就以為這個算法和自己10年前提出的一樣。

留言網(wǎng)友的算法:

比冒泡算法還簡單的排序算法:看起來滿是bug的程序,居然是對的

乍一看兩種算法的代碼確實很像,原理上的確有些相似。

都是看起來像冒泡排序,但其實更貼近選擇排序。

不過很快有人指出真相:這種算法中 j=i+1 to n,并且是當(dāng) A[i] > A[j] 時交換。

而作者提出的算法中 j=1 to n,A[i] < A[j] 時交換。

兩種算法相比,網(wǎng)友此前提出的更容易被理解為什么可以運行。

比冒泡算法還簡單的排序算法:看起來滿是bug的程序,居然是對的

當(dāng)然也有歪樓的,有人就調(diào)侃自己剛學(xué)編程時寫過這個算法。

我百分百確定,在我剛開始學(xué)編程、并想要找到最短的排序方法時就寫過它。

比冒泡算法還簡單的排序算法:看起來滿是bug的程序,居然是對的
[[427441]]

不過說到實際應(yīng)用上,這種算法需要的計算時間太長了。

有人就認(rèn)為,這種算法此前被發(fā)現(xiàn)過很多次,但是那些人根本沒打算用它。

比冒泡算法還簡單的排序算法:看起來滿是bug的程序,居然是對的

也有人提出:這種排序沒有睡眠排序簡單。

比冒泡算法還簡單的排序算法:看起來滿是bug的程序,居然是對的

睡眠排序就是構(gòu)造n個線程,讓線程和排序的n個數(shù)對應(yīng)。

例如對于[4,2,3,5,9]這樣一組數(shù)字,就創(chuàng)建5個線程,每個線程睡眠4s,2s,3s,5s,9s。這些線程睡醒之后,就把自己對應(yīng)的數(shù)報出來即可。這樣等所有線程都醒來,排序就結(jié)束了。

但和作者提出的算法一樣,睡眠排序由于多線程的問題,在真正實現(xiàn)上也有困難

此外,這位網(wǎng)友也表示自己看到過這種算法:

我確定我此前看到過這種算法,它沒有名字嗎?

很快就有人提議說——

如果它沒有名字的話,我建議稱之為“面試排序”。

比冒泡算法還簡單的排序算法:看起來滿是bug的程序,居然是對的
 

 

 

責(zé)任編輯:張燕妮 來源: 量子位
相關(guān)推薦

2021-02-02 13:23:47

Python語言線程

2014-11-07 10:26:05

2023-08-29 08:01:39

2020-06-29 15:00:31

UbuntumacOSLinux

2024-05-20 08:45:46

2019-08-09 10:15:07

程序員項目研發(fā)

2021-01-22 09:11:34

Python多線程CPU

2021-09-29 00:19:10

容器集群k8s

2022-02-28 12:57:09

GNOMEPlasma桌面

2021-10-02 10:36:00

YAML編程語言軟件開發(fā)

2013-12-30 10:06:51

智能硬件3D打印互聯(lián)網(wǎng)化

2016-08-01 11:33:40

云遷移云安全合規(guī)性

2024-03-08 12:20:25

Python代碼

2021-08-02 15:06:46

vim服務(wù)Java

2021-02-27 21:45:22

程序代碼函數(shù)

2025-03-12 10:36:32

2022-02-21 12:05:49

LibreOffiLinux工具欄

2022-03-30 14:23:48

LibreOfficOffice開源

2015-09-06 08:55:54

Java自帶排序算法

2022-01-22 16:25:51

System76桌面應(yīng)用
點贊
收藏

51CTO技術(shù)棧公眾號