如何将一个链接列表复制到另一个列表中?

发布于 2024-10-16 23:19:30 字数 61 浏览 5 评论 0原文

我正在研究数据结构和链表,但我不了解如何制作链表副本的概念。有人可以解释一下,可能使用伪代码或 C 代码吗?

I'm studying data structures and linked lists, but I'm not getting the concept of how to make a copy of a linked list. Can someone explain this, possibly using pseudocode or C code?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

拥抱影子 2024-10-23 23:19:30

复制链表的逻辑是递归的,并且基于以下观察:

  1. 空列表的克隆是空列表。
  2. 具有第一个节点 x 和其余节点 xs 的列表的克隆是 x 的副本前置到 xs 的克隆。

如果用 C++ 对链表进行编码,这会非常干净:

struct Node {
    int value;
    Node* next;
};

Node* Clone(Node* list) {
    if (list == NULL) return NULL;

    Node* result = new Node;
    result->value = list->value;
    result->next = Clone(list->next);
    return result;
}

The logic for duplicating a linked list is recursive and based on the following observations:

  1. The clone of the empty list is the empty list.
  2. The clone of a list with first node x and remaining nodes xs is a copy of x prepended to a clone of xs.

If you encode the linked list in C++, this can be very clean:

struct Node {
    int value;
    Node* next;
};

Node* Clone(Node* list) {
    if (list == NULL) return NULL;

    Node* result = new Node;
    result->value = list->value;
    result->next = Clone(list->next);
    return result;
}
梦幻的味道 2024-10-23 23:19:30

您了解如何向现有列表添加新节点吗?您了解如何遍历(即迭代)列表吗?复制列表只是同时执行这两个操作(遍历ListA;对于每个元素,复制该元素并将其作为新节点添加到ListB)。

Do you understand how to add a new node to an existing list? And do you understand how to traverse (i.e. iterate over) a list? Copying a list is just performing both of these operations simultaneously (traverse ListA; for each element, copy the element and add it as a new node to ListB).

囚你心 2024-10-23 23:19:30

这篇文章的答案已给出并被接受 - 一切都很好!
但是,如果有人正在C#中寻找迭代方法,这里是:

Node类:

public class Node
{
    public Node(int val)
    {
        Val = val;
    }

    public Node Next { get; set; }
    public int Val { get; }
}

这是迭代实现:

public Node CopyLinkedListIteratively(Node head)
{
    // validation:
    if (head == null) return null;

    // current node is always a 'new' node with value.
    Node currentNode = new Node(head.Val);

    // set copyList and previous to current node to start with - which is true at this point in time!
    Node copyList = currentNode;
    Node previous = currentNode;
    
    // move head one step forward as we already have copied its value.
    head = head.Next;

    // keep moving until we hit a null reference which is the end.
    while (head != null)
    {
        currentNode = new Node(head.Val); // create a new node every time as we move forward.
        previous.Next = currentNode; // set previous node's next to current node as previous node itself is one step behind the current.
        previous = previous.Next; // move prev pointer forward
        head = head.Next; // move head pointer forward as well
    }

    // return the reference to copyList.
    // copyList and previous both started off pointing to the currentNode, then in the while loop
    // previous kept moving forward till all nodes are copied.
    // copyList reference never moved from its position so its still pointing at the start.
    return copyList;
}

时间复杂度:O(n )

空间复杂度:O(n)

,其中 n = 链表中的节点数。

个人偏好使用递归或迭代方法,但是我建议在使用递归时考虑函数调用堆栈。

单元测试:

[Test]
public void CopyLinkedListIterativelyTest()
{
    Node head = new Node(1);
    head.Next = new Node(2);
    head.Next.Next = new Node(3);
    head.Next.Next.Next = new Node(4);
    head.Next.Next.Next.Next = new Node(5);

    var actual = runner.CopyLinkedListIteratively(head);

    while (actual != null)
    {
        Assert.AreEqual(head.Val, actual.Val);
        actual = actual.Next;
        head = head.Next;
    }
}

The answer to this post has been given and accepted - all good!
However, if someone is looking for an iterative approach in C#, here it is:

The Node class:

public class Node
{
    public Node(int val)
    {
        Val = val;
    }

    public Node Next { get; set; }
    public int Val { get; }
}

Here is the iterative implementation:

public Node CopyLinkedListIteratively(Node head)
{
    // validation:
    if (head == null) return null;

    // current node is always a 'new' node with value.
    Node currentNode = new Node(head.Val);

    // set copyList and previous to current node to start with - which is true at this point in time!
    Node copyList = currentNode;
    Node previous = currentNode;
    
    // move head one step forward as we already have copied its value.
    head = head.Next;

    // keep moving until we hit a null reference which is the end.
    while (head != null)
    {
        currentNode = new Node(head.Val); // create a new node every time as we move forward.
        previous.Next = currentNode; // set previous node's next to current node as previous node itself is one step behind the current.
        previous = previous.Next; // move prev pointer forward
        head = head.Next; // move head pointer forward as well
    }

    // return the reference to copyList.
    // copyList and previous both started off pointing to the currentNode, then in the while loop
    // previous kept moving forward till all nodes are copied.
    // copyList reference never moved from its position so its still pointing at the start.
    return copyList;
}

Time complexity: O(n)

Space complexity: O(n)

where n = number of nodes in the linked list.

Its personal preference to use recursive or iterative approach, however I would suggest to think about the function call stack when using recursive.

Unit test:

[Test]
public void CopyLinkedListIterativelyTest()
{
    Node head = new Node(1);
    head.Next = new Node(2);
    head.Next.Next = new Node(3);
    head.Next.Next.Next = new Node(4);
    head.Next.Next.Next.Next = new Node(5);

    var actual = runner.CopyLinkedListIteratively(head);

    while (actual != null)
    {
        Assert.AreEqual(head.Val, actual.Val);
        actual = actual.Next;
        head = head.Next;
    }
}
迷乱花海 2024-10-23 23:19:30

Java 版本的递归克隆解决方案。

伪代码:

  1. 每个节点都是一个新的初始化节点
  2. 递归调用clone函数为每个节点创建一个新节点

程序[JAVA]:

public class Program
{
    public static void main(String[] args) {
        ListNode node5 = new ListNode(5,null);
        ListNode node4 = new ListNode(4,node5);
        ListNode node3 = new ListNode(3,node4);
        ListNode node2 = new ListNode(2,node3);
        ListNode node1 = new ListNode(1,node2);
        ListNode head = node1;
        //Printing to display the address
        System.out.println(head +"->" + head.next + "->" + head.next.next + "->" + head.next.next.next + "->" + head.next.next.next.next + "->" + head.next.next.next.next.next);
        ListNode newClone = Clone(head);
        while(newClone.next != null){
            System.out.print(newClone.getAddress() + "->");
            newClone = newClone.next;
        }
    }

    public static class ListNode {
        int val;
        ListNode next;
        ListNode() {}
        ListNode(int val) { this.val = val; }
        ListNode(int val, ListNode next) { this.val = val; this.next = next; }
        ListNode getAddress() {return this; }
    }

    public static ListNode Clone(ListNode nextNode) {
        if (nextNode == null) return nextNode;    
        ListNode newNode = new ListNode();
        newNode.val = nextNode.val;
        newNode.next = Clone(nextNode.next);
        return newNode;
    }
}

Java version of the recursive clone solution.

Pseudocode :

  1. Every node is a new initialized node
  2. Recursively call the clone function to create a new node for every node

Program [JAVA] :

public class Program
{
    public static void main(String[] args) {
        ListNode node5 = new ListNode(5,null);
        ListNode node4 = new ListNode(4,node5);
        ListNode node3 = new ListNode(3,node4);
        ListNode node2 = new ListNode(2,node3);
        ListNode node1 = new ListNode(1,node2);
        ListNode head = node1;
        //Printing to display the address
        System.out.println(head +"->" + head.next + "->" + head.next.next + "->" + head.next.next.next + "->" + head.next.next.next.next + "->" + head.next.next.next.next.next);
        ListNode newClone = Clone(head);
        while(newClone.next != null){
            System.out.print(newClone.getAddress() + "->");
            newClone = newClone.next;
        }
    }

    public static class ListNode {
        int val;
        ListNode next;
        ListNode() {}
        ListNode(int val) { this.val = val; }
        ListNode(int val, ListNode next) { this.val = val; this.next = next; }
        ListNode getAddress() {return this; }
    }

    public static ListNode Clone(ListNode nextNode) {
        if (nextNode == null) return nextNode;    
        ListNode newNode = new ListNode();
        newNode.val = nextNode.val;
        newNode.next = Clone(nextNode.next);
        return newNode;
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文