Попробуйте свою программу с массивом [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
больше не указывает на второй наименьший элемент.
Существует несколько различных условий, в которых может произойти нечто подобное.Вы должны думать об этих условиях и справляться с ними.Код, который я предоставил, позволяет вам найти самые маленькие и вторые самые маленькие предметы.Но вы должны выяснить, как поменять вещи в нужных местах после того, как вы их нашли.