J'ai une gamme de flotteurs, triés du plus petit au plus grand et j'ai besoin de pouvoir choisir le flotteur le plus proche supérieur ou inférieur à une valeur d'entrée passée. Cette valeur d'entrée n'est pas nécessairement présente comme une valeur dans la matrice.
Une approche naïve serait de faire une simple recherche linéaire à travers la matrice. Cela pourrait ressembler à ceci:
void FindClosestFloatsInArray( float input, std::vector<float> array,
float *min_out, float *max_out )
{
assert( input >= array[0] && input < array[ array.size()-1 ] );
for( int i = 1; i < array.size(); i++ )
{
if ( array[i] >= input )
{
*min = array[i-1];
*max = array[i];
}
}
}
Mais évidemment, car le tableau devient plus grand, cela deviendra plus lent et plus lent.
Quelqu'un a-t-il une idée d'un algorithme qui me permettrait de trouver ces données plus de manière optimale? Je suis déjà passée à une recherche binaire, qui a une amélioration quelque peu, mais cela reste beaucoup plus lent que je le souhaiterais, et comme je ne cherche pas réellement une valeur spécifique qui existe dans le tableau, elle ne peut jamais se terminer. de bonne heure.
Plus d'informations: Les valeurs de points flottants dans la matrice ne sont pas nécessairement distribuées uniformément (c'est-à-dire que la matrice pourrait être constituée des valeurs "1.f, 2.f, 3.f, 4.f, 100.f, 1200.f, 1200.f , 1203.f, 1400.f ".
Je fais cette opération des centaines de milliers de fois, mais je peux faire une quantité de pré-traitement sur le tableau de flotteurs, si cela améliorera le temps de recherche. Je peux absolument changer pour utiliser autre chose qu'un vecteur pour les stocker, si cela vous aidera.
Le code de la question (une recherche linéaire), comme vous l'avez souligné à juste titre, cela va se lendre pour de grandes matrices de flottaison. Techniquement, c'est O(n) où n est le nombre de valeurs de flotteur dans votre tableau.
En général, le mieux que vous puissiez faire pour trouver une valeur dans un tableau commandé est une recherche d'arborescence récursive de quelque nature que ce soit (par exemple, la recherche binaire), auquel cas vous pouvez obtenir une heure de recherche O (log n) dans le nombre d'éléments. dans votre tableau. O (journal n) est beaucoup meilleur que O(n) pour les grandes valeurs de n.
Mon approche suggérée serait donc une simple recherche binaire de la matrice , c'est-à-dire
C'est un algorithme O (log n) qui devrait être assez rapide pour presque toutes les situations. Intuitivement, cela fonctionne de moitié la plage à rechercher à chaque étape jusqu'à ce que vous trouviez la valeur correcte.
Il est vraiment difficile de baisser la recherche binaire simple, donc si vous l'avez déjà implémenté correctement, vous êtes peut-être assez proche de votre optimisme déjà. Toutefois, si vous connaissez les distributions des données et/ou si vous avez une gamme limitée de valeurs de recherche (x), il reste encore d'autres astuces plus avancées que vous pouvez essayer:
Toutefois, à moins que vous ne soyez dans une situation très particulière, je vous recommande probablement de coller avec la simple recherche binaire. Les raisons:
Cela semble assez simple:
Faites une recherche binaire du flotteur que vous souhaitez lier - O (log n).
Ensuite, l'élément à gauche est la limite inférieure et l'élément à droite est la limite supérieure.
La réponse évidente est de stocker les flotteurs dans un arbre . Soutenir les opérations "précédentes" et "suivantes" sont triviales dans un arbre. Donc, faites simplement une "suivante" sur votre valeur, puis faites un "précédent" sur la valeur que vous trouvez dans la première étape.