In addition to the next pointer, a single-chain table also has a random pointer pointing to any element in the linked list.
How to copy such a linked list?
It is easy to copy a chain through next. The difficulty is how to properly set the random pointer in the new linked list. For this purpose, we need to establish a connection between the old linked list and the corresponding node of the new linked list. In addition to the linked list, we can use extra pointers in the linked list to link up the storage space.
Let's just move on to the code. It is only possible that a pointer is not necessarily used for some purpose, but the idea is similar.
#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 pointervoid 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 listvoid 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;}