【问题标题】:Shuffle linked list in c with pointers用指针在c中洗牌链表
【发布时间】:2019-05-29 12:22:04
【问题描述】:

我正在尝试对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

标签: c pointers linked-list shuffle


【解决方案1】:

错误在于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 不作为指针?我需要为此分配内存,你能举个例子吗?
猜你喜欢
  • 2015-06-30
  • 2016-03-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-07-28
  • 1970-01-01
相关资源
最近更新 更多