C++ Program For Selecting A Random Node From A Singly Linked List
Last Updated :
17 Aug, 2023
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).
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/N
The 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 list
void 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 code
int 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.
The algorithm implemented in the code is called "Reservoir Sampling". It is a technique for selecting a random item from a large data stream with equal probability.
Here's an algorithm to randomly select a node from a singly linked list in C++:
1.Calculate the length of the linked list, let's call it n.
2.Generate a random number in the range [0, n-1]. This can be done using the rand() function in C++.
3.Start at the head of the linked list and traverse the linked list until the randomly generated index is reached.
4.Return the node at the randomly generated index.
Here's some sample code to implement the algorithm in C++:
C++
#include <iostream>
#include <cstdlib>
#include <ctime>
struct Node {
int data;
Node* next;
};
int getLength(Node* head) {
int count = 0;
Node* current = head;
while (current != nullptr) {
count++;
current = current->next;
}
return count;
}
Node* getRandomNode(Node* head) {
int length = getLength(head);
int randomIndex = rand() % length;
Node* current = head;
for (int i = 0; i < randomIndex; i++) {
current = current->next;
}
return current;
}
int main() {
srand(time(0));
Node* head = new Node{1, nullptr};
head->next = new Node{2, nullptr};
head->next->next = new Node{3, nullptr};
head->next->next->next = new Node{4, nullptr};
Node* randomNode = getRandomNode(head);
std::cout << "Random node: " << randomNode->data << std::endl;
return 0;
}
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!
Similar Reads
C++ Program For Cloning A Linked List With Next And Random Pointer- Set 2
We have already discussed 2 different ways to clone a linked list. In this post, one more simple method to clone a linked list is discussed. Recommended: Please solve it on "PRACTICE" first, before moving on to the solution. The idea is to use Hashing. Below is algorithm. Traverse the original link
4 min read
C++ Program For Recursive Selection Sort For Singly Linked List - Swapping Node Links
Given a singly linked list containing n nodes. The problem is to sort the list using the recursive selection sort technique. The approach should be such that it involves swapping node links instead of swapping node data. Examples: Input: 10 -> 12 -> 8 -> 4 -> 6 Output: 4 -> 6 -> 8
4 min read
C++ Program For Writing A Function To Get Nth Node In A Linked List
Write a C++ Program to GetNth() function that takes a linked list and an integer index and returns the data value stored in the node at that index position. Example: Input: 1->10->30->14, index = 2Output: 30 The node at index 2 is 30Recommended: Please solve it on "PRACTICE" first, before m
4 min read
C++ Program For Segregating Even And Odd Nodes In A Linked List
Given a Linked List of integers, write a function to modify the linked list such that all even numbers appear before all the odd numbers in the modified linked list. Also, keep the order of even and odd numbers the same. Examples: Input: 17->15->8->12->10->5->4->1->7->6-
7 min read
C++ Program For Rotating A Linked List
Given a singly linked list, rotate the linked list counter-clockwise by k nodes. Where k is a given positive integer. For example, if the given linked list is 10->20->30->40->50->60 and k is 4, the list should be modified to 50->60->10->20->30->40. Assume that k is smal
6 min read
C++ Program For Removing Duplicates From A Sorted Linked List
Write a function that takes a list sorted in non-decreasing order and deletes any duplicate nodes from the list. The list should only be traversed once. For example if the linked list is 11->11->11->21->43->43->60 then removeDuplicates() should convert the list to 11->21->43-
9 min read
C++ Program For Reversing A Doubly Linked List
Given a Doubly Linked List, the task is to reverse the given Doubly Linked List. See below diagrams for example. (a) Original Doubly Linked List (b) Reversed Doubly Linked List Here is a simple method for reversing a Doubly Linked List. All we need to do is swap prev and next pointers for all nodes
5 min read
C++ Program For Swapping Nodes In A Linked List Without Swapping Data
Given a linked list and two keys in it, swap nodes for two given keys. Nodes should be swapped by changing links. Swapping data of nodes may be expensive in many situations when data contains many fields. It may be assumed that all keys in the linked list are distinct. Examples: Input : 10->15-
5 min read
C++ Program For Writing A Function To Delete A Linked List
Algorithm For C++:Iterate through the linked list and delete all the nodes one by one. The main point here is not to access the next of the current pointer if the current pointer is deleted. Implementation: C++ // C++ program to delete a linked list #include <bits/stdc++.h> using namespace std
2 min read
C++ Program For Removing Duplicates From An Unsorted Linked List
Write a removeDuplicates() function that takes a list and deletes any duplicate nodes from the list. The list is not sorted. For example if the linked list is 12->11->12->21->41->43->21 then removeDuplicates() should convert the list to 12->11->21->41->43. Recommended:
4 min read