【发布时间】:2022-01-19 14:26:33
【问题描述】:
给定数组
a=[4,6,9,3,1,5,9,1,4,2,8]
[4, 6, 9, 3, 1, 5, 9, 1, 4, 2, 8]
排序算法
请注意,以防有人不知道。要交换 2 个数字 'a' 和 'b',您可以执行 a=a+b b=a-b a=a-b (也可以使用 * 或 / 来完成)。
for(i=0;i<a.length;i++)
for(j=i+1;j<a.length;j++)
if(a[i]>a[j]) {a[i]=a[i]+a[j]; a[j]=a[i]-a[j]; a[i]=a[i]-a[j]; }
或更简洁,使用 += 和 -=
for(i=0;i<a.length;i++)
for(j=i+1;j<a.length;j++)
if(a[i]>a[j]) {a[i]+=a[j]; a[j]=a[i]-a[j]; a[i]-=a[j]; }
结果数组
[1, 1, 2, 3, 4, 4, 5, 6, 8, 9, 9]
所以它工作,在 C 和 javascript 控制台中测试。我看到有人用 C 语言从他的头脑中做到这一点,我对此感到震惊,因为当我做排序算法时,我记得它们是你研究的棘手的东西,然后你可以从头到尾知道,写下数学陈述来描述它是如何工作的,不要不要记住它,然后忘记它或查找它或使用第三方。但这是一个简单的 3 行,可以蒙着眼睛输入。
我想到了我听说过的排序算法。我知道它不是什么。冒泡排序是冗长的,并且会扫描多次,所以绝对不是那样。合并排序和快速排序涉及递归,所以不是那样的。我认为它要么是插入排序,要么是选择排序。但是在维基百科上看它们,它们看起来都没有那么小……
我了解它的工作原理。从数组的已排序部分右侧的 i 向前扫描,查找与 a[i] 的第一个最小交换然后是下一个最小的交换并交换它,因此 a[i] 然后包含未排序和 i++ 中的最小
维基百科上有一个用于插入排序的,它有更多的行,可能相似,但似乎有不同的“逻辑”
for i = 1 to length(A) - 1
x = A[i]
j = i
while j > 0 and A[j-1] > x
A[j] = A[j-1]
j = j - 1
end while
A[j] = x
end for
它看起来一点也不简洁(尽管也许可以做到这一点),并且内部循环倒计时而不是倒计时。
或(仍在维基百科插入排序页面上)
for i ← 1 to length(A) - 1
j ← i
while j > 0 and A[j-1] > A[j]
swap A[j] and A[j-1]
j ← j - 1
end while
end for
我试图制作一个简洁的表格(部分是为了测试逻辑有多相似),但它没有这样做
a=[4,6,9,3,1,5,9,1,4,2,8]
for(i=1;i<a.length-1;i++)
for(j=i;j>0;j--)
if(a[j-1]>a[j]) {a[j-1]+=a[j]; a[j]=a[j-1]-a[j]; a[j-1]-=a[j]; }
生产
[1, 1, 2, 3, 4, 4, 5, 6, 9, 9, 8] <-- spot the 8 at the end!
抛开我的失败尝试使维基百科上的插入排序算法与我所拥有的算法一样简洁,并且结构相似..
这表明它本质上是不同的。所以如果我一开始给出的 3 行算法不是插入排序,那么它是什么......为什么它与维基百科上的不同,内部循环以另一种方式计数,它不会进入等效的 3 行,这告诉我算法背后的逻辑也有点不同。
我看到维基百科上的选择排序看起来也不是很简洁。所以我确定我的算法不是那样的。
我看到了 wikipedia 上的插入排序是如何工作的。它递增 i,将元素添加到已排序的部分,然后从右到左向下扫描已排序的部分,以及第一个最大的项目 > a[i](那是也是排序部分中最大的),与 a[i] 交换所以现在再次对 0..i 中的所有内容进行排序和 i++。但这个逻辑是完全不同的。通过排序部分向下计数与通过未排序部分向上计数是完全不同的。而且我可以看到维基百科的效率很高,当它在内部循环中交换时会中断,这比我的效率更高,因为它可能会进行多次交换以将排序部分增加一。
所以我想我的问题是......我的名字是什么?我不会称它为垃圾排序,因为它在线条方面非常简洁......我认为它必须有一个正确的名称。他们甚至给冒泡排序起了个名字,但效率并不高。
wikipedia 插入排序能否像我所做的那样在行方面变得简洁..(或接近简洁)?
修正
moreon 发现了一个错字,我将 i<a.length-1 现在修改为 i<a.length 或 i<=a.length-1 显然应该如此,所以现在插入排序的 3 行低效版本有效。不过,我已经制作了一个高效简洁的版本,请参阅我的答案。
【问题讨论】:
-
“冒泡排序是冗长的,并且会扫描多次,所以绝对不是那样”。是什么让您认为冒泡排序“啰嗦”?是什么让你认为这个算法不会扫描多次?
-
如果你修复' for(i=1;i
-
@moreON 没有该算法的
i=1也在维基百科中(如我从那里的粘贴中所示),否则当它执行 j=i 并查看 a[j-1] 它时d 查看 a[-1] 并失败。 -
@barlop 那行有问题,只是那部分没有问题。我之前的评论中有提示。
-
@moreON 啊