【问题标题】:Insert a number to a sorted linked list, why the number inserts to the second position every time?向排序链表插入一个数字,为​​什么每次都插入到第二个位置?
【发布时间】:2018-04-24 07:10:50
【问题描述】:

我正在做一个关于链表的项目,我无法将数字插入到排序的链表中。每次插入第二个位置的数字,我无法弄清楚问题出在哪里。这是我的代码:

void insertSort(struct linkedList *n,int num,int *length){                   //insert number to a sort linked list
    node *new = (node *) malloc(sizeof(node));          //create a new node
    new->next=NULL;
    new->data = num;
    while(n!=NULL&&n->data > new->data){             // find which position     num should insert in sorted list
            n = n->next;
    }
    new->next = n->next;          
    n->next= new;       
    length += 1;

}

n 是链表的头部。我初始化 head 指向第一个节点并且没有值。 这是我如何调用这个函数:

insertSort(head->next,num,&length);

每次插入第二个位置的数字。就像我想将 45 插入排序的链表 一样,插入后,列表将是 。 45 出于某种原因插入到第二个位置。

【问题讨论】:

    标签: c sorting linked-list insert singly-linked-list


    【解决方案1】:

    问题:

    每次插入第二个位置的数字……

    发生是因为在这部分代码中:

    while(n!=NULL&&n->data > new->data){             // find which position     num should insert in sorted list
            n = n->next;
    }
    new->next = n->next;          
    n->next= new;
    

    您将在n->next 之后插入新节点。

    假设你的链表的第一个节点有数据16,现在你想在链表中插入数据45的新节点,while循环条件将失败,因为16 > 45将评估到false

    while 循环之后的语句new->next = n->next; 会将新节点的下一个节点设置为第一个节点的下一个节点,n->next= new; 将在第一个节点之后插入新节点。因此,新节点每次都插入到第二个位置。

    您的函数insertSort() 存在更多问题,例如:

    • 在向链表插入节点时不跟踪链表的head,并且,
    • 如果插入的节点是链表的第一个节点会怎样?在这种情况下,nNULLinsertSort()while 循环之后访问 nextn - new->next = n->next;

    查看您给出的示例 - ,您希望按升序插入。 你可以这样做:

    struct linkedList *insertSort(struct linkedList *n, int num, int *length) {
        struct linkedList *first_node = n;
    
        struct linkedList *new_node = malloc(sizeof(struct linkedList));  //create a new node
        new_node->next=NULL;
        new_node->data = num;
    
        if (first_node == NULL || first_node->data >= new_node->data) {
                new_node->next = first_node;
                first_node = new_node;
        } else {
                struct linkedList *temp = first_node;
    
                while (temp->next != NULL && temp->next->data < new_node->data) {
                        temp = temp->next;
                }
                new_node->next = temp->next;
                temp->next = new_node;
        }
        *length += 1;
    
        return first_node;
    }
    

    在这里,您可以看到我已将返回类型void 更改为struct linkedList *,以便在将新节点插入到链表中的适当位置后insertSort() 将返回链表的head。这样,您可以在每次插入后跟踪链表的head。你只需要这样做:

    head = insertSort(head, num, &length);
    

    无论您在哪里拨打insertSort()

    或者,如果你不想改变insertSort()的返回类型,你可以在insertSort()中传递head指针的地址并跟踪它,像这样:

    void insertSort(struct linkedList **head, int num, int *length) {
        struct linkedList *new_node = malloc(sizeof(struct linkedList));  //create a new node
        new_node->next=NULL;
        new_node->data = num;
    
        if (*head == NULL || (*head)->data >= new_node->data) {
            new_node->next = *head;
            *head = new_node;
        } else {
            struct linkedList *temp = *head;
    
            while (temp->next != NULL && temp->next->data < new_node->data) {
                    temp = temp->next;
            }
            new_node->next = temp->next;
            temp->next = new_node;
        }
        *length += 1;
    }
    

    您可以像这样拨打insertSort()

    insertSort(&head, 32, &length);
    

    希望这会有所帮助。

    【讨论】:

    • "向链表插入节点时不跟踪链表头部"。只是徘徊为什么我们需要跟踪链表的头部。是不是 head 总是指向第一个节点。就像我将 2 插入到 中,这给了我们 。 Head 总是指向第一个节点,不管它是什么值。所以,跟踪头部的位置对我来说没有意义。谢谢你的回答!
    • 假设您有列表&lt;1,2,3&gt; 并且head 指向第一个节点,即1。现在,尝试插入0 以列出&lt;1,2,3&gt;。结果列表将是&lt;0,1,2,3&gt;,而之前指向节点1head 现在应该指向节点0。这就是为什么列表插入逻辑需要根据您要在列表中插入的新元素设置/重置列表的head,以便head 应始终指向列表中的第一个元素。
    • 这样我就可以传递head的地址了,它是一个指向指针的指针。
    • like insertSort(int linkedList **n, int num, int *length)
    • 是的,有了这个,您可以根据条件简单地设置/重置头指针*n
    【解决方案2】:

    因为您从不测试节点的位置。您的代码仅将新节点放在第二个位置。它不检查它应该在排序列表中的位置 试试下面

     void sortedInsert(struct Node** head_ref, struct Node* new_node) {
    
            struct Node* current;   /* Special case for the head end */ 
            if(*head_ref == NULL || (*head_ref)->data >= new_node->data)    {
    
                new_node->next = *head_ref;         
                *head_ref = new_node;   
            } 
            else    { 
            /*Locate the node before the point of insertion */      
                current =*head_ref;            
                while (current->next!=NULL && current->next->data < new_node->data) 
               {            
                  current = current->next;  
             }        
               new_node->next =current->next;   
               current->next = new_node;    }
         }
    

    【讨论】:

    • 谢谢!我想知道为什么我们必须检查节点的位置。例如,3->5>。现在我将 2 插入到列表中。所以我们让 1 指向 2,让 2 指向 3,这给了我们2->3->5>。我不知道我们为什么要检查这个位置。
    • 因为您下次可能会在列表中插入 4 。代码需要找到最后一个小于 4 的值在哪里,在本例中为 3 。寻找位置适用于 n 大小的列表。
    猜你喜欢
    • 2014-05-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-02
    • 2022-01-17
    相关资源
    最近更新 更多