У меня есть двусвязный список, и я хочу отсортировать пользователей по их 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
Буду признателен за вашу помощь :)
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;
Ответ Аманды показывает один из способов справиться со смежными узлами, но особого случая для обработки смежных и несмежных узлов не требуется, если сначала выполняется замена, меняя местами то, что указывает на два целевых узла, а затем меняй местами указатели внутри двух целевых узлов.
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);
Похожие вопросы
Новые вопросы
c++
C ++ - это язык программирования общего назначения. Первоначально он был разработан как расширение C и имеет аналогичный синтаксис, но теперь это совершенно другой язык. Используйте этот тег для вопросов о коде (который будет скомпилирован с помощью компилятора C ++). Используйте тег, зависящий от версии, для вопросов, связанных с конкретной редакцией стандарта [C ++ 11], [C ++ 14], [C ++ 17] или [C ++ 20] и т. Д.