【问题标题】:Adding value in the "nth" node of a linked list在链表的第 n 个节点中添加值
【发布时间】:2020-08-30 17:17:00
【问题描述】:

我正在尝试在链表的“第 n 个”节点中添加一个值。如果 n = 0,则该值将是列表的头部。如果 n 大于列表的长度,它将是列表中的最后一个节点。否则,n 将被插入到列表中。但是,我的代码不起作用。下面是我的代码中访问任何输入并相应调整输入列表的函数。

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>

struct node {
    struct node *next;
    int data;
};

struct node *insert_nth(int n, int value, struct node *head);
struct node *strings_to_list(int len, char *strings[]);
void print_list(struct node *head);

// DO NOT CHANGE THIS MAIN FUNCTION

int main(int argc, char *argv[]) {
    int n;
    scanf("%d", &n);
    int value;
    scanf("%d", &value);
    // create linked list from command line arguments
    struct node *head = NULL;
    if (argc > 1) {
        // list has elements
        head = strings_to_list(argc - 1, &argv[1]);
    }

    struct node *new_head = insert_nth(n, value, head);
    print_list(new_head);

    return 0;
}



// Insert a new node containing value at position n of the linked list.
// if n == 0, node is inserted at start of list
// if n >= length of list, node is appended at end of list
// The head of the new list is returned.
struct node *insert_nth(int n, int value, struct node *head) {
    struct node *temporary = head;
    struct node *p;
    p = malloc(sizeof(struct node));
    p->data = value; 
    int count = 0;

    while (temporary != NULL) {
        count++;
        temporary = temporary->next;
    }

    if (n == 0) {
        p->next = head;
        return p;
    }

    else if (n >= count) {
        while (temporary != NULL) {
            temporary = temporary->next;
        }
        temporary->next = p;
        p->next = NULL;
        return head; 
    }

    else {
        int i = 0;
        while (i < count && temporary != NULL) {
        temporary = temporary->next; 
        }
    temporary = p;
    p->next = temporary;
    return head;
    }
}

// DO NOT CHANGE THIS FUNCTION
// create linked list from array of strings
struct node *strings_to_list(int len, char *strings[]) {
    struct node *head = NULL;
    int i = len - 1;
    while (i >= 0) {
        struct node *n = malloc(sizeof (struct node));
        assert(n != NULL);
        n->next = head;
        n->data = atoi(strings[i]);
        head = n;
        i -= 1;
    }   
    return head;
}

// DO NOT CHANGE THIS FUNCTION
// print linked list
void print_list(struct node *head) {
    printf("[");    
    struct node *n = head;
    while (n != NULL) {
        // If you're getting an error here,
        // you have returned an invalid list
        printf("%d", n->data);
        if (n->next != NULL) {
            printf(", ");
        }
        n = n->next;
    }
    printf("]\n");
}

【问题讨论】:

  • 您能否提供一个完整的示例,其中包含main 程序发出您的insert_nth 以重现您的问题?顺便说一句:当您写“它不起作用”时,您的实际意思是什么?它崩溃了吗?它破坏了数据?什么?
  • 我试图包含整个程序,但我无法发布它,因为显然代码太多了。不过我会再试一次。我的意思是它没有通过我的大部分练习测试。

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


【解决方案1】:

对于初学者,应该更改函数参数的顺序。第一个参数应指定要更改的列表,第二个参数应指定将插入到列表中的值,第三个参数应指定插入值的位置。

位置应该是无符号整数类型,例如size_t。为该位置指定有符号整数类型int 没有任何意义。

计算当前列表中的节点数完全是多余的。经过这个循环

while (temporary != NULL) {
    count++;
    temporary = temporary->next;
}

指针temporary 将等于NULL。所以在随后的循环中使用这个指针,就像在这个

