C++ Program For Selecting A Random Node From A Singly Linked List - GeeksforGeeks

28 Dec, 2021
Given a singly linked list, select a random node from the linked list (the probability of picking a node should be 1/N if there are N nodes in the list). You are given a random number generator.Below is a Simple Solution:
Count the number of nodes by traversing the list.Traverse the list again and select every node with probability 1/N. The selection can be done by generating a random number from 0 to N-i for i’th node, and selecting the i’th node only if the generated number is equal to 0 (or any other fixed number from 0 to N-i).
Count the number of nodes by traversing the list.
Traverse the list again and select every node with probability 1/N. The selection can be done by generating a random number from 0 to N-i for i’th node, and selecting the i’th node only if the generated number is equal to 0 (or any other fixed number from 0 to N-i).
We get uniform probabilities with the above schemes.  
i = 1, probability of selecting first node = 1/N
i = 2, probability of selecting second node =
                   [probability that first node is not selected] * 
                   [probability that second node is selected]
                  = ((N-1)/N)* 1/(N-1)
                  = 1/N  
Similarly, probabilities of other selecting other nodes is 1/NThe above solution requires two traversals of linked list. 
How to select a random node with only one traversal allowed? The idea is to use Reservoir Sampling. Following are the steps. This is a simpler version of Reservoir Sampling as we need to select only one key instead of k keys.
(1) Initialize result as first node
    result = head->key 
(2) Initialize n = 2
(3) Now one by one consider all nodes from 2nd node onward.
    (a) Generate a random number from 0 to n-1. 
        Let the generated random number is j.
    (b) If j is equal to 0 (we could choose other fixed numbers 
        between 0 to n-1), then replace result with the current node.
    (c) n = n+1
    (d) current = current->next
Below is the implementation of above algorithm.
C++
/* C++ program to randomly select    a node from a singly linked list */#include<stdio.h>#include<stdlib.h>#include <time.h>#include<iostream>using namespace std;  // Link list node class Node{    public:    int key;    Node* next;    void printRandom(Node*);    void push(Node**, int);      };  // A reservoir sampling-based function to // print a random node from a linked listvoid Node::printRandom(Node *head){    // If list is empty    if (head == NULL)    return;      // Use a different seed value so that     // we don't get same result each time     // we run this program    srand(time(NULL));      // Initialize result as first node    int result = head->key;      // Iterate from the (k+1)th element     // to nth element    Node *current = head;    int n;    for (n = 2; current != NULL; n++)    {        // Change result with         // probability 1/n        if (rand() % n == 0)        result = current->key;          // Move to next node        current = current->next;    }      cout << "Randomly selected key is " <<              result;}  /* A utility function to create    a new node */Node* newNode(int new_key){    // Allocate node     Node* new_node =           (Node*) malloc(sizeof( Node));      /// Put in the key     new_node->key = new_key;    new_node->next = NULL;      return new_node;}  /* A utility function to insert a    node at the beginning of linked list */void Node:: push(Node** head_ref,                  int new_key){    // Allocate node     Node* new_node = new Node;      // Put in the key     new_node->key = new_key;      // Link the old list off the     // new node     new_node->next = (*head_ref);      // Move the head to point to     // the new node     (*head_ref) = new_node;}  // Driver codeint main(){    Node n1;    Node *head = NULL;    n1.push(&head, 5);    n1.push(&head, 20);    n1.push(&head, 4);    n1.push(&head, 3);    n1.push(&head, 30);    n1.printRandom(head);    return 0;}// This code is contributed by SoumikMondal
Note that the above program is based on the outcome of a random function and may produce different output.
How does this work? Let there be total N nodes in list. It is easier to understand from the last node.The probability that the last node is result simply 1/N [For last or N’th node, we generate a random number between 0 to N-1 and make the last node as a result if the generated number is 0 (or any other fixed number]The probability that second last node is result should also be 1/N.  
The probability that the second last node is result 
          = [Probability that the second last node replaces result] X 
            [Probability that the last node doesn't replace the result] 
          = [1 / (N-1)] * [(N-1)/N]
          = 1/N
Similarly, we can show probability for 3rd last node and other nodes.Please refer complete article on Select a Random Node from a Singly Linked List for more details!
C++ Programs
Linked List
Randomized
Linked List
Writing code in comment?
Please use ide.geeksforgeeks.org,
generate link and share the link here.
Comments
Old Comments
Passing a function as a parameter in C++
Program to implement Singly Linked List in C++ using class
cout in C++
Pi(π) in C++ with Examples
Const keyword in C++
Linked List | Set 1 (Introduction)
Linked List | Set 2 (Inserting a node)
Reverse a linked list
Stack Data Structure (Introduction and Program)
Linked List | Set 3 (Deleting a node)