我有一个作业,必须使用以下参数“改进” SelectionSort:
好的,到目前为止,我已经编写了以下c ++代码:
#include <iostream>
#include <array>
#include <string>
using namespace std;
int main()
{
int min, min2;
// doesn't work
array<int, 9> list = { 97,34,15,25,27,4,19,41,68 };
/* this one works:
array<int, 10> list = { 4,8,1,3,10,6,5,7,9,2 };
*/
// First loop
for (int i = 0; i < list.size(); i+=2) {
min = i;
min2 = i + 1;
// 2nd Loop for searching the smallest elements
for (int j = i + 2; j < list.size(); j++) {
if (list.at(j) < list.at(min)) {
min = j;
}
// outer if -> stop before out of array
if (j+1 < list.size()) {
if (list.at(j+1) < list.at(min2)) {
min2 = j+1;
}
}
}
swap(list.at(i), list.at(min));
// Prevent out of array error
if (i + 1 < list.size()) {
swap(list.at(i+1), list.at(min2));
}
}
cout << '\n' << '\n';
cout << "Sorted list: " << endl;
for (int elem : list) {
cout << elem << ", ";
}
}
当然是排序,这就是结果...但不是我希望的结果:
4、97、15、19、25、34、27、41、68,
我没主意了,唯一的提示是:“没有第三回合”。
我将不胜感激:-)
编辑:
由于要举行投票,我试图指出问题所在。 当我使用高int值(例如代码中的int值)时,排序算法无法正常工作
array<int, 9> list = { 97,34,15,25,27,4,19,41,68 };
4, 97, 15, 19, 25, 34, 27, 41, 68,
如您所见,第一个if语句中位置0、2、4、6、8的值已正确排序,而其他两个则未形成第二个if语句。
例如,当我将int值更改为1-10的值并将它们随机混合时,该算法似乎正常工作(感谢评论!):
array<int, 10> list = { 4,8,1,3,10,6,5,7,9,2 };
1, 2, 4, 3, 5, 6, 8, 7, 9, 10,
我没主意-是编程错误还是算法错误?
编辑3: 这是我的(最终工作的)更新代码:
//array<int, 10> list = { 4,8,1,3,10,6,5,7,9,2 };
//array<int, 4> list = { 97,15,25,18 };
//array<int, 2> list = { 97,18 };
array<int, 3> list = { 4,5,3 };
// First loop
for (int i = 0; i < list.size(); i+=2) {
if (i == list.size() - 1) {
break;
}
min = i;
min2 = i + 1;
// Enforce that list.at(min) <= list.at(min2) -> Sorting pivot (element) for the algorithm to smallest, 2nd smallest.
if (list.at(min) > list.at(min2)) {
swap(list.at(min), list.at(min2));
}
// Second Loop
for (int j = i + 2; j < list.size(); ++j) {
if (list.at(j) < list.at(min)) {
min2 = min; // min2 points now on the 2nd smallest element
min = j; // min points now on the smallest element
}
else if (list.at(j) < list.at(min2)) {
min2 = j;
}
}
// Swapping the elements in the right position.
swap(list.at(i + 1), list.at(min2));
swap(list.at(i), list.at(min));
}
结果:
{4,8,1,3,10,6,5,7,9,2}-> 1,2,3,4,5,6,7,8,9,10
{97,15,25,18}-> 15,18,25,97,
{97,18}-> 18,97,
{4,5,3}-> 3,4,5,
答案 0 :(得分:0)
尝试使用数组[97,18]
进行程序。我认为您会发现它不起作用,因为从未输入过第二个循环,并且第一个循环结尾的行也不会交换任何内容。
当我在评论中说min
必须小于或等于min2
时,我的意思是说您必须确保list.at(min) <= list.at(min2)
。我上面的2个项目数组的示例说明了为什么这样做很重要。
实施该方法的方法是修改您的第一个循环:
// First loop
for (int i = 0; i < list.size(); i+=2) {
if (i == list.size()-1) {
// There is an odd number of items in the list.
// At this point, we know that the last item is in place.
// So just exit.
break;
}
min = i;
min2 = i + 1;
// enforce list(min) <= list(min2)
if (list.at(min) > list.at(min2)) {
swap(list.at(min), list.at(min2));
}
// second loop
是的,必须在内部循环中保持该状态。如果尝试使用数组[4,5,3]
,结果将是[3,5,4]
。
这主要是因为在您的内部循环中,当您发现list.at(j) < list.at(min)
时便交换了项目。但是当list.at(min2) > list.at(min)
时,您要做的就是乱码交换。
您应该使用3元素列表在调试器中单步执行代码,以了解正在发生的事情。如果您不知道如何使用调试器,请立即停止学习。当您可以观看代码的逐行执行时,很容易发现这种类型的编程错误。另一种方法是手工完成:用一支纸笔和一支铅笔,一步一步地遍历代码,将更改记入每个变量。
内循环的另一个问题是您正在使用list.at(j+1)
检查list.at(min2)
。但是您每次仅将j
递增1,因此最终需要做更多的工作。没有理由进行额外检查。下次将通过循环进行处理。
假设您在min
和min2
之间保持适当的关系,则内循环中的修复很容易。如果为list.at(j) < list.at(min)
,则设置min2=min
(因为min
现在指向第二小的项目),并设置min=j
。如果为list.at(j) < list.at(min2)
,则只需设置min2=j
。代码如下:
for (j = i+2; j < list.size(); ++j) {
if (list.at(j) < list.at(min)) {
min2 = min;
min = j;
} else if (list.at(j) < list.at(min2)) {
min2 = j;
}
}
现在,您的代码在外部循环的末尾可以正常工作。
使用数组[4,5,3]
在调试器中运行程序。在内部循环之后的行上放置一个断点,这里:
swap(list.at(i), list.at(min));
如果检查数组,您会发现它仍然是[4,5,3]
。但是请看min
和min2
。您会看到min=2
和min2=0
。 i
等于0
。现在,当您在list[i]
和list[min]
交换项目时会发生什么?您得到[3,5,4]
,并且min2
不再指向第二小的项目。
在几种不同的情况下,可能会发生这种情况。您必须考虑这些条件并加以处理。我提供的代码可让您找到最小和第二小的项目。但是,找到它们后,您必须弄清楚如何将它们交换到正确的位置。