Advanced SelectionSort - поиск двух элементов за одну итерацию - PullRequest
0 голосов
/ 13 октября 2018

У меня есть домашнее задание, в котором я должен «улучшить» SelectionSort со следующими параметрами:

  • Сортировка указанного списка с «улучшенной» SelectionSort
  • За одну итерацию,найти самый маленький и второй самый маленький элемент
  • Привести самый маленький и второй самый маленький элемент в правильное положение.1013 * Конечно, это сортировка, и это результат ... но не тот, на который я надеялся:

    4, 97, 15, 19, 25, 34, 27, 41, 68,

    У меня нет идей, и единственная подсказка, которую я получил, была: «нет третьего цикла».

    Буду признателен за любую помощь: -)

    РЕДАКТИРОВАТЬ:

    В связи с продолжением голосования я пытаюсь уточнить проблему.Когда я использую высокие значения int, например, те, что в коде, алгоритм сортировки не работает должным образом

    • Список: array<int, 9> list = { 97,34,15,25,27,4,19,41,68 };
    • Результат: 4, 97, 15, 19, 25, 34, 27, 41, 68,

    Как вы можете видеть, значения в позиции 0, 2, 4, 6, 8 из первого оператора if были отсортированы правильно, но остальные образуют 2-й оператор 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

1 Ответ

0 голосов
/ 15 октября 2018

Попробуйте свою программу с массивом [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 больше не указывает на второй наименьший элемент.

Существует несколько различных условий, в которых может произойти нечто подобное.Вы должны думать об этих условиях и справляться с ними.Код, который я предоставил, позволяет вам найти самые маленькие и вторые самые маленькие предметы.Но вы должны выяснить, как поменять вещи в нужных местах после того, как вы их нашли.

...