У меня есть двусвязный список, и я хочу отсортировать пользователей по их ELO.

Проблема в том, что при вызове функции swap () некоторые пользователи исчезают

Вот что я получаю в своей консоли: https://imgur.com/a/pJSPSnW

Как видите, первый обмен (между игроками 1 и 2) сделан правильно. Но когда он меняет местами игроков 3 и 4, пользователь1 исчезает.

Я думаю, что проблема заключается в функции swap (), но я не могу понять, где именно

Код: объявление пользователя / узла

struct user {
public:
    string username;
    float ELO = NULL; //Score of the user       
    user* next = nullptr;
    user* previous = nullptr;
};

Быстрая сортировка рекурсивная функция

 void ELOManager::_quickSortRecursive(user* low, user* high) {
    if (high != nullptr && low != high && low != nullptr) {
        user* p = partition(low, high);
        _quickSortRecursive(low, p->previous);
        _quickSortRecursive(p->next, high);
    }
}

Функция быстрой сортировки

void ELOManager::quickSort(){
    _quickSortRecursive(first, last);
}

Функция разделения

    user* ELOManager::partition(user* low, user* high) {
    float pivot = high->ELO;

    user* i = low->previous;

    for (user* j = low; j != high && j!=nullptr; j = j->next) {
        if (j->ELO <= pivot){
            i = (i == NULL) ? low : i->next;

            swap(i, j);
        }
    }
    //i = (i == NULL) ? low : i->next;
    swap(i->next, high);
    cout << endl << "Loop finished -----------------------" << endl;
    printUsers();
    return i;
}

Функция своп

    void ELOManager::swap(user* A, user* B) {
    user* tmp = new user();
    user* swapperVector[4];

    cout << endl << "swap1[" << A->username << "]" << endl;
    cout << "swap2[" << B->username << "]" << endl;

    if (A == B) {
        cout << "Same Users: Continue" << endl;
        return;
    }   

    swapperVector[0] = A->previous;
    swapperVector[1] = B->previous;
    swapperVector[2] = A->next;
    swapperVector[3] = B->next; 

    if (areTheyNeighbours(A, B)) {
        A->previous->next = B;
        A->next->previous = B;
        B->previous->next = A;
        B->next->previous = A;


        A->previous = B;
        B->previous = swapperVector[1];
        A->next = swapperVector[3];
        B->next = A;    
        cout << endl << "Option 1" << endl;
    }
    else {
        A->previous = swapperVector[1];
        B->previous = swapperVector[0];
        A->next = swapperVector[3];
        B->next = swapperVector[2];

        A->previous->next = B;
        A->next->previous = B;
        B->previous->next = A;
        B->next->previous = A;
        cout << endl << "Option 2" << endl;
    }

    cout <<"Print list after swap" << endl << "-----" << endl;
    printUsers();
}

Не стесняйтесь, чтобы войти в GitHub моего проекта https://github.com/pablogalve/ELO-System

Буду признателен за вашу помощь :)

0
eduinvestor 28 Май 2019 в 17:10

2 ответа

Лучший ответ

В вашем блоке if (areTheyNeighbors(A, B)) указатели на связанный список в конечном итоге выглядят так: указатели Заметь:

  • Оба указателя B направлены на A
  • И A, и A->next считают B своим предыдущим элементом списка.

Это вызывает многочисленные проблемы при обходе списка и может быть причиной того, что первый элемент в списке теряется.

Если A и B являются соседями, это должно поменять их местами.

A->previous = B;
B->previous = swapperVector[0];
A->next = swapperVector[3];
B->next = A;
1
Amanda 28 Май 2019 в 14:51

Ответ Аманды показывает один из способов справиться со смежными узлами, но особого случая для обработки смежных и несмежных узлов не требуется, если сначала выполняется замена, меняя местами то, что указывает на два целевых узла, а затем меняй местами указатели внутри двух целевых узлов.

    AP = A->previous;
    BP = B->previous;
    AN = A->next;
    BN = B->next;
    std::swap(AN->previous, BN->previous);
    std::swap(AP->next, BP->next);
    std::swap(A->previous, B->previous);
    std::swap(A->next, B->next);
1
rcgldr 28 Май 2019 в 14:55