进行气泡排序


19

创建一个需要两个输入的函数或程序:

  • 应当排序的整数列表(少于20个元素)
  • 一个正整数,N表示您应该进行多少次比较

函数将停止,并在N比较后输出结果的整数列表。如果在进行N比较之前对列表进行了完全排序,则应该输出排序后的列表。


冒泡排序算法是众所周知的,我想大多数人都知道它。以下伪代码和动画(均来自链接的Wikipedia-文章)应提供必要的详细信息:

procedure bubbleSort( A : list of sortable items )
   n = length(A)
   repeat 
     swapped = false
     for i = 1 to n-1 inclusive do
       /* if this pair is out of order */
       if A[i-1] > A[i] then    
         /* swap them and remember something changed */
         swap( A[i-1], A[i] )
         swapped = true
       end if
     end for
   until not swapped
end procedure

下面的动画显示了进度:

在此处输入图片说明

一个示例(直接从链接的Wikipedia文章中获取)显示了对列表进行排序的步骤( 5 1 4 2 8 )

首过

1: ( 5 1 4 2 8 ) ->  ( 1 5 4 2 8 ) // Here, algorithm compares the first two elements, 
                                   // and swaps since 5 > 1.
2: ( 1 5 4 2 8 ) ->  ( 1 4 5 2 8 ) // Swap since 5 > 4
3: ( 1 4 5 2 8 ) ->  ( 1 4 2 5 8 ) // Swap since 5 > 2
4: ( 1 4 2 5 8 ) ->  ( 1 4 2 5 8 ) // Now, since these elements are already in order 
                                   // (8 > 5), algorithm does not swap them.

第二关

5: ( 1 4 2 5 8 ) ->  ( 1 4 2 5 8 )
6: ( 1 4 2 5 8 ) ->  ( 1 2 4 5 8 ) // Swap since 4 > 2
7: ( 1 2 4 5 8 ) ->  ( 1 2 4 5 8 )
8: ( 1 2 4 5 8 ) ->  ( 1 2 4 5 8 )

现在,该数组已经排序,但是算法不知道它是否完成。该算法需要一整遍而无需任何交换就可以知道它已被排序。

第三关

9: ( 1 2 4 5 8 ) ->  ( 1 2 4 5 8 )
10:( 1 2 4 5 8 ) ->  ( 1 2 4 5 8 )
11:( 1 2 4 5 8 ) ->  ( 1 2 4 5 8 )
12:( 1 2 4 5 8 ) ->  ( 1 2 4 5 8 )

测试用例:

格式: Number of comparisons (N): List after N comparisons

Input list:
5  1  4  2  8
Test cases: 
1: 1  5  4  2  8
2: 1  4  5  2  8
3: 1  4  2  5  8
4: 1  4  2  5  8
5: 1  4  2  5  8
6: 1  2  4  5  8
10: 1  2  4  5  8
14: 1  2  4  5  8

Input list:
0: 15  18  -6  18   9  -7  -1   7  19  19  -5  20  19   5  15  -5   3  18  14  19
Test cases:
1: 15  18  -6  18   9  -7  -1   7  19  19  -5  20  19   5  15  -5   3  18  14  19
21: -6  15  18   9  -7  -1   7  18  19  -5  19  19   5  15  -5   3  18  14  19  20
41: -6   9  -7  15  -1   7  18  18  -5  19  19   5  15  -5   3  18  14  19  19  20
60: -6  -7  -1   9   7  15  18  -5  18  19   5  15  -5   3  18  14  19  19  19  20
61: -6  -7  -1   7   9  15  18  -5  18  19   5  15  -5   3  18  14  19  19  19  20
81: -7  -6  -1   7   9  15  -5  18  18   5  15  -5   3  18  14  19  19  19  19  20
119: -7  -6  -1  -5   7   9  15   5  15  -5   3  18  14  18  18  19  19  19  19  20
120: -7  -6  -1  -5   7   9  15   5  15  -5   3  18  14  18  18  19  19  19  19  20
121: -7  -6  -1  -5   7   9   5  15  15  -5   3  18  14  18  18  19  19  19  19  20
122: -7  -6  -1  -5   7   9   5  15  15  -5   3  18  14  18  18  19  19  19  19  20
123: -7  -6  -1  -5   7   9   5  15  -5  15   3  18  14  18  18  19  19  19  19  20
201: -7  -6  -5  -1  -5   3   5   7   9  14  15  15  18  18  18  19  19  19  19  20
221: -7  -6  -5  -5  -1   3   5   7   9  14  15  15  18  18  18  19  19  19  19  20

  • 是的,允许使用内置的冒泡排序算法。
  • 不,您不能仅假设正整数或唯一整数。
  • 排序必须按上述顺序进行。您不能从列表末尾开始

