zoukankan      html  css  js  c++  java
  • 复制一个带random指针的链表

    一个单链表,其中除了next指针外,还有一个random指针,指向链表中的任意某个元素。

    如何复制这样一个链表呢?

    通过next来复制一条链是很容易的,问题的难点在于如何恰当地设置新链表中的random指针。从这个目的出发,我们要在旧链表和新链表的对应节点之间建立联系。除了在链表之外来另外开辟空间存储的方法之外,我们可以利用链表中多余的指针来连接起来。

    不扯淡了,上代码。这里的只是一种可能,不一定要某个指针一定要某种用途,但是思想是类似的。

    #include <cstdio>
    #include <cstdlib>
    #include <ctime>
    #include <cassert>
    using namespace std;
    
    struct Node {
        int val;
        struct Node *next;
        struct Node *random;
        Node(int val_, Node *next_, Node *random_)
            : val(val_), next(next_), random(random_) { }
        Node (int val_)
            : val(val_), next(NULL), random(NULL) { }
        Node () // for the head nodes.
            : val(-1), next(NULL), random(NULL) { }
    };
    
    #define NR_NODES    10
    
    // Setup a linked-list with random pointer
    void setup_random_linked_list(struct Node *head)
    {
        Node *curr;
        Node *all_nodes[NR_NODES];
        int i;
    
        // allocate all the nodes.
        for (i = NR_NODES - 1; i >= 0; i--) {
            curr = new Node(i, head->next, NULL);
            head->next = curr;
            all_nodes[i] = curr;
        }
        // setup the random pointers in each node.
        srand(time(0));
        curr = head->next;
        while (curr) {
            curr->random = all_nodes[rand() % NR_NODES];
            curr = curr->next;
        }
    }
    
    // free the list
    void free_random_linked_list(struct Node *head)
    {
        Node *curr, *temp;
    
        curr = head->next;
        while (curr) {
            temp = curr->next;
            delete curr;
            curr = temp;
        }
    }
    
    void print_random_linked_list(struct Node *head)
    {
        Node *curr;
        curr = head->next;
        while (curr) {
            printf("%d ", curr->val);
            curr = curr->next;
        }
        printf("\n");
        curr = head->next;
        while (curr) {
            printf("%d ", curr->random->val);
            curr = curr->next;
        }
        printf("\n");
    }
    
    // copy from list @src to list @dst.
    void copy_random_linked_list(struct Node *dst, struct Node *src)
    {
        // Image that there're 4 parallel lists...
    
        Node *curr_src, *curr_dst;
        // 1, duplicate the list.
        curr_src = src->next;
        while (curr_src) {
            // copy the node
            curr_dst = new Node(curr_src->val);
            // 'random' vertically goes down, while 'next' goes up to original's random.
            curr_dst->next = curr_src->random;
            curr_src->random = curr_dst;
            // move forward
            curr_src = curr_src->next;
        }
        // 2, Now that 'random' comes vertically form the original list to the duplicated list, 
        // and that 'next' points to the random node in the old list,
        // use that to setup the 'random' pointer in the new list.
        curr_src = src->next;
        dst->next = curr_src->random; // follow the head node.
        while (curr_src) {
            curr_dst = curr_src->random;
            // setup 'random' relationship via the original list.
            curr_dst->random = curr_dst->next->random;
            // move forward
            curr_src = curr_src->next;
        }
        // 3, now the vertical links still exist, and 'next's in the new list point to 'random' 
        // in the original list, go through the lists to repair both.
        curr_src = src->next;
        while (curr_src) {
            curr_dst = curr_src->random;
            // setup 'next' relationship via the original list.
            curr_src->random = curr_dst->next;
            curr_dst->next = curr_src->next ? curr_src->next->random : NULL;
            // move forward
            curr_src = curr_src->next;
        }
    }
    
    int main(int argc, char *argv[])
    {
        Node head, head2;
    
        setup_random_linked_list(&head);
        printf("the original list before copying: \n");
        print_random_linked_list(&head);
    
        copy_random_linked_list(&head2, &head);
        printf("finished copying random linked list.\n");
    
        printf("the original list after copying: \n");
        print_random_linked_list(&head);
        printf("and the duplicated list: \n");
        print_random_linked_list(&head2);
    
        free_random_linked_list(&head);
        free_random_linked_list(&head2);
        return 0;
    }
    
  • 相关阅读:
    JS之函数声明与表达式
    任重道远!
    Java_Notes01
    Android_Application Fundamentals
    Android_Activity
    Android
    Linux下的实模式和保护模式
    spring注解原理
    开启aix SFTP日志 是否和链接SFTP有关呢
    Apache版本兼容性问题
  • 原文地址:https://www.cnblogs.com/qsort/p/2107829.html
Copyright © 2011-2022 走看看