2010-07-18 2 views
8

J'ai une liste de valeurs (1-dimensionnelle) et je voudrais connaître la meilleure structure de données/algorithme pour trouver le plus proche d'une valeur de requête que j'ai. La plupart des solutions (toutes?) Que j'ai trouvées pour les questions ici concernent 2 dimensions ou plus. Quelqu'un peut-il me suggérer l'approche de mon cas? Mon instinct me dit de trier les données et d'utiliser la recherche binaire d'une manière ou d'une autre. En passant, il n'y a aucune limite sur la construction ou le temps d'insertion pour n'importe quel arbre nécessaire, alors probablement quelqu'un peut suggérer un arbre meilleur que simplement une liste triée.Meilleure structure de données pour le plus proche voisin dans 1 dimension

+2

un BST en combinaison avec la recherche binaire sonne parfaitement bien pour moi. –

Répondre

9

Si vous avez besoin de quelque chose de plus rapide que O (log (n)), que vous pouvez facilement obtenir avec un tableau trié ou une recherche binaire arbre, vous pouvez utiliser un van Emde Boas Tree. Les arbres vEB vous donnent O (log (log (n))) pour rechercher l'élément le plus proche de chaque côté.

+7

Comparé à un tableau trié, un arbre vEB est un portique complexe. À moins que les points ne soient très denses, les effets de la hiérarchie de la mémoire sont susceptibles d'effacer la différence théorique entre O (log n) et O (log log n), puis certains. – user382751

+0

C'est impressionnant. J'accepte cette réponse comme étant la meilleure théorie jusqu'à présent pour les énormes données linéaires. Bien que de façon réaliste, je vais utiliser la liste triée/recherche binaire qui devrait suffire à mes fins. –

1

Triez la liste et utilisez la recherche binaire pour trouver l'élément que vous recherchez, puis comparez vos voisins gauche et droit. Vous pouvez utiliser un tableau qui est un accès O (1).

Quelque chose comme:

int nearest(int[] list, int element) { 

    sort(list); 
    int idx = binarySearch(element, list); 

    // make sure you are accessing elements that exist 
    min = (element - list[idx-1] <= list[idx+1] - element) ? idx-1 : idx+1; 

    return list[min]; 
} 

Ceci est O (n log n), qui sera amorti si vous allez effectuer des hauts look.

EDIT: Pour que vous auriez à déplacer le tri de cette méthode

+0

Tout d'abord, je ne vois toujours pas comment la fonction min retourne l'élément correct. Vous ne comparez même pas avec le point de requête. Deuxièmement, le coût amorti ne semble pas améliorer quelque chose ... vous ne devriez pas trier la liste lors de l'exécution des requêtes. Vous devriez le faire seulement en modifiant la collection de points. –

+0

@ Eyal-Schneider Merci – quantumSoup

+0

en fait, si vous déplacez le tri la recherche binaire devrait être O (log n) –

1

Comme vous l'avez mentionné, la façon la plus rapide et la plus simple devrait être trier les données et à la recherche puis pour le voisin de gauche et à droite d'un point de données.

2

Si le temps d'insertion n'est pas pertinent, la recherche binaire sur un tableau trié est le moyen le plus simple d'atteindre l'heure de requête O (log N). Chaque fois qu'un article est ajouté, tout est trié. Pour chaque requête, effectuez une recherche binaire. Si une correspondance est trouvée, retournez-la. Sinon, la recherche binaire doit renvoyer l'index de l'élément, où il aurait dû être inséré. Utilisez cet index pour vérifier les deux éléments voisins et déterminer lequel d'entre eux est le plus proche du point de requête. Je suppose qu'il y a des solutions avec O (1) temps

Je vais essayer de penser à un qui n'implique pas trop d'utilisation de la mémoire ...

+0

Cela devrait être intéressant. Je ne vois pas comment vous pouvez trouver le voisin le plus proche dans le temps, indépendamment de la taille de l'ensemble de données. Donc, si vous avez une solution comme celle-ci, veuillez l'ajouter ici, bien que ce soit une curiosité plus académique à ce stade. –

+1

@Muhammad: C'est un compromis entre la complexité temporelle et la complexité de l'espace. En supposant que vous n'avez pas de problèmes d'espace (ou que la plage de valeurs ne soit pas trop grande), vous pouvez simplement créer un grand tableau contenant à la position k le point le plus proche de la valeur k.Cela a complexité de temps de requête O (1) et la complexité de l'espace O (max-min). Je ne suis pas sûr de la façon dont la complexité de l'espace peut être améliorée, cependant ... –

+0

Excellente idée. Cela ressemble donc à une implémentation de la table findup de la fonction find nearest. Le problème est que tout hashing auquel je peux penser car ce cas le transformera pour quelque chose O (log n). –