else {
    int i = 0;
    while (i < count && temporary != NULL) {
    temporary = temporary->next; 
    }
temporary = p;
p->next = temporary;

没有意义,而且在这个循环中

else if (n >= count) {
    while (temporary != NULL) {
        temporary = temporary->next;
    }
    temporary->next = p;
    ^^^^^^^^^^^^^^^^

使用指针会导致未定义的行为。

这是一个带有多个测试的演示程序。

#include <stdio.h>
#include <stdlib.h>

struct node 
{
    struct node *next;
    int data;
};

struct node * insert_nth( struct node *head, int value, size_t n )
{
    struct node *new_node = malloc( sizeof( struct node ) );

    new_node->data = value;

    struct node *current = head, *prev = NULL;

    while ( n-- && current != NULL )
    {
        prev = current;
        current = current->next;
    }

    new_node->next = current;

    if ( prev == NULL )
    {
        head = new_node;
    }
    else
    {
        prev->next = new_node;
    }

    return head;
}

// DO NOT CHANGE THIS FUNCTION
// print linked list
void print_list(struct node *head) {
    printf("[");    
    struct node *n = head;
    while (n != NULL) {
        // If you're getting an error here,
        // you have returned an invalid list
        printf("%d", n->data);
        if (n->next != NULL) {
            printf(", ");
        }
        n = n->next;
    }
    printf("]\n");
}

int main(void) 
{
    {   
        struct node *head = NULL;

        head = insert_nth( head, 0, 0 );

        print_list( head );
    }

    putchar( '\n' );

    {   
        struct node *head = NULL;

        head = insert_nth( head, 1, 0 );

        print_list( head );
    }

    putchar( '\n' );

    {   
        struct node *head = NULL;

        head = insert_nth( head, 0, 0 );
        head = insert_nth( head, 1, 1 );

        print_list( head );
    }

    putchar( '\n' );

    {   
        struct node *head = NULL;

        head = insert_nth( head, 1, 1 );
        head = insert_nth( head, 0, 0 );

        print_list( head );
    }

    putchar( '\n' );

    {   
        struct node *head = NULL;

        head = insert_nth( head, 1, 0 );
        head = insert_nth( head, 3, 1 );
        head = insert_nth( head, 2, 1 );
        head = insert_nth( head, 0, 0 );
        head = insert_nth( head, 4, 10 );

        print_list( head );
    }

    return 0;
}

程序输出是

[0]

[0]

[0, 1]

[0, 1]

[0, 1, 2, 3, 4]

函数insert如果通过引用将指向头节点的指针传递给函数,会更安全、更简单。

在这种情况下,函数可以如下所示

#include <stdio.h>
#include <stdlib.h>

struct node 
{
    struct node *next;
    int data;
};

int insert_nth( struct node **head, int value, size_t n )
{
    struct node *new_node = malloc( sizeof( struct node ) );
    int success = new_node != NULL;

    if ( success )
    {
        new_node->data = value;

        while ( *head != NULL && n-- )
        {
            head = &( *head )->next;
        }

        new_node->next = *head;
        *head = new_node;
    }

    return success;
}

// DO NOT CHANGE THIS FUNCTION
// print linked list
void print_list(struct node *head) {
    printf("[");    
    struct node *n = head;
    while (n != NULL) {
        // If you're getting an error here,
        // you have returned an invalid list
        printf("%d", n->data);
        if (n->next != NULL) {
            printf(", ");
        }
        n = n->next;
    }
    printf("]\n");
}

int main(void) 
{
    {   
        struct node *head = NULL;

        insert_nth( &head, 0, 0 );

        print_list( head );
    }

    putchar( '\n' );

    {   
        struct node *head = NULL;

        insert_nth( &head, 1, 0 );

        print_list( head );
    }

    putchar( '\n' );

    {   
        struct node *head = NULL;

        insert_nth( &head, 0, 0 );
        insert_nth( &head, 1, 1 );

        print_list( head );
    }

    putchar( '\n' );

    {   
        struct node *head = NULL;

        insert_nth( &head, 1, 1 );
        insert_nth( &head, 0, 0 );

        print_list( head );
    }

    putchar( '\n' );

    {   
        struct node *head = NULL;

        insert_nth( &head, 1, 0 );
        insert_nth( &head, 3, 1 );
        insert_nth( &head, 2, 1 );
        insert_nth( &head, 0, 0 );
        insert_nth( &head, 4, 10 );

        print_list( head );
    }

    return 0;
}

程序输出同上图

[0]

[1]

[0, 1]

[0, 1]

[0, 1, 2, 3, 4]

注意函数print_list的参数应该用限定符const声明,因为函数中的列表没有改变。

void print_list( const struct node *head );

【讨论】:

  • 谢谢! :) :)
【解决方案2】:

我建议你像这样重构你的代码:

struct node *insert_nth(int n, int value, struct node *head) {
    struct node *el;
    struct node *curr = head, *prev = NULL; // current and previous elements

    el = (struct node*) malloc(sizeof(struct node));
    el->data = value;

    // Insert in the head
    if (n == 0 || head == NULL) {
        el->next = head;
        return el;
    }

    // Move to second element
    prev = head;
    curr = head->next;
    n--;

    // Iterate until n-th element or the end of the list
    while (curr != NULL && n != 0) {
        prev = curr;
        curr = curr->next;
        n--;
    }

    // Insert between previous and current elements
    prev->next = el;
    el->next = curr;

    return head;
}

首先您需要检查列表是否为空或n 为0。如果不是,则迭代直到第n 个元素。我建议您对当前和上一个元素使用几个指针。然后在先前和当前指针之间插入新元素。如果您位于列表的末尾,则当前指针将为NULL

【讨论】:

  • 谢谢! :) :)
  • @comp_questions 不客气,但请记住当它是您问题的正确解决方案时接受答案。
猜你喜欢
  • 1970-01-01
  • 2014-08-06
  • 1970-01-01
  • 2011-01-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-04-17
  • 1970-01-01
相关资源
最近更新 更多