简体   繁体   English

C中的段故障链接列表递归

[英]Seg fault linked list recursion in C

I can't figure out why I'm seg faulting. 我不知道为什么我要断层。 The basic idea is to insert integers in order recursively using a linked list. 基本思想是使用链接列表以递归顺序插入整数。

node* insert(node** head, int integer)
{
    node* temp = malloc(sizeof(node));
    node* temp1;
    node* newNode;

    if(*head == NULL)
    {
        temp->num = integer;
        temp->next = *head;
        *head = temp;
    }
    else if((*head)->num > integer)
    {
        temp = *head;
        temp1 = temp->next; //breaks the link
        temp->next = newNode;   //creates a new node
        newNode->num = integer;  //adds int
        newNode->next = temp1;   //links new node to previously broken node 
        temp1->next = *head; //next node is NULL 
        *head = temp1;  //Makes next node head again
    }

    else
        insert(&((*head)->next), integer);

    return(temp);
}

I ran this code in GDB and it seg faults at temp1->next = *head but I don't understand why. 我在GDB中运行了这段代码,它在temp1->next = *headtemp1->next = *head了段错误,但我不明白为什么。 I even put notes to help myself but I guess it isn't working. 我什至会做笔记以帮助自己,但我想它没有用。 Can someone please tell me why I'm seg faulting? 有人可以告诉我我为什么要断层吗? Thanks. 谢谢。

temp1 = temp->next;

should be before 应该在之前

temp = *head;

In case that the (*head)->num > integer and If you want to insert the integer in the header than your code is complicated and wrong. 如果(*head)->num > integer并且如果您想在标头中插入整数,那么您的代码将是复杂且错误的。 you can do it in this way: 您可以通过以下方式进行操作:

else if((*head)->num > integer)
    {
        temp->next = *head;
        temp->num = integer;
        *head = temp;
    }

and the

temp = malloc(sizeof(node));

should be called only into the 应该只叫入

if(*head == NULL)

and into 并入

else if((*head)->num > integer)

So your final function could be like this 所以您的最终功能可能是这样的

node* insert(node** head, int integer)
{
    node* temp;

    if(*head == NULL)
    {
        temp = malloc(sizeof(node));
        temp->num = integer;
        temp->next = *head;
        *head = temp;
    }
    else if((*head)->num > integer)
    {
        temp = malloc(sizeof(node));
        temp->next = *head;
        temp->num = integer;
        *head = temp;
    }

    else
        temp = insert(&((*head)->next), integer);

    return(temp);
}

I test the insert function with: 我测试插入功能:

int main (void) {


   node *tmp, *head = NULL;
   insert(&head, 5);
   insert(&head, 7);
   insert(&head, 3);
   insert(&head, 6);
   insert(&head, 4);
   insert(&head, 2);

   for (tmp = head; tmp!=NULL; tmp = tmp->next) {
        printf("tmp->num  %d\n",tmp->num);
   }

}

and it works succefully! 它成功地工作了!

$ ./test
tmp->num  2
tmp->num  3
tmp->num  4
tmp->num  5
tmp->num  6
tmp->num  7

So the first time you go through this, head is null and you've got a case for that. 因此,第一次执行此操作时,head为空,并且您有一个理由。

The next time through, head has a pointer, and there is no next node. 在下一次通过时,head有一个指针,并且没有下一个节点。 The head->next is NULL. head-> next为NULL。

So when you get to: 因此,当您到达:

temp1 = temp->next; 

That's setting it equal to NULL. 将其设置为NULL。 And when you get to 当你到达

temp1->next = *head; //next node is NULL 

Whoa there, temp1 is null. 那里,temp1为空。 There is no such thing as temp1->next, that's looking for a structure where there is none. 没有temp1-> next这样的东西,它正在寻找不存在的结构。

Edit: 编辑:
And you're throwing away the memory you just allocated when you set temp = *head . 当您设置temp = *head时,您将丢弃刚刚分配的内存。 You probably shouldn't be allocating memory until you're sure you need it. 在确定需要之前,您可能不应该分配内存。 I mean, you call a new instance of insert() every time the number is less than the target. 我的意思是,每当数字小于目标数时,您就调用一个insert()的新实例。 Each pass you allocate some memory that you don't actually use. 每遍都分配一些您实际上不使用的内存。 And you probably wanted to allocate memory for newnode , not temp . 您可能想为newnode分配内存,而不是temp

And you should probably use a better naming scheme. 而且您可能应该使用更好的命名方案。 I mean, the second time you call insert, it's no longer the head. 我的意思是,第二次调用插入时,它不再是头。 integer could be something more like intToInsert or newValue . integer可能更像intToInsertnewValue temp1 is more like savedTail . temp1更像savedTail Minor issue, but it helps keep things straight, and it's a good habit to get into. 次要问题,但这有助于保持直率,这是一个养成的好习惯。

Finally, think about what happens when you've gone through the list, found where the new item belongs, made a new node, set it's ->next field to the rest of the tail, and returned. 最后,考虑一下当您遍历列表,找到新项目所属的位置,创建新节点,将其->next字段设置为其余部分并返回时会发生什么。 ... now what? ... 怎么办? the previous node has a next value that's still pointing to what it was before. 前一个节点的next值仍指向之前的值。 You need to update that link as well. 您还需要更新该链接。

Lets assume that the linked list currently has only one node. 假设链表当前只有一个节点。

So *head = some node. 所以* head =某个节点。

*head->next = NULL. * head-> next = NULL。

Now lets look into the code: 现在让我们看一下代码:

node* insert(node** head, int integer)
{
    node* temp = malloc(sizeof(node));
    node* temp1;
    node* newNode;

    if(*head == NULL)  // condition = false
    {
        temp->num = integer;
        temp->next = *head;
        *head = temp;
    }
    else if((*head)->num > integer)  // let's assume condition = true
    {
        temp = *head;
        temp1 = temp->next; //breaks the link   // temp1 = NULL
        temp->next = newNode;   //creates a new node  // temp1 is not changed
        newNode->num = integer;  //adds int
        newNode->next = temp1;   //links new node to previously broken node 
        temp1->next = *head; //next node is NULL // NULL->next !!!
        *head = temp1;  //Makes next node head again
    }

    else
        insert(&((*head)->next), integer);

    return(temp);
}
*head = temp1;

应该在之前

temp1->next = *head;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM