交换链表中的元素

Posted

技术标签:

【中文标题】交换链表中的元素【英文标题】:Swapping elements in a linked list 【发布时间】:2022-01-07 21:41:35 【问题描述】:

所以我的排序功能遇到了一点问题。 虽然它在第二个边缘情况下做它应该做的事情, 元素被交换,然后不断交换回来。

这里的例子发生在 Sven(25) 和 Bob(22) 相遇时。

void sortPerson(person *pers, person* newPerson)

    if(pers == NULL || pers->next == NULL)
    
        printf("List is emtpy");
        return;
    
    person* tempValue;
    person* prev = pers;
    person* curr = pers->next;
    //person* newValue = pers;

    while(prev != NULL && curr != NULL)
    
        //first edge case
        //adds a new person
        if(prev->age < newPerson->age)
        
            newPerson->next = prev->next;
            prev->next = newPerson;
               
        
        //second edge case
        //swapping process when prev age greater than curr age
        //forming a decending order of ages
        if(prev->age > curr->age)
        
            tempValue = prev; 
            prev = prev->next; 
            prev->next = tempValue; 

            printf("\nPerson age: %d\n", tempValue->age);
            printf("loop test\n");
            printf("%d and %d\n",prev->age, prev->next->age);
        
        //third edge case
        //if age is the same do nothing
        if(prev->age == curr->age)
        
            return;
        
        prev = prev->next;
        curr = curr->next;  
        
    

这个函数返回一个新人

person* addPerson( person *newPers )
    return newPers;

如果你想自己测试,这里是我的主要内容

int main()
    person* person1 = construct_person("Max", 20);
    person* person2 = construct_person("Sven", 25);
    person* person3 = construct_person("Bob", 22);
    person* person4 = construct_person("John", 23);
    person* newPerson = construct_person("Markus", 21);

    person1->next = person2;
    person2->next = person3;
    person3->next = person4;
    //person4->next = addPerson(person1, newPerson);
    

   
    //swapPerson(person1);
    sortPerson(person1, addPerson(newPerson));
    printperson(person1);

    free(person1);
    free(person2);
    free(person3);
    free(person4);
    free(newPerson);


我的结构人和构造函数

typedef struct person person;
struct person
    char *name;
    int age;
    person *next;
;

person* construct_person(char *name, int age)

    person* pers = (person*) malloc (sizeof(person));
    pers->name = name;
    pers->age = age;
    pers->next = NULL;
    return pers;

我怀疑问题是我的“prev”结构指针在整个过程中被改变了,但我想要第二个意见和潜在的修复。

*注意我只是像这样释放它,因为这只是测试,我不会添加更多的人,否则我会重复这样做。

【问题讨论】:

与其交换prevcurr 节点本身,为什么不交换它们的内容(即节点内的数据)? 因为例如,如果我创建更大的对象,我必须将它们一个一个地切换出来,对吗?例如,如果我有姓名、年龄、地址、身份证等。或者有没有办法捆绑它们? 如果从数据中抽象出列表和节点结构,这可能是最简单的。因此,如果一个节点有一个指向 person 结构而不是 person 结构的指针,那将非常简单(简单的初始化和结构对象的分配)。 除此之外,我建议您使用调试器逐语句逐句执行代码,同时使用铅笔和纸绘制列表以及您对其执行的操作。使用框作为节点,使用箭头作为指针(包括next 链接)。当您修改指针或链接时,请擦除箭头并重新绘制它。如果你喜欢这样,当你看到纸上的视觉表示时,所做的操作是否有意义?在编写代码之前,使用铅笔和纸也是开始试验的好方法。把它写在纸上,然后翻译成代码。 你应该发布construct_personperson 【参考方案1】:

一些备注:

名称sortPerson 选择不当。最好命名为insertPerson 您不能希望仅通过一次迭代和在该迭代期间的各处交换来对列表进行排序。如果可能的话,您将发明最有效的排序算法。所以,这行不通——至少并非总是如此。 不要实现某种排序算法(如冒泡排序、选择排序……),请确保使用 insertPerson 函数添加 所有 人。这样,您可以确定插入新人的列表 into 已经排序。这样,您根本不必交换元素。您只需找到正确的插入点并将新人插入那里。所以在主程序中你不应该摆弄next 指针。把它留给这个 insertPerson 函数。 当列表为空或只有一个人时,您仍应插入新人。当列表为空(或只有一个元素)时,不这样做是没有意义的。 唯一的基本情况是当您需要在所有其他人之前插入人。在这种情况下,对第一人称的引用需要改变,因为新人成为第一人称。实现该工作的一种方法是使第一个参数成为引用调用。换句话说:传递存储第一人称指针的地址,以便可以更改此指针,调用者将有权访问该更改。 当新人的年龄与列表中已有人的年龄相匹配时,我看不到忽略插入的逻辑。当然,您的名单应该允许 Bob 和 Alice,即使他们都是 28 岁。 还有其他几点需要说明...

这是一个工作版本。我不得不对你没有分享的代码做一些假设,但即使你的代码不同,原则也应该很清楚:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct person_s 
    int age;
    char name[100];
    struct person_s * next;
 person;

person* construct_person(char* name, int age) 
    person* p = malloc(sizeof(person));
    strcpy(p->name, name);
    p->age = age;
    p->next = NULL;
    return p;
;

void insertPerson(person** youngest, char* name, int age)

    person* newPerson = construct_person(name, age);
    // Even when list is empty, still add it
    if (*youngest == NULL || (*youngest)->age > age) 
        newPerson->next = *youngest;
        *youngest = newPerson;
        return;
    
    person* prev = *youngest;
    person* curr = prev->next;
    // Search insertion point
    while (curr != NULL && curr->age < age) 
        prev = curr;
        curr = curr->next;
    
    // Found it:
    prev->next = newPerson;
    newPerson->next = curr;


void printList(person* pers) 
    while (pers != NULL) 
        printf("%s is %d years old.\n", pers->name, pers->age);
        pers = pers->next;
    


void freeList(person** pers) 
    while (*pers != NULL) 
        person* temp = *pers;
        *pers = (*pers)->next;
        free(temp);
    



int main()
    person* personList = NULL;
    insertPerson(&personList, "Max", 20);
    insertPerson(&personList, "Sven", 25);
    insertPerson(&personList, "Bob", 22);
    insertPerson(&personList, "John", 23);
    insertPerson(&personList, "Markus", 21);
    printList(personList);
    freeList(&personList);

【讨论】:

以上是关于交换链表中的元素的主要内容,如果未能解决你的问题,请参考以下文章

链表

两两交换链表中的节点

交换链表中的节点

LeetCode 24 两两交换链表中的节点

链表结点的交换

链表-LeetCode24两两交换链表中的节点