【问题标题】:creating an interleave_lists linked list?创建 interleave_lists 链表?
【发布时间】:2016-03-24 20:08:57
【问题描述】:

我正在尝试创建一个名为IntNode *interleave_lists(IntNode *head_1, IntNode *head_2); 的链表函数,它接受两个链表,将它们组合起来并返回一个指向头部的指针。

示例:假设 head_1 指向一个包含三个整数的链表:1、3、5 和 head_2 指向一个包含 5 个整数的链表:10、11、12、13、14。新的链表将包含 8 整数,按以下顺序:1、10、3、11、5、12、13、14。

我有这些结构来帮助创建链表:

struct intnode {
   int value;
   struct intnode *next;
};
typedef struct intnode IntNode;

IntNode *intnode_construct(int value, IntNode *next)
{
   IntNode *p = malloc(sizeof(IntNode));
   assert (p != NULL);
   p->value = value;
   p->next = next;
   return p;
}
void print_linked_list(IntNode *p) //for printing linked list
{
    if (p == NULL) {
        printf("empty list");
        return; 
    }

    /* Print every node in the linked list except the last one,
       using the format: value1 -> value2 -> value3 -> ...
     */
    for (; p->next != NULL; p = p->next) {
        printf("%d -> ", p->value);
    }

    /* Print the last node. */
    printf("%d", p->value);
}

现在尝试创建我拥有的功能:

IntNode *interleave_lists(IntNode *head_1, IntNode *head_2)
{
    int count = 1;
    IntNode *p1=head_1, *p2=head_2,*head=NULL;
    for(; (p1->next != NULL) || (p2->next != NULL); p1 = p1->next, p2 = p2->next){
        if(p1 != NULL && count == 1){
            head = intnode_construct(p1->value,head);
            count = 0;
        } else if(p2 != NULL && count == 0){
            head = intnode_construct(p2->value,head);
        }
    }
    return head;
}

但每次我运行它时,控制台都会显示 CRT: unhandled exception (main) -- terminating。 我对此功能的测试用例:

int main(void)
{
    IntNode *list1 = NULL,*list2 = NULL; // An empty linked list.
    list1 = intnode_construct(5, list1);
    list1 = intnode_construct(3, list1);
    list1 = intnode_construct(1, list1);

    list2 = intnode_construct(14, list2);
    list2 = intnode_construct(13, list2);
    list2 = intnode_construct(12, list2);
    list2 = intnode_construct(11, list2);
    list2 = intnode_construct(10, list2);


    IntNode *head = NULL;

    head = interleave_lists(list1, list2);
    print_linked_list(head);
}

【问题讨论】:

  • 崩溃发生在哪一行?如果您不知道,请使用调试器查找。
  • 我猜p->next = next;应该是p->next = NULL;
  • 顺便说一句,如果需要,您可以使 interleave 函数对现有列表进行操作,以避免复制所有节点。取决于您以后是否要保留原始列表。

标签: arrays c pointers heap-memory dynamic-memory-allocation


【解决方案1】:

多个问题

  • 您检查的是p->next != NULL 而不是p != NULL,因此您丢失了列表的最后一个元素
  • 您的循环检查p1 || p2,只要其中一个指针还没有到达末尾就循环。因此,如果列表的长度不同,短列表的指针就会跑到最后并崩溃。
  • 您的 intnode_construct 函数从右到左(尾到头)构造列表,但您从头到尾迭代,因此您在交错列表时反转列表。

反转列表意味着您需要从尾部交错,使您的 interleave_lists 函数更容易递归实现:

IntNode *copy_list(IntNode *head)
{
    if (!head) return head;
    return intnode_construct(head->value, copy_list(head->next));
}

IntNode *interleave_lists(IntNode *head_1, IntNode *head_2)
{
    if (!head_1) return copy_list(head_2);
    return intnode_construct(head_1->value, interleave_lists(head_2, head_1->next));
}

或者,您可以进行“破坏性”交错,重用输入列表的节点:

IntNode *interleave_lists(IntNode *head_1, IntNode *head_2)
{
    if (!head_1) return head_2;
    head_1->next = interleave_lists(head_2, head_1->next);
    return head_1;
}

【讨论】:

    【解决方案2】:

    1)您的intnode_construct 应如下所示

    IntNode *intnode_construct(int value, IntNode *next)
    {
       IntNode *p = malloc(sizeof(IntNode));
       if (p != NULL)
       {
           p->value = value;
           p->next = NULL;
       }
       return p;
    }
    

    使用您的代码,函数interleave_lists 中的循环for(; (p1->next != NULL) || (p2->next != NULL); 永远不会结束,因为->next 永远不会是== NULL

    2) 您的interleave_lists 必须如下所示:

    IntNode *interleave_lists(IntNode *head_1, IntNode *head_2)
    {
        int count = 1;
        IntNode *p1=head_1, *p2=head_2,*head=NULL;
    
        while ((p1 != NULL) || (p2 != NULL))
        {
            if(p1 != NULL && count == 1)
            {
                head = intnode_construct(p1->value,head);
                count = 0;
                p1 = p1->next;
            }
            else if(p2 != NULL && count == 0)
            {
                head = intnode_construct(p2->value,head);
                p2 = p2->next;
            }
        }
    
        return head;
    }
    

    您的代码总是在每个循环中将两个指针都移动到下一个,而不检查指针是否有效或NULL

    3) 顺便说一句,您必须更正您的代码以使每个链表都位于头部。您的代码更新传递给interleave_lists 最后一个元素...

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-10-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-06-16
      相关资源
      最近更新 更多