【问题标题】:This function returns a list that contains the values that appear in list "A" at positions given in "pos_list"此函数返回一个列表,其中包含列表“A”中“pos_list”中给定位置的值
【发布时间】:2020-02-02 12:52:09
【问题描述】:

-如果一个列表有整数数据如:1->2->3->4->5->6 -而pos_list有整数数据如:4->0->5 - 那么这个函数应该返回一个新列表,其中包含列表 A 中 pos_list 中给定位置的值 这样新列表= 5->1->6

我正在实施深层复制以创建新列表。 我正在尝试使用根据 pos_list 的数据进行迭代的循环。在这个循环中,A 的节点将移动到 pos_list 数据的位置。这次我将复制新列表中的节点 A 以创建另一个列表。 假设第一种情况,pos_list 有数据 4,所以循环将运行 4 次,直到列表 A 的节点指向它的第四个位置。在这个循环中,我将在一个新循环中复制列表 A 的数据。 我需要指导来解决这个问题。

struct node * sublist(struct node * A, struct node * pos_list) {
struct node* newList=NULL;
struct node * curr;
int i=0;

for (i = 0, curr = pos_list->next; (curr != NULL); curr = curr->next) { //pos_list->data has a dummy node so loop until the end of pos_list->data.
   struct node* newList = (struct node *) malloc(sizeof (struct node));

    for(int i=0;i<=pos_list->data;i++){   //counter for pos_list as it will be (3 then 0,6 and 4)
        if(i==pos_list->data){            //At the time when i == pos_list->data(3 or 0 or 6..)
            newList->data = A->data;      //Putting value of list A data in new list.
            newList = newList->next;      //Linking
            printf("%d\t", newList->data);   //Just for log
        }
        A=A->next;                       //Going to next position on A
    }
   pos_list=pos_list->next;             //Going to next position on B
}
return newList ;
}

如果一个列表是:1->2->3->4->5->6 而pos_list是:4->0->5

我希望输出是 5->1->6 的新列表

【问题讨论】:

  • 总是用极端情况检查你的逻辑。如果你有一个空的 pos_list 怎么办?如果你有一个单元素 pos_list 怎么办?
  • 这个问题需要一个 pos_list 数据来排列新列表,所以 pos_list 不可能为空。虽然空的 pos_list 可以是测试用例之一,但不会做任何安排。新列表的排列方式应使其包含列表 A 中 pos_list 中给定位置处出现的值。
  • 空列表是包含零个元素的列表。除非您的作业明确说明“非空列表”,或者列表非空存在某些内在原因,否则任何列表都可能为空。在这个问题中没有这样的原因。一个空的 pos_list 只会导致一个空列表作为结果。这没有任何问题。
  • 发布的代码不包含任何功能。它缺少struct node 的定义
  • Stackoverflow 不是来为您编写代码的。请发布minimal reproducible example,以便我们重现问题并帮助您调试。

标签: c algorithm linked-list singly-linked-list deep-copy


【解决方案1】:

您的代码有几个问题:

  • 您应该以pos_list 开始遍历,而不是pos_list-&gt;next。头指针指向的节点是链表的一部分。此外,如果pos_list == NULL、pos_list-&gt;next 将导致未定义的行为。
  • int i 的外部定义没有用。删除它。
  • 不要通过位置来遍历A。如果位置无效,您将越过列表的末尾,获取空指针并调用未定义的行为。列表应该由从先前节点的next 指针访问的列表节点迭代。 (当然,提供有效位置是调用者的责任,但您的程序应该优雅地处理无效输入。)
  • 仅在找到有效位置后创建新节点。否则,您将创建一个从未插入的节点,从而导致内存泄漏。
  • 这里:newList = newList-&gt;next、newList-&gt;next 未初始化。请记住,malloc 会为您提供一大块未初始化的数据。
  • 您尝试使newList 指向新创建列表的末尾,以便快速添加新节点。这是个好主意,但如果你返回那个指针,你会得到一个只包含一个元素的列表。 (您也无法访问该列表中任何以前创建的节点。)

这是一个应该可以工作的实现:

struct node *sublist(struct node *A, struct node *pos_list)
{
    struct node *newHead = NULL;
    struct node *newTail = NULL;
    struct node *pos = pos_list;

    while (pos) {
        struct node *a = A;
        int i = 0;

        while (a) {
            if (i == pos->data) {
                struct node *node = malloc(sizeof(*node));

                if (newHead == NULL)  newHead = node;
                if (newTail) newTail->next = node;
                node->data = a->data;
                node->next = NULL;
                newTail = node;

                break;
            }

            a = a->next;
            i++;
        }

        pos = pos->next;
    }

    return newHead;
}

【讨论】:

  • 谢谢@M Oehm。你的指导帮助了我。但是为了正确的输出顺序,我必须将 i=0 替换为 i=-1。
  • 您的原始列表的开头是否有一个虚拟节点? (这可以解释为什么你以pos-&gt;next 开头。)不要那样做。它带来的麻烦多于它的价值。一个空列表应该由一个头指针 NULL 表示,并且它没有节点。
【解决方案2】:

该问题不允许使用“结构”来实施解决方案。 如果是这样,我就错了,但如果不是,这不是矫枉过正吗,当可以实现类似于以下内容时....

#include <stdio.h> 
#define CREATE_ARRAY(n) int result[n]

void main() {
  int data[] = {1,2,3,4,5,6};
  int pos[] = {4,0,5};
  int i;

  CREATE_ARRAY(sizeof(pos)/sizeof(int));
  for(i = 0; i < sizeof(pos)/sizeof(int);++i)
    result[i] = data[pos[i]];
/*
  To print the values stored in result
  for(i = 0;i < sizeof(result)/sizeof(int); ++i)
    printf("%d ",result[i]);
  putchar('\n');
}
*/

【讨论】:

    【解决方案3】:

    对于初学者来说,函数sublist 应该声明为

    struct node * sublist( const struct node *A, const struct node *pos_list );
    

    因为列表A 和列表pos_list 在函数中都没有改变。否则函数的声明会使代码的读者感到困惑。

    列表pos_list 包含一个虚拟节点是一个坏主意,因为它在此语句的注释中写入

    for (i = 0, curr = pos_list->next; (curr != NULL); curr = curr->next) { //pos_list->data has a dummy node so loop until the end of pos_list->data
    

    虚拟节点都不应该在列表中。

    在这个内部循环中

    for(int i=0;i<=pos_list->data;i++){
    

    没有使用列表的虚拟节点。而且pos_list在两个循环中遍历:外循环和内循环

    for (i = 0, curr = pos_list->next; (curr != NULL); curr = curr->next) { //pos_list->data has a dummy node so loop until the end of pos_list->data.
       struct node* newList = (struct node *) malloc(sizeof (struct node));
    
        for(int i=0;i<=pos_list->data;i++){
    

    在循环中,变量newList 的值发生了变化

    newList = newList->next;
    

    因此,函数总是返回一些不确定的值,而不是新创建的列表的头部。该值不确定,因为新创建的节点的数据成员 next 未初始化。

    newList->data = A->data;      //Putting value of list A data in new list.
    newList = newList->next; 
    

    函数可以通过以下方式定义

    struct node * sublist( const struct node *A, const struct node *pos_list ) 
    {
        struct node *newList = NULL;
        struct node **current = &newList;
    
        for ( ; pos_list != NULL; pos_list = pos_list->next )
        {
            const struct node *target = A;
    
            for ( int index = pos_list->data; index != 0 && target != NULL; --index )
            {
                target = target->next;
            }
    
            if ( target != NULL )
            {
                *current = malloc( sizeof( struct node ) );
                ( *current )->data = target->data;
                ( *current )->next = NULL;
                current = &( *current )->next;
            }
        }
    
        return newList;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-03-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-10-05
      • 1970-01-01
      相关资源
      最近更新 更多