2
清晰而合理。遗憾的是,自从我发现了镜像气泡排序的真正绝妙解决方案以来,这篇评论还不太狭窄:)
Ton Hospel

列表会为非空吗?
英里

另外,列表的大小是否大于或等于2?我注意到以下一些答案不适用于长度为1的列表或空列表。
2016年

Answers:


2

果冻,25个字节

ḣ©ṫ-Ṣ®ṖṖ¤;;ṫḊ¥
JḊṁ¹³W¤;ç/

根据我在J中的回答

在线尝试!

验证比较次数。

说明

helper链接[i-1, i]通过对索引进行排序来对列表进行排序,从而产生与气泡排序比较相同的结果。

ḣ©ṫ-Ṣ®ṖṖ¤;;ṫḊ¥  Helper link - Input: list A, index i
ḣ               Take the first i values
 ©              Save a copy of it
  ṫ-            Take the last two values
    Ṣ           Sort them
         ;      Append them to
     ®            Get the copy
      ṖṖ¤         Pop the last two values (Ṗ is pop)
          ;     Prepend it to
           ṫ      Take the last i values
            Ḋ¥    Dequeue - remove the head

JḊṁ¹³W¤;ç/  Input: list A and # of comparisons n
J           Enumerate the indices of A
 Ḋ          Dequeue - remove the head
  ṁ         Reshape it cyclically to length n
   ¹        Identity function (Just to avoid parsing rules)
       ;    Append it to
    ³         The list A
     W¤       Wrap it as an array
        ç/  Reduce from left to right using the helper link and return

9

JavaScript(ES6),102 82 80 86 80字节

借助@ edc65,修复了错误并节省了1个字节

(a,m)=>eval("for(i=0;m;a[j=i-1]>(b=a[i])?a[a[i]=a[j],j]=b:0)1/a[++i]?m--:i=0;a")

递归不一定 绝对不是最好的方法,但是我现在坚持使用循环。

试试看:


我也设法将递归版本降低到82字节:f=(a,m,n=0,_,b=a[n+1])=>b+.5?m?f(a,m-1,n+1,a[n]>b?a[a[n+1]=a[n],n]=b:0):a:f(a,m,0)
尼尔

@Neil Wow,令人印象深刻!如果愿意,可以将其发布为自己的。
ETHproductions 2016年

@Neil您也可以在80中执行递归版本,只需删除最后一个,0
Jonathan Allan

尝试检查1/b而不是b+.5检查undefined
edc65'9

好吧,我对1 / b的建议仍然成立
edc65'9

7

Haskell,83 82 81字节

y%x@(a:b:c)=(y++x):(y++[min a b])%(max a b:c)
y%x=[]%(y++x)
[x]!_=[x] 
x!n=[]%x!!n

用法示例:[5,1,4,2,8] ! 5-> [1,4,2,5,8]

在功能上,% y跟踪当前通过过程中到目前为止访问的元素,x尚待检查。ab在接下来的两个,即考生调剂。如果我们到达列表的末尾,则从头开始:y%x = []%(y++x)。所有步骤都存储在一个列表中,其中主函数选择第nth个元素。

编辑:以前的版本不适用于单个元素列表,幸运的是,新版本更短。


