5

我是 C 新手,所以如果您在我的代码中看到一些真正的新手错误,请耐心等待!

作为作业的一部分,我需要创建一个有序列表来存储一些数据。到目前为止我所做的是创建将表示列表的每个节点的结构(firstNode 是指向列表的第一个节点的全局变量):

typedef struct Node {
    struct Node *next;
    int id;
    int value;
}Node;

Node *firstNode = NULL;

之后,我创建了一个函数,通过检查节点的值将新节点插入到列表中。具有较小值的节点应该在其他节点之前。所以我做的是这样的:

void addNewNode(int nodeId, int nodeValue) {
    Node *newNode = (Node*) malloc(sizeof(Node));
    Node *temp, *tempPrev;
    newNode->id = nodeId;
    newNode->value = nodeValue;

    if(firstNode == NULL) {
        newNode->next = firstNode;
        firstNode = newNode;
    }
    temp = firstNode;
    tempPrev = NULL;
    while(temp->value < newNode->value) {
        tempPrev = temp;
        temp = temp->next;
    }
    if(tempPrev == NULL) {
        newNode->next = firstNode;
        firstNode = newNode;
    } 
    else {
        tempPrev->next = newNode;
        newNode->next = temp;
    }
}

上面代码的问题是,有时候程序会崩溃,但是我找不到错误!

另外,我接下来要做的是,如果某些节点具有相同的值,那么它们会根据它们的 id 进行排序(具有较小 ID 的节点首先出现)。我怎样才能做到这一点?我真的很困惑!

4

5 回答 5

3

程序崩溃是因为在 while 循环条件下,您没有检查 temp 是否等于 NULL。换句话说,如果您尝试插入一个值大于列表中所有其他节点的新节点,则 temp 会到达列表的末尾(因此 temp 等于 NULL)并且您尝试获取该节点的值!所以解决方法是:

while(temp!=NULL && temp->value>newNode->value)
{
    ....
}

至于节点的 id,您可以像这样扩展您的 while 循环条件:

while(temp!=NULL && (temp->value<newNode->value || (temp->value==newNode->value && temp->id<newNode->id))
{
    ....
}

此外,在您的情况下,不需要检查 firstNode 是否为 NULL 的第一个 if 语句。如果为 NULL,程序将不会进入 while 循环,而是直接进入 while 循环之后的第一个 if 语句。

顺便说一句,C 语言新程序员的好代码 :-)

于 2010-01-13T13:05:31.033 回答
1

1.

if(firstNode == NULL) {
        newNode->next = firstNode;
        firstNode = newNode;
        return; // done with inserting the first node...need not continue.
    }

2.

// ensure temp is not null only then access its value.
while(temp && (temp->value < nodeId->value)) {
        tempPrev = temp;
        temp = temp->next;
    }
于 2010-01-13T13:05:17.970 回答
0

一方面,你有 nodeID -> value 在那里。NodeID 是一个 int,所以这不起作用。

于 2010-01-13T13:07:17.380 回答
0

作为一种调试方法,我将创建一个简单的测试工具。换句话说,您编写的测试程序贯穿您能想到的所有常见场景(也称为单元测试)。每个单元测试都会检查以确保其正常运行并生成预期的输出。这样,您就可以确信,如果一切正常,您就可以开始了。如果单元测试失败,您就可以确切地知道出了什么问题。

于 2010-01-13T13:08:22.633 回答
0

我建议构建几个测试用例来检查您的边界条件(例如,将一个元素添加到一个空列表;添加一个应该在现有列表的前面结束的元素;添加一个应该在末尾结束的元素现有列表;添加一个应该在现有列表中间某处结束的元素)。制作一个“打印”功能,将列表中的元素打印到控制台进行调试。这至少可以帮助您缩小崩溃的背景范围。一种可能性(我不知道您正在添加多少)是程序内存不足并且 malloc 失败。您可以检查一下,因为我认为如果 malloc 未能分配必要的内存,它会返回 NULL。

Node *newNode = (Node*) malloc(sizeof(Node)); 
if(newNode == NULL)
{
  printf("Out of Memory!");
  return;
}
于 2010-01-13T13:11:53.023 回答