【问题标题】:C program to make a second copy of a linked listC 程序制作链表的第二个副本
【发布时间】:2023-03-16 09:18:01
【问题描述】:

我正在编写一个 C 代码来将链接列表的内容复制到另一个列表中。我想知道是否有更有效的方法。

哪个更好?

struct node *copy(struct node *start1)
{
struct node *start2=NULL,*previous=NULL;

while(start1!=NULL)
{
    struct node * temp = (struct node *) malloc (sizeof(struct node));
    temp->info=start1->info;
    temp->link=NULL;

    if(start2==NULL)
    {
        start2=temp;
        previous=temp;
    }
    else
    {
        previous->link=temp;
        previous=temp;          
    }
    start1=start1->link;
}
return start2;
}

struct node *copy(struct node *start1)
{
    if(start1==NULL) return;
    struct node *temp=(struct node *) malloc(sizeof(struct node));
    temp->info=start1->info;
    temp->link=copy(start1->link);
    return temp;
}

【问题讨论】:

  • 您是在寻找运行时效率,还是寻求更紧凑/优雅的方式?
  • 我猜是更优雅的做法。
  • 比你应该递归的。
  • 递归地这样做会非常优雅,但你必须小心,以免堆栈溢出。嘿嘿嘿嘿,今天双关语自己写的。说真的,你只能递归到目前为止,除非你使用的是尾递归语言,而 C 不是。
  • @user1161318 真正的男人使用goto 进行递归;-) 虽然,某些C 编译器实现(即带有扩展的GCC?)can optimize for TCO 在某些情况下......但它必须是TCO'able开始。

标签: c algorithm linked-list


【解决方案1】:

对于速度,实际上可能有更好的方法。与往常一样,唯一真正的判断方法是对其进行基准测试。

  • 取决于迭代的相对成本
    • (这本身可能取决于您分配节点的方式和顺序,以及缓存和内存架构)
  • 免费商店分配
    • (这可能取决于您的堆处于什么状态、可能有多少其他线程正在访问它、主机操作系统中的物理内存状态等)
  • 可能更快:

    • 用一次迭代计算源列表的长度

      int len = 0;
      for (start2 = start1; start2 != NULL; start2 = start2->link)
          ++len;
      
    • 在单个块中为所有需要的节点分配空间

      struct node *temp = malloc(len * sizeof(*temp));
      
    • 然后花费第二次迭代链接你的节点数组

      int i = 0;
      for (start2 = start1; start2 != NULL; start2 = start2->link) {
          temp[i].info = start2->info;
          temp[i].link = &temp[i+1];
      }
      temp[len-1].link = NULL;
      

正如我所说,我不保证它更快(而且它肯定更丑),但它可能在某些系统上,带有一些编译器,在一些条件。当然,如果您的其余代码假定您可以随意free 单个节点,这将是不可行的。


为了优雅,递归自然胜出。

不过,简单的迭代方法通常会是一个很好的折衷方案,在优雅但可能会爆炸,除非你有一个花哨的 TCO 编译器 和上面的,坦率地说有点丑陋和将受益于解释性评论。

【讨论】:

  • 嗯,我正在为这个问题编写一个程序,因为它是在我的数据结构教科书的练习中。感谢您对效率的洞察力! :)
【解决方案2】:

要将一个链表复制到另一个链表,您别无选择,只能遍历一个并继续将值复制到第二个,总共O(n)time。 您已经这样做了。除非存储的元素之间存在某种关系,否则没有办法做得更好。

递归解决方案可能更好看,但实际上它效率较低

编辑:对于已更改的问题

迭代版本是better

注意:LOC 与效率没有直接关系。

【讨论】:

  • 是否可以至少减少代码行数?
  • 代码行数与效率无关。你的问题是关于提高效率的,我想我已经回答了:)
  • 可以减少行数。看我的回答
  • 但这并不一定会提高效率。另外看看我的评论。
【解决方案3】:

不用递归,这是你能得到的最紧凑的:

struct node *copy(struct node *org)
{
struct node *new=NULL,**tail = &new;

for( ;org; org = org->link) {
    *tail = malloc (sizeof **tail );
    (*tail)->info = org->info;
    (*tail)->link = NULL;
    tail = &(*tail)->link;
    }
return new;
}

【讨论】:

    猜你喜欢
    • 2016-01-29
    • 1970-01-01
    • 2020-06-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-22
    • 1970-01-01
    相关资源
    最近更新 更多