【问题标题】:C - Inserting new node alphabetically into linked listC - 按字母顺序将新节点插入到链表中
【发布时间】:2016-10-01 06:25:32
【问题描述】:

我一直在阅读,但仍然无法理解链接列表。我的问题是,由于某种原因,当我遍历列表以确定列表中的任何结构是否具有相同的名称或年龄时,它会删除列表,或者当我尝试将新节点添加到列表中时,它也会被删除。

该列表是动态的,因此我不会根据任何类型的计数,而是根据用户决定输入的结构数量。

任何方向都将不胜感激。

int add(char* name, char* genderValueString, char* breed, int age, float weight)
{

int result;
int count = 0;
gender curGen = 1;


struct dog *temp = malloc(sizeof(struct dog));

strcpy(temp->name, name);
strcpy(temp->breed, breed);
temp->age = age;
temp->weight = weight;

if (strcmpi(genderValueString, "male") == 0) {
    curGen = 0;
}
temp->genderValue = curGen;


if (list == NULL) {
    temp->next = list;
    list = temp;
    result = 1;
}

else {

    while (list != NULL) {
        if (strcmpi(list->name, name) == 0 && list->age == age) {
            result = 0;
        }

        else {
            result = 1;
        }

        list = list->next;
    }


    if (result == 1) {
        while (list != NULL) {

            if (strcmpi(list->name, name) > 0 || list->age > age) {

                struct dog *prev = list;
                list = temp;
                list->next = prev;              

            }   

            list = list->next;
        }


    }

}


return result;
}

【问题讨论】:

    标签: c linked-list


    【解决方案1】:

    我想你的变量 list 是一个全局变量,代表你的列表的头部。

    您的代码中的主要问题是您在 while 循环 (list = list->next) 中修改了 list,这意味着您正在丢失对头部的跟踪。

    你现在可以做的是让你的代码工作(也许)是声明另一个变量,它是头部的副本,你可以安全地修改它。

    例如:

    struct dog *list_tmp;
    
    ...
    
    for (list_tmp = list; list_tmp != NULL; list_tmp = list_tmp->next)
    {
        if (strcmpi(list->name, name) == 0 && list->age == age) {
            result = 0;
        }
        ...
    }
    

    然后为您的两个循环执行此操作。

    但最重要的是,永远不要修改list,因为它似乎是您列表头部的唯一副本;)

    【讨论】:

    • 非常感谢,但我还是有点麻烦。如果我想在列表中添加一些内容,我会将其添加到 list_tmp 中,然后使旧列表等于临时列表,还是应该直接将其添加到原始列表中?
    【解决方案2】:

    我使用 Visual Studio 2013 对此进行了测试。您需要跟踪列表的当前头部。我已将此全局命名为doglist。然后使用局部变量list 在列表中移动。有一个棘手的情况 - 当您在列表头部之前插入时,您需要将其设为列表的新头部。

    struct dog
    {
        char name[50];
        int genderValue;  
        char breed[50];
        int age;
        float weight;
        struct dog * next;
    };
    
    struct dog *doglist = NULL;
    
    int dogadd(char* name, char* genderValueString, char* breed, int age, float weight)
    {
        struct dog * list = doglist;    // save head of list
        int count = 0;
        int curGen = 1;
    
        struct dog *temp = (dog *)malloc(sizeof(struct dog));
        strcpy(temp->name, name);
        strcpy(temp->breed, breed);
        temp->age = age;
        temp->weight = weight;
    
        if (strcmpi(genderValueString, "male") == 0) {
            curGen = 0;
        }
        temp->genderValue = curGen;
    
        if (list == NULL) {
            temp->next = list;
            doglist = temp;
            return 1;
        }
    
        while (list != NULL) {
            if (strcmpi(list->name, name) == 0 && list->age == age) {
                return 0;
            }
            list = list->next;
        }
    
        list = doglist;             // restore the head of the list
        struct dog * prev = NULL;   // keep the previous list node so we can point it to the inserted entry
        while (list != NULL) {
            int nameCompare = strcmpi(list->name, name);
            if ( nameCompare > 0 || (nameCompare == 0 && list->age > age) ) {
    
                temp->next = list;
                if (prev != NULL)
                    prev->next = temp;
                // if we are inserting before the current head of the list we need to make this the new head
                if (list == doglist)
                    doglist = temp;
                list = temp;
                return 1;
            }
            if (list->next == NULL) {
                // Nothing greater than this, so add it to end
                list->next = temp;
                temp->next = NULL;
                return 1;
            }
            prev = list;
            list = list->next;
        }
        return 0;
    }
    
    void main()
    {
        dogadd("Sybil", "female", "red heeler", 7, 40.1);
        dogadd("Pepi", "male", "chihuahua", 5, 3.3);
        dogadd("Goliath", "male", "bulldog", 9, 20.5);
        dogadd("Harry", "male", "golden retriever", 9, 35.6);
        dogadd("ZsaZsa", "female", "poodle", 3, 10.5);
        dogadd("Bruce", "male", "german shepherd", 9, 42.7);
        dogadd("Sybil", "female", "red heeler", 7, 40.1); // check it isn't added again
        struct dog * list = doglist;
        while (list != NULL) {
            printf("Dog name=%s sex=%d, breed=%s, age=%d, weight=%f\n", list->name, list->genderValue, list->breed, list->age, list->weight);
            list = list->next;
        }
    }
    

    【讨论】:

    • 感谢您的建议,我仍然遇到这个问题,它只会让我在列表中添加几个名字,然后停止。
    • 哎呀 - 忘记将前一个列表节点指向新插入的节点。我没有在 2 个现有条目之间插入新条目的测试用例,这会暴露此错误。
    • 非常感谢,这真的帮助我弄清楚了链接列表的功能。
    • (dog *)malloc... --> C 中的(struct dog *)malloc...。C 中也不需要这种转换。
    猜你喜欢
    • 1970-01-01
    • 2019-01-25
    • 2021-01-20
    • 2013-09-17
    • 1970-01-01
    • 2012-10-21
    • 1970-01-01
    • 1970-01-01
    • 2014-03-12
    相关资源
    最近更新 更多