我已经写了选择排序的修改后的版本,我认为既是一个数组的最小值和最大值,并将其置于两端
该算法是这样的
1. Find the minimum and the maximum value in the list.
2. Swap the minimum value with the value in the first position.
3. Swap the maximum value with the value in the last position.
4. Repeat the steps above for the remainder of the list
(starting at the second position and ending at the second to
last position and narrowing the range of positions examined
from both ends of the array each time).
不幸的是,上面示出了用于具有重复值的阵列意外的结果。
例如,
[9, 37, 12, 1, 13, 31, 5, 37, 36, 29, 19, 22, 20, 15, -1, 23]
分类到
[-1, 1, 5, 9, 12, 13, 15, 19, 20, 22, 23, 29, 31, 37, 36, 37]
事实上,这里的主要问题是,在一般的算法是不是做在阵列中,后期的元素适当排序除了简单地相对于重复。
这里是我的伪代码
int i=0;
while(i<=(arr.length-i-1)) {
int minIndex = i;
int maxIndex=arr.length-i-1;
for (int j = i+1; j <=arr.length-i-1; j++) {
if (arr[j] <=arr[minIndex]) {
minIndex = j;
}
if(arr[j]>=arr[maxIndex]){
maxIndex = j;
}
}
swap(arr, i, minIndex);
swap(arr, (arr.length-i-1), maxIndex);
i++;
}
编辑这是我的代码交换一部分是与算法交互的唯一的事情。 我不认为这将使任何差别,但无论如何,我会包括它
private static void swap(int[] arr, int oldIndex, int newIndex){
int temp=arr[oldIndex];
arr[oldIndex]=arr[newIndex];
arr[newIndex]=temp;
}
Answer 1:
当问题发生i
正好是maxIndex
。 为了解决这个问题,你需要添加:
swap(arr, i, minIndex);
if(i == maxIndex) {
maxIndex = minIndex;
}
swap(arr, (arr.length-i-1), maxIndex);
看到它@Work
Answer 2:
OK,问题出在哪里最大值在迭代的最低位置开始的情况。 考虑通过你的问题阵列上的第二次循环时:
-1,37,12,1,13,31,5,23,36,29,19,22,20,15,9,37
i为1,LEN-I-1是14循环后,maxindex为1,且minIndex是3。
所以你交换1(i)和3(minIndex):
-1,1,12,37,13,31,5,23,36,29,19,22,20,15,9,37
然后如图14(LEN-I-1)和1(maxIndex):
-1,9,12,37,13,31,5,23,36,29,19,22,20,15,1,37
哎呀。 基本上,你需要同时做两互换。
编辑并行不会真正帮助在两个重叠的掉期的情况下,由于每个互换希望把不同的值在数组槽之一; 你必须解决冲突。 我觉得@ codaddict的解决方案效果很好。
Answer 3:
你必须在内部的for循环的终止条件的差一错误..
for (int j = i+1; j <=arr.length-i-1; j++) {
这应该是一个<
,而不是<=
出于同样的原因你开始i+1
代替i
。
作为一个文体的建议,我也将存储值arr.length - i - 1
在一个变量,因为它显示了在代码的四倍。
编辑 :验证此错误是不是问题的根源。
Answer 4:
我认为你做太多的掉期 - 即你正在做的掉期交易,无论您是否实际上已经找到了新的最低或最高值。 此外,你不需要做两个测试(最小和最大的,因为你不能同时,除了在平等的琐碎情况下,在这种情况下,不要紧,他们出现在了哪些命令......)。
我认为以下是你的算法有更好的表现:
int arrayLength = arr.length;
for (int i=0; i<arrayLength; i++){
for (int j=i+1; j<arrayLength; j++){
int v = arr[j];
if (v < arr[i]){
swap(arr, i, j);
} else if (v > arr[(arrayLength -1)]){
swap(arr, (arrayLength -i-1), j);
}
}
}
但是,你实际上并不需要做的最高值的测试,他们交换到年底,因为这些将全部由搜索最小值被捕获为你做,你通过你的阵列顶级迭代 - 即
int arrayLength = arr.length;
for (int i=0; i<arrayLength; i++){
for (int j=i+1; j<arrayLength; j++){
int v = arr[j];
if (v < arr[i]){
swap(arr, i, j);
}
}
}
会更有效。
编辑:在审查了其他的答案,这种选秀权了对马克·里德的关于做并行互换的答案 - 只是,我会建议你做掉,你已经找到了需要。
Answer 5:
以及在评论中,第一个交换会做的很好,但你的第二个交换,使一个问题。
在这种情况下,当你maxindex变量是位于我,你正确放置你的最低刑期,但失去了你的最大项。 这可以通过添加额外的规定,即检查加以处理if(i==maxterm)
,并且通过使通常首先交换和的最大项其次小项和第二位置交换处理这种特殊情况。 它是无用的您通过您的数组从0遍历array.length-1
我建议,遍历从0到(array.length-1)/ 2,因为你是在两侧排序。 该部已经被归类为是起始部分,为什么要额外迭代? 我写了完全相同的程序与修正,我建议这还检查数量已经排序,并立即终止循环。
文章来源: Selection sort growing ordered ranges from both ends