可以在线测试吗?我对Haskell一无所知,尝试将其直接粘贴到在线ide时会出错。我想我缺少一些基本的东西...?
Stewie Griffin

f=在答案的第二行之前添加,然后将第三行添加到包含的程序中main=print(f [5,1,4,2,8] 5)。那应该使其可运行。
林恩

@WeeingIfFirst:完整的程序
NIMI

4

Python 3,77 74字节

@Maltysen(j在声明中初始化),得-3个字节

lambda l,n,j=0:exec('j*=j<len(l)-1;l[j:j+2]=sorted(l[j:j+2]);j+=1;'*n)or l

测试用例在ideone

用于sorted执行每个比较和交换操作,但它正在执行冒泡排序。

设置j=0(左索引),然后执行n比较和交换相邻列表项,j0在此窗口越界时重置为。

j*=j<len(l)-1将成倍jFalse(即0),在这一点上,而所有其他的时间它会乘jTrue(即1)。

(它仍然适用于空列表。)


1
我想你可以通过在拉姆达默认PARAMS除去加和设置J = 0保存
Maltysen

1
另外,您不需要重置j,可以使用%
Maltysen

@Maltysen实际上我不能使用模算术并保存字节,因为我们需要处理长度为1的列表,否则我们将得到零除错误,并添加了逻辑处理以字节为单位。
乔纳森·艾伦

1
对于所有测试用例都可以正常工作,并且比我的MATLAB答案要短很多。+1 =)不幸的是,eval由于内联分配,我无法在MATLAB中使用相同的技术。
Stewie Griffin

1
更新以包括新的测试用例
Jonathan Allan'9

3

PowerShell的V2 +,135个 129字节

param($a,$n)for($s=1;$s){($s=0)..($a.count-2)|%{if($a[$_]-gt$a[$_+1]){$a[$_],$a[$_+1]=$a[$_+1],$a[$_];$s=1}if(!--$n){$a;exit}}}$a

所以。许多。美元。

保存六个字节通过认识到这一挑战不包括“免费”跳过对每遍,因为有保证的排序,而是最后一个元素(一个或多个)的优化贯穿全通各一次。这移动$a.countfor循环并消除$z变量。

将气泡整理整齐,有一个漂亮的位置,一步就进行交换-
$a[$_],$a[$_+1]=$a[$_+1],$a[$_]

退出逻辑通过以下方式处理 if(!--$n){$a;exit}

测试用例

(此处的数组显示为以空格分隔,因为用于对数组进行字符串化的默认“ 输出字段分隔符 ”是一个空格。之所以发生字符串化,是因为我们将其与标签串联在一起"$_ -> "。)

PS C:\Tools\Scripts\golfing> 1,2,3,4,5,6,10,14|%{"$_ -> "+(.\bubble-sorting-in-progress.ps1 @(5,1,4,2,8) $_)}
1 -> 1 5 4 2 8
2 -> 1 4 5 2 8
3 -> 1 4 2 5 8
4 -> 1 4 2 5 8
5 -> 1 4 2 5 8
6 -> 1 2 4 5 8
10 -> 1 2 4 5 8
14 -> 1 2 4 5 8

PS C:\Tools\Scripts\golfing> 1,21,41,60,61,81,119,120,121,122,123,201,221|%{"$_ -> "+(.\bubble-sorting-in-progress.ps1 @(15,18,-6,18,9,-7,-1,7,19,19,-5,20,19,5,15,-5,3,18,14,19) $_)}
1 -> 15 18 -6 18 9 -7 -1 7 19 19 -5 20 19 5 15 -5 3 18 14 19
21 -> -6 15 18 9 -7 -1 7 18 19 -5 19 19 5 15 -5 3 18 14 19 20
41 -> -6 9 -7 15 -1 7 18 18 -5 19 19 5 15 -5 3 18 14 19 19 20
60 -> -6 -7 -1 9 7 15 18 -5 18 19 5 15 -5 3 18 14 19 19 19 20
61 -> -6 -7 -1 7 9 15 18 -5 18 19 5 15 -5 3 18 14 19 19 19 20
81 -> -7 -6 -1 7 9 15 -5 18 18 5 15 -5 3 18 14 19 19 19 19 20
119 -> -7 -6 -1 -5 7 9 15 5 15 -5 3 18 14 18 18 19 19 19 19 20
120 -> -7 -6 -1 -5 7 9 15 5 15 -5 3 18 14 18 18 19 19 19 19 20
121 -> -7 -6 -1 -5 7 9 5 15 15 -5 3 18 14 18 18 19 19 19 19 20
122 -> -7 -6 -1 -5 7 9 5 15 15 -5 3 18 14 18 18 19 19 19 19 20
123 -> -7 -6 -1 -5 7 9 5 15 -5 15 3 18 14 18 18 19 19 19 19 20
201 -> -7 -6 -5 -1 -5 3 5 7 9 14 15 15 18 18 18 19 19 19 19 20
221 -> -7 -6 -5 -5 -1 3 5 7 9 14 15 15 18 18 18 19 19 19 19 20

3

R,132个 131 112 136字节

程序按如下方式接收输入:首先N是向量本身。例如,如果您需要v = [5 1 4 2 8]and n = 1,输入到中的输入scan1 5 1 4 2 8。因此,为了运行此程序,您需要运行第一行在控制台中逐个输入数字然后运行其余的数字(这是REPL的答案)。

然后,下面的代码可以解决问题:

v=scan()
s=m=0
while(!s){s=T;for(i in 3:length(v)){m=m+1
if(m>v[1]){s=T;break}
if(v[i-1]>v[i]){v[c(i-1,i)]=v[c(i,i-1)];s=F}}}
cat(v[-1])

测试:

Input: a vector with N first and the elements to be sorted next
1 5 1 4 2 8
5 5 1 4 2 8
14 5 1 4 2 8
60 15 18 -6 18  9 -7 -1  7 19 19 -5 20 19  5 15 -5  3 18 14 19

Output: 
1 5 4 2 8
1 4 2 5 8
1 2 4 5 8
-6 -7 -1  9  7 15 18 -5 18 19  5 15 -5  3 18 14 19 19 19 20

更新:由于Vlo打高尔夫球1个字节。


2
这似乎需要将输入硬编码为变量,并通过REPL机制隐式显示输出,这是我们可接受的I / O方法列表无法接受的
Mego 2016年

@Mego好的,我已解决该问题。请看看现在是完全兼容...
安德烈KOSTYRKA

看来您可以删除第一个s = T; 仍然有正确的输出;这样可以节省4个字节。编辑:实际上,您可以完全删除while()循环,而只需使用for()循环,用break替换s = T,这也使我们摆脱了一些花括号。这样得出:v = scan(); s = m = 0; for(i in 3:length(v)){m = m + 1; if(m> v [1])break; if(v [i- 1]> v [i]); v [c(i-1,i)] = v [c(i,i-1)]; break}}; v [-1]总共117个字节。
rturnbull

@rturnbull您的版本好多了!恭喜您。
安德烈KOSTYRKA

@rturnbull这些早期评论去了哪里?您建议打高尔夫球距离19个字节...只是删除了必要的额外循环,因为气泡排序的性能为O(n²),而没有该额外循环,则其长度为(n-1)。我应该检查过...现在已修复,其中包含有关如何输入内容的说明!比以前好吗?
安德烈KOSTYRKA


2

JavaScript(ES6),82 80 79字节

f=(a,m,n=0,_,b=a[n+1])=>1/b?m?f(a,m-1,n+1,a[n]>b?a[a[n+1]=a[n],n]=b:0):a:f(a,m)

基于@ETHproduction的原始答案。编辑:感谢@JonathanAllan,节省了2个字节。@ edc65,节省了1个字节。


2

J62 60字节

>@([:({.,(2/:~@{.}.),]}.~2+[)&.>/]|.@;<:@#@]<@|i.@[)^:(]1<#)

这是一个动词,带有两个参数:LHS上的比较数和RHS上的整数列表。首先,它检查列表的长度是否大于一个。如果不是,它将返回未修改的列表,否则将通过在返回结果之前执行指定的比较次数来对其进行操作。

用法

对于第一个测试用例,Extras命令用于格式化多个输入/输出。第二个测试用例显示为单个输入/输出。

   f =: >@([:({.,(2/:~@{.}.),]}.~2+[)&.>/]|.@;<:@#@]<@|i.@[)^:(]1<#)
   1 2 3 4 5 6 10 14 ([;f)"0 1 ] 5 1 4 2 8
┌──┬─────────┐
│1 │1 5 4 2 8│
├──┼─────────┤
│2 │1 4 5 2 8│
├──┼─────────┤
│3 │1 4 2 5 8│
├──┼─────────┤
│4 │1 4 2 5 8│
├──┼─────────┤
│5 │1 4 2 5 8│
├──┼─────────┤
│6 │1 2 4 5 8│
├──┼─────────┤
│10│1 2 4 5 8│
├──┼─────────┤
│14│1 2 4 5 8│
└──┴─────────┘
   1 f 15 18 _6 18 9 _7 _1 7 19 19 _5 20 19 5 15 _5 3 18 14 19
15 18 _6 18 9 _7 _1 7 19 19 _5 20 19 5 15 _5 3 18 14 19
   123 f 15 18 _6 18 9 _7 _1 7 19 19 _5 20 19 5 15 _5 3 18 14 19
_7 _6 _1 _5 7 9 5 15 _5 15 3 18 14 18 18 19 19 19 19 20
   221 f 15 18 _6 18 9 _7 _1 7 19 19 _5 20 19 5 15 _5 3 18 14 19
_7 _6 _5 _5 _1 3 5 7 9 14 15 15 18 18 18 19 19 19 19 20

说明

用可变性用J编写简洁的代码很困难,因此我将问题转换为减少一组索引上的列表。我认为这段代码很凌乱,因此我将逐步介绍每个短语而不是每个原始语言的工作。第一部分获取列表的长度并产生一个范围。然后,对大小为2的每个infix进行操作,以模拟一次比较。

   i. # 5 1 4 2 8
0 1 2 3 4
   2 <\ i. # 5 1 4 2 8
┌───┬───┬───┬───┐
│0 1│1 2│2 3│3 4│
└───┴───┴───┴───┘
   2 <@{.\ i. # 5 1 4 2 8
┌─┬─┬─┬─┐
│0│1│2│3│
└─┴─┴─┴─┘

这些是每个比较的开始指标。如果要进行7次比较,则将其重塑形状以获得所需的数量。J从右到左解析,因此它像从右折叠一样从右到左减小。附加初始列表并将其反转。

   7 $ 2 <@{.\ i. # 5 1 4 2 8
┌─┬─┬─┬─┬─┬─┬─┐
│0│1│2│3│0│1│2│
└─┴─┴─┴─┴─┴─┴─┘
   |. 5 1 4 2 8 ; 7 $ 2 <@{.\ i. # 5 1 4 2 8
┌─┬─┬─┬─┬─┬─┬─┬─────────┐
│2│1│0│3│2│1│0│5 1 4 2 8│
└─┴─┴─┴─┴─┴─┴─┴─────────┘

或者,可以设置范围[0,7),每个值取列表长度减去1的模为模,以创建相同的范围。

   (<: # 5 1 4 2 8) <@| i. 7
┌─┬─┬─┬─┬─┬─┬─┐
│0│1│2│3│0│1│2│
└─┴─┴─┴─┴─┴─┴─┘

最后一部分是动词,它在RHS上有一个列表,在LHS上有一个索引,用于标记比较的起始索引。选择从该索引处开始的两个元素,对它们进行排序,然后将它们重新插入列表并返回。

   > ({.,(2/:~@{.}.),]}.~2+[)&.>/ |. 5 1 4 2 8 ; 7 $ 2 <@{.\ i. # 5 1 4 2 8
1 2 4 5 8

令人印象深刻,令人印象深刻的+1。
Magic Octopus Urn's

1

Matlab,93 91字节

function l=f(l,m)
n=numel(l)-1;i=0;while n&m;i=mod(i,n)+1;m=m-1;l(i:i+1)=sort(l(i:i+1));end

通过省略节省11个字节if l(i)>l(i+1);l(i:i+1)=l([i+1,i]),而是每次仅对两个元素进行排序。适用于长度为1的列表。可以使用Octave的m--运算符保存一个或两个字节,但这并不多。

通过设置保存另外两个字节n=numel(l)-1;,因为那样我就可以while n代替while n>1i=mod(i,n)+1代替i=mod(i,n-1)+1


记录下来,这个挑战是在挑战创建许多小时后写的。


1

Groovy(101字节)

{l,n->(l.size()..0).each{i->(0..i-2).each{if(l[it]>l[it+1] && n>0 && it>-1){l.swap(it,it+1)};n--}};l}

编辑:我不需要编写自己的交换关闭,groovy内置了
它。在这里尝试:https : //groovyconsole.appspot.com/script/5104724189642752

输出跟踪示例:

4:[1, 5, 4, 2, 8]
3:[1, 4, 5, 2, 8]
2:[1, 4, 2, 5, 8]
1:[1, 4, 2, 5, 8]
0:[1, 4, 2, 5, 8] - Locks in the final answer.
-1:[1, 4, 2, 5, 8]
-2 (Return):[1, 4, 2, 5, 8]

旧的实现(122字节)

m={l,n->s={x,y->t=l[x];l[x]=l[y];l[y]=t};((l.size()-2)..2).each{i->(0..i).each{if(l[it]>l[it+1] && n){s(it,it+1)};n--}};l}

在这里尝试:https : //groovyconsole.appspot.com/script/6316871066320896


对于少于两个项目的列表,会出现此错误
Jonathan Allan

在我的手机上...在第二条if语句中添加> = 0即可解决该问题。
魔术章鱼缸

对于带有负输入的列表,它似乎也失败了。例如第二个测试用例。
Stewie Griffin

现在可以工作了,昨晚我在移动设备上,所以无法进行所需的编辑。
魔术章鱼缸

1

php,148145字节

<?php for($i=2,$a=$argv;$a[1]--;$i=$i==count($a)-2?2:$i+1)if($a[$i]>$a[$i+1])list($a[$i],$a[$i+1])=[$a[$i+1],$a[$i]];echo substr(join(' ',$a),5);

我对循环结构不是很满意,但是我喜欢列表开关,它确实起作用,所以无论如何我都会发布它。php7.1将允许我至少保存4个字节。

使用更好的格式:

<?php 
for($i=2,$a=$argv;$a[1]--;$i=$i==count($a)-2?2:$i+1)
  if($a[$i]>$a[$i+1])
    list($a[$i],$a[$i+1])=[$a[$i+1],$a[$i]];
echo substr(join(' ',$a),5);

编辑:JörgHülsermann提醒我加入,而不是内向。
注意:必须位于具有单个字符文件名的文件中。



$ t = $ a [$ i]; $ a [$ i] = $ a [$ i + 1]; $ a [$ i + 1] = $ t; 比list($ a [$ i],$ a [$ i + 1])= [$ a [$ i + 1],$ a [$ i]]短;而且我不确定是否代替echo echo substr(implode('',$ a),5); 这一个$ a [1] = null; echo join('',$ a); 更好的选择是。
约尔格Hülsermann

1
虽然使用临时变量要短2个字节,但它也是多个语句,因此您需要使用这2个字节将整个内容括在花括号中。对于$ a [1] = null,您实际上需要取消设置($ a [0],$ a [1])以避免空格和开头的文件名。
user59178'9

1

Ruby,52个 50字节

等等...没有露比吗?

->l,n{n.times{|a|l[s=a%~-l.size,2]=l[s,2].sort};l}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.