具有两个约束的链表插入

时间:2018-08-19 04:35:57

标签: c linked-list insert

尝试按字母顺序将学生插入链接列表。学生有名字和年龄。它们按名称排序,如果名称相同,则按年龄排序。

我可以正确命名名称,但是年龄有点棘手。分解的部分是第一个if语句。当一个新学生与列表中的第一个人同名时,则必须按年龄对他们进行排序,但是当我尝试使用该代码时,这给我带来了细分错误。其余代码有效。
这里是code

Student* insert(Student* student, Student* list)
{
Student* current;

if (list == NULL || (precedes(student->name, list->name) > 0) || strcmp(student->name, list->name) == 0){    
    if (strcmp(list->name, student->name) == 0) {  // goes wrong here i think
        if (student->age < list->age) {
            student->next = list;
            list = student;
        } else {
            student->next = list->next;
            list->next = student;
        }
    } else {
        student->next = list;
        list = student;
    }
} else {
    current = list;
    while(current->next != NULL && (precedes(current->next->name, student->name) > 0)) {
        current= current->next;
    }
    if (current->next != NULL && strcmp(current->next->name, student->name) == 0) {
        if (current->next->age > student->age){
            student->next = current->next;
            current->next = student;
        } else {
            student->next = current->next->next;
            current->next->next = student;
        }
    } else {
        student->next = current->next;
        current->next = student;
    }

}
return list;
}

1 个答案:

答案 0 :(得分:2)

您正在做的事情比需要做的要困难得多。

您有一个明确的案例,其中肯定要取消引用空指针,这样就可以确保未定义的行为。在您的代码中:

if (list == NULL || (precedes(student->name, list->name) > 0) || strcmp(student->name, list->name) == 0){    
    if (strcmp(list->name, student->name) == 0) {  // goes wrong here i think

如果由于list == NULL为真而输入了if块,则将立即取消引用该空指针以访问其nameage成员。随之而来的是未定义的行为,实际上您是不幸的您的程序崩溃了(这可能更糟;它可能成功了,并让您相信自己没有错误)。


实用程序比较功能

只有两个Student对象的比较可能潜在地是两阶段而不是一阶段的事实,才使此任务变得复杂。所以做两件事:

  • 编写一个比较函数,该函数绘制出不等大条件的特定条件。
  • 在需要比较两个Student结构的任何地方使用该功能。

这样的比较功能如下:

int cmp_Student(const Student *lhs, const Student *rhs)
{
    int cmp = strcmp(lhs->name, rhs->name);
    if (cmp == 0)
        cmp = (lhs->age < rhs->age) ? -1 : rhs->age < lhs->age;
    return cmp;
}

< 0引用的lhs小于Student时,返回rhs,当lhs等于{{1}时返回零。 },以及rhs> 0“大”的lhs

使用它,您可以编写一个简单的指针到指针漫游算法,该算法在列表中漫游指针以寻找合适的插入点,然后使用指针到指针来实现这一点。由于您确实不在乎,因此在rhs为NULL时,这也消除了使用特殊大小写的需要。

list

即使您不执行此Student *insert(Student *student, Student *list) { Student **pp = &list; while (*pp && cmp_Student(student, *pp) < 0) pp = &(*pp)->next; student->next = *pp; *pp = student; return list; } 方法,仍可以将insert用于自己的算法。无论如何,值得仔细阅读以上内容以了解其工作方式,而调试器是实现此目的的绝佳方法。

如果您坚持使用现有的实现,显然您需要修复该空指针取消引用代码路径,因为这显然是错误的。