给定数组
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行,可以打开蒙住眼睛。
我想到了我听说过的排序算法......我知道它不是什么。冒泡排序很长,并且多次扫描,所以绝对不是那样.. mergesort和quicksort涉及递归,所以不是这样。而且我认为它是插入排序或选择排序。但是在维基百科上看它们,它们似乎都没有那么小......
我明白它是如何运作的。从数组的排序部分右侧的i向前扫描,查找具有[i]然后下一个最小的第一个最小交换并交换它,因此a [i]然后包含未排序和i ++中的最小值
维基百科上有一个插入排序,它有更多行,可能相似但似乎有不同的逻辑&#39;
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!
并且把我的失败放在我的蹩脚企图中,在wikipedia上为插入排序制作排序算法,就像我的那样简洁,结构相似......
它告诉我它本质上是不同的。所以如果我在开始时给出的3行算法不是inserion sort,那么它是什么..为什么它与它不同一个在维基百科上,内循环正在计算另一种方式,它没有进入等效的3行,这告诉我算法背后的逻辑也有点不同。
我看到维基百科上的选择排序看起来也不是很简洁。所以我确定我的算法不是那样的。
我看到维基百科上的插入排序是如何工作的......它递增了i,将元素添加到排序部分,然后从右到左扫描排序部分,第一个最大项目&gt; a [i](也是排序部分中最大的),与[i]交换所以现在再次从0..i开始排序和i ++。但这种逻辑完全不同。通过排序部分向下计数与通过未排序部分计数完全不同。而且我可以看到维基百科是如何非常有效的,当它在内循环中交换时会破坏,这比我可能进行多次交换以使排序部分增加一个的效率更高。
所以我猜我的问题是......我的名字是什么?我不会称它为废话,因为它在线条方面非常简洁。我认为它必须有一个正确的名称。他们甚至给泡沫起了一个名字,而且效率不高。
维基百科的插入排序可以简洁地形成(或简洁),就像我做的那样吗?
修订
moreon发现了一个拼写错误,我完成i<a.length-1
现在已经修改为i<a.length
或i<=a.length-1
,因为它显然应该是,所以现在插入排序的3行低效版本作品。我已经制作了一个高效简洁的版本,请参阅我的回答。
答案 0 :(得分:4)
double for循环暗示它是O(N ^ 2)运行时间。这是老式的selection sort。最里面的三个语句(a [j-1] ...)是执行交换的一种方式。
除了有趣之外,我一般会建议不要使用此代码。几乎任何语言都在其标准库中具有更快的排序例程。此外,通过加/减来进行交换是不必要的,并且减少了允许的整数范围(由于溢出)。
答案 1 :(得分:3)
它实际上是一种编码不佳的选择类型。第i次传递从子阵列a [i..n-1]中选择最小元素,并将其置于[i]中,用于i = 0 ... n-1。 (最后一遍考虑的是一个零长度的子阵列,什么都不做。)它只是通过大量无用的交换找到了最小值。
交换本身是一个避免使用临时变量的老技巧。大多数时候你会看到XOR作为操作,但减法也可以。实际上,在几乎所有情况下使用temp都会更有效。
大多数O(n ^ 2)种类的愚蠢变异相当于重新调整循环。插入排序是:
for (i = 1; i < n; i++)
for (j = i; j > 0; j--)
if (a[j] < a[j-1]) swap(a[j], a[j-1])
这是愚蠢的,因为虽然它最终会在排序的子阵列a [0..i-1]中的正确位置插入第i个元素时停止,但它仍然继续。它也是交换而不仅仅是向上移动元素,这是一种“真正的”插入排序。
答案 2 :(得分:0)
插入排序可以高效且简洁
插入排序
for(i=1;i<a.length;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]} else break;
插入排序涉及并且必须涉及多次交换,将所有较大的数字向右移动,方法是将新数字与其邻居连续交换,直到它按顺序排列。请参阅此图以获得解释“算法第2课:插入排序”https://www.youtube.com/watch?v=c4BRHC7kTaQ
的图表选择排序https://www.youtube.com/watch?v=6nDMgr0-Yyo不应该使用多次交换,这是非常低效的。它应该找到未分类的最小索引并进行一次交换。你可以用4行+大括号
来做你不能在这里做a+=b
b=a-b
a-=b
,因为在那里i == minius你用一个[i]“交换”一个[i]一个临时变量,但是使用算术黑客你得到一个[i] == 0还有人指出,如果你的数字接近数据类型的限制,例如对于int,然后加和减可能导致溢出。
选择排序
// minius是未分类/未放置的最小索引
for(i=0;i<a.length;i++)
{
minius=i; // min index in unsorted/unplaced
for(j=i+1;j<a.length;j++) if(a[minius]>a[j]) minius=j;
temp=a[i]; a[i]=a[minius]; a[minius]=temp;
}