Я пытаюсь перетасовать связанный список в C
.
Я думаю сделать это, пробежав по всему списку, и для каждого объекта я попытаюсь рандомизировать индекс и поменять местами между ними.
вроде код работает, но через пару раз я запускаю код, кажется, что часть списка исчезла, и иногда меня выкидывают из приложения.
Вот код:
void main() {
Song* head = createSong(1, "aaaa", "aaaa");
Song* song2 = createSong(2, "bbbb", "bbbb");
Song* song3 = createSong(3, "cccc", "cccc");
addSongToTheEndOfTheList(head, song2);
addSongToTheEndOfTheList(head, song3);
printPlaylist(head);
shuffleList(head);
printPlaylist(head);
//freePlaylist(head);
}
int countList(Song* head) {
Song* currentSong = head;
int i = 0;
if (currentSong)
{
while (currentSong->next)
{
currentSong = currentSong->next;
i++;
}
i++;
}
return i;
}
void swapSong(Song* head,Song* Source, int id) {
Song* tempSong = (Song*)malloc(sizeof(Song));
Song* currentSong = head;
while(currentSong && currentSong->id != id){
currentSong = currentSong->next;
}
if (currentSong) {
tempSong->id = currentSong->id;
tempSong->name = currentSong->name;
tempSong->artist = currentSong->artist;
tempSong->next = currentSong->next;
currentSong->id = Source->id;
currentSong->name = Source->name;
currentSong->artist = Source->artist;
currentSong->next = Source->next;
Source->id = tempSong->id;
Source->name = tempSong->name;
Source->artist = tempSong->artist;
Source->next = tempSong->next;
free(tempSong);
}
else {
printf("The list is empty.");
}
}
void shuffleList(Song* head) {
Song* currentSong = head;
int listLength = countList(head);
int randNum;
srand(time(NULL));
if (currentSong) {
for (int i = 1; currentSong;i++) {
swapSong(head, currentSong, rand()%listLength+1);
currentSong = currentSong->next;
}
}
else {
printf("The list is empty.");
}
}
Полный код здесь: https://pastebin.com/fSS3rrTv
Надеюсь, вы поможете мне разобраться. Спасибо!
Также скомпилируйте со всеми включенными предупреждениями, int *id;
, скорее всего, неправильно, вместо этого вы определенно хотите int id;
. И вы, вероятно, хотите char* name[somelength];
вместо char* name;
. Прочтите главы, посвященные строкам, и главу, посвященную указателям, в учебнике по C.
Вы должны поменять местами либо данные или узлы списка (это связность списка); ваш код делает оба. Другими словами, не трогайте next
при обмене.
Ошибка заключается в swapSong
. Есть два возможных способа поменять местами элементы в списке:
next
указателиПервый проще для односвязного списка с небольшим количеством внутренних данных (это ваш вариант использования), второй больше подходит для двусвязных списков.
Здесь просто измените swapSong
на:
void swapSong(Song* head,Song* Source, int id) {
Song* tempSong = (Song*)malloc(sizeof(Song));
Song* currentSong = head;
while(currentSong && currentSong->id != id){
currentSong = currentSong->next;
}
if (currentSong) {
tempSong->id = currentSong->id;
tempSong->name = currentSong->name;
tempSong->artist = currentSong->artist;
//tempSong->next = currentSong->next;
currentSong->id = Source->id;
currentSong->name = Source->name;
currentSong->artist = Source->artist;
//currentSong->next = Source->next;
Source->id = tempSong->id;
Source->name = tempSong->name;
Source->artist = tempSong->artist;
//Source->next = tempSong->next;
free(tempSong);
}
else {
printf("The list is empty.");
}
}
Кстати, в структуре Song
id
объявляется как int *
, а используется как int
. Измените на следующее, чтобы удалить некоторые предупреждения:
typedef struct Song {
int id;
char* name;
char* artist;
struct Song* next;
}Song;
И, как заметил @500-InternalServerError, вам не нужно ничего выделять в swapSong
: просто используйте локальную структуру:
void swapSong(Song* head,Song* Source, int id) {
Song* currentSong = head;
while(currentSong && currentSong->id != id){
currentSong = currentSong->next;
}
if (currentSong) {
Song tempSong = *currentSong;
currentSong->id = Source->id;
currentSong->name = Source->name;
currentSong->artist = Source->artist;
Source->id = tempSong.id;
Source->name = tempSong.name;
Source->artist = tempSong.artist;
}
else {
printf("The list is empty.");
}
}
- конечно, можно еще больше упростить, если tempSong
не будет указателем.
@ 500-InternalServerError: Конечно! Я внес только минимальные изменения, чтобы решить проблему.
@ 500-InternalServerError, как сделать tempSong не указателем? мне нужно выделить память для этого, вы можете показать пример?
Сначала используйте отладчик.