/// <summary> /// Returns an item chosen randomly by weight (higher weights are more likely), /// and replaces it so that it can be chosen again /// </summary> public TKey NextWithReplacement() { VerifyHaveItemsToChooseFrom(); Node currentNode = _root; long randomNumber = _random.NextLong(0, TotalWeight) + 1; //[1, TotalWeight] inclusive while (true) { if (currentNode.left.subtreeWeight >= randomNumber) { currentNode = currentNode.left; } else { randomNumber -= currentNode.left.subtreeWeight; if (currentNode.right.subtreeWeight >= randomNumber) { currentNode = currentNode.right; } else { return(currentNode.key); } } } }
/// <summary> /// Returns an item chosen randomly by weight (higher weights are more likely), /// and replaces it so that it can be chosen again /// </summary> public TKey NextWithReplacement() { VerifyHaveItemsToChooseFrom(); if (_listNeedsRebuilding) { RebuildProbabilityList(); } //Choose a random box, then flip a biased coin (represented by choosing a number of balls within the box) int randomIndex = _random.Next(_probabilityBoxes.Count); long randomNumBalls = _random.NextLong(_heightPerBox) + 1; if (randomNumBalls <= _probabilityBoxes[randomIndex].NumBallsInBox) { return(_probabilityBoxes[randomIndex].Key); } else { return(_probabilityBoxes[randomIndex].Alias); } }