Il existe un algorithme simple pour choisir un élément au hasard, où les éléments ont des poids individuels :
1) calculer la somme de tous les poids
2) choisir un nombre aléatoire égal ou supérieur à 0 et inférieur à la somme des poids.
3) Passez en revue les éléments un par un, en soustrayant leur poids de votre nombre aléatoire, jusqu'à ce que vous obteniez l'élément pour lequel le nombre aléatoire est inférieur à son poids.
Pseudo-code illustrant ceci :
int sum_of_weight = 0;
for(int i=0; i<num_choices; i++) {
sum_of_weight += choice_weight[i];
}
int rnd = random(sum_of_weight);
for(int i=0; i<num_choices; i++) {
if(rnd < choice_weight[i])
return i;
rnd -= choice_weight[i];
}
assert(!"should never get here");
Cela devrait être facile à adapter à vos conteneurs de boost et autres.
Si vos poids sont rarement modifiés mais que vous en choisissez souvent un au hasard, et pour autant que votre conteneur stocke des pointeurs vers les objets ou qu'il compte plus de quelques dizaines d'éléments (en gros, vous devez établir un profil pour savoir si cela vous aide ou vous gêne), alors il y a une optimisation :
En stockant la somme des poids cumulés dans chaque élément, vous pouvez utiliser une fonction recherche binaire pour choisir l'élément correspondant au poids du prélèvement.
Si vous ne connaissez pas le nombre d'éléments de la liste, il existe un algorithme très soigné appelé échantillonnage de réservoirs qui peuvent être adaptés pour être pondérés.