我有点难以理解书中的以下脚本:
values=(39 5 36 12 9 3 2 30 4 18 22 1 28 25)
numvalues=${#values[@]}
for (( i=0; i < numvalues; i++ )); do
lowest=$i
for (( j=i; j < numvalues; j++ )); do
if [ ${values[j]} -le ${values[$lowest]} ]; then
lowest=$j
fi
done
temp=${values[i]}
values[i]=${values[lowest]}
values[lowest]=$temp
done
for (( i=0; i < numvalues; i++ )); do
echo -ne "${values[$i]}\t"
done
echo
该脚本对数组中的数字执行选择排序,并最终按正确的数字顺序对它们进行排序。据书中所述:
外部的 i for 循环用于循环整个数组并指向当前的“头”(我们在其中放置需要交换的任何值)。变量 low 被设置为此索引。
我理解这部分,我猜第一次迭代的最低值将是索引 0,值 39。
我很难理解内部 j 循环是如何工作的。书上说:
它将剩余元素与最低值进行比较;如果值小于最低值,则设置为该元素的索引。
我无法理解 的值j
与 的值有什么不同i
。在我看来,如果j=i
,在第一次迭代 0 上,那么j
也等于 0。我想这必须在第二次和后续迭代中改变。我知道 的值j
必须与 的值不同i
,因为这是[ ${values[j]} -le ${values[$lowest]} ]
脚本部分正在计算的值。
这是否因为内部 for 循环的j=i
后续部分而起作用?j++
如果j=i
,并且在第二次迭代中如果i=1
,这是否意味着j++
等于 2?
新评论:
进一步思考这个脚本。我可以看到 j=i+1 在内循环中如何工作。在第一次迭代中,i 为 0,j 为 1,因此这将比较第一个和第二个元素的值。在进一步的迭代中,i=1 和 j=2、i=2 和 j=3 等等……。
然而,在编写的脚本中我不太明白它是如何工作的。第一次迭代时 i=0 且 j=0。因此数组中的第一个值与其自身进行比较。当然,在第二次迭代中 i=1 且 j=2,因此这将比较第二个和第三个值。我看不到索引 0 与索引 1 是如何比较的。 39 与 5 进行比较。当然,第二次迭代会跳过这一点,因为它将 5 与 36 进行比较。
答案1
在我看来,如果 j=i,即第一次迭代 0,那么 j 也等于 0。
正确的是,对于内部循环的每次第一次迭代,j
将等于i
。
我想这必须在第二次和后续迭代中改变。
也是正确的(对于内循环)。对于内部循环的第一次迭代,将具有外部循环的该迭代中保留的j
任何值。i
我知道 的值
j
必须与 的值不同i
,因为这是[ ${values[j]} -le ${values[$lowest]} ]
脚本部分正在计算的值。
从(内循环的)第二次迭代开始。
如果
j=i
,并且在第二次迭代中如果i=1
,这是否意味着j++
等于 2?
对于内部循环1的第二次迭代也是正确的。
现在,对于内部循环的每次第一次迭代,i
、j
和lowest
都是相同的。为什么?lowest
已经设置为i
.在迭代开始时j
设置为,随后的测试将设置为,即,因为它正在比较相同的元素。因此,该内部循环的第一次迭代是毫无意义的,它可以毫无问题地开始。然而,这并不是一个错误,只是没有必要。i
lowest
j
i
i+1
1从技术上讲,j++
将是1
,而不是两个,因为++
在变量之后,称为 a后增量运算符,在对表达式计算变量后增加值。j
将是 2后表达式已被求值。
答案2
那个内部循环for (( j=i; j < ...
似乎有问题,相比之下“算法”(第四版,Sedgewick & Wayne)使用:
for (int j = i+1; j < ...
对于他们的选择排序示例。