web-dev-qa-db-fra.com

Avantages des arbres de recherche binaires sur les tables de hachage

Quels sont les avantages des arbres de recherche binaires par rapport aux tables de hachage?

Les tables de hachage peuvent rechercher n’importe quel élément à l’époque de Theta (1) et il est tout aussi facile d’ajouter un élément ... mais je ne suis pas sûr des avantages qui en découlent.

90
Devoted

N'oubliez pas que les arbres de recherche binaires (basés sur des références) utilisent efficacement la mémoire. Ils ne réservent pas plus de mémoire que nécessaire.

Par exemple, si une fonction de hachage a une plage R(h) = 0...100, vous devez allouer un tableau de 100 éléments (pointeurs), même si vous ne faites que hacher 20 éléments. Si vous utilisiez un arbre de recherche binaire pour stocker les mêmes informations, vous alloueriez seulement autant d’espace que nécessaire, ainsi que des métadonnées sur les liens.

83
Christian Mann

Un avantage que personne d’autre n’a souligné est que l’arbre de recherche binaire vous permet d’effectuer des recherches par plage de manière efficace.

Pour illustrer mon idée, je souhaite présenter un cas extrême. Supposons que vous souhaitiez obtenir tous les éléments dont les clés sont comprises entre 0 et 5 000. Et en fait, il n'y a qu'un seul élément de ce type et 10 000 autres éléments dont les clés ne sont pas dans la plage. BST peut effectuer des recherches de plage assez efficacement car il ne recherche pas un sous-arbre impossible à obtenir.

Alors, comment pouvez-vous effectuer des recherches par plage dans une table de hachage? Vous devez soit itérer chaque espace du compartiment, qui est O (n), soit rechercher si chacun des nombres 1,2,3,4 ... jusqu'à 5000 existe. (que diriez-vous des clés entre 0 et 5000 sont un ensemble infini? par exemple les clés peuvent être décimales)

106
Alex

Un "avantage" d'un arbre binaire est qu'il peut être parcouru pour lister tous les éléments dans l'ordre. Ce n'est pas impossible avec une table de hachage mais ce n'est pas une opération normale mais une conception dans une structure hachée.

74
NealB

En plus de tous les autres bons commentaires:

En règle générale, les tables de hachage ont un meilleur comportement de cache, nécessitant moins de lectures de mémoire que les arborescences binaires. Pour une table de hachage, une seule lecture est normalement nécessaire avant d'avoir accès à une référence contenant vos données. L'arbre binaire, s'il s'agit d'une variante équilibrée, nécessite quelque chose dans l'ordre de k * lg (n) memory lit pour une constante k.

D'autre part, si un ennemi connaît votre fonction de hachage, il peut forcer votre table de hachage à faire des collisions, ce qui nuit grandement à ses performances. La solution de contournement consiste à choisir la fonction de hachage de manière aléatoire dans une famille, mais un BST ne présente pas cet inconvénient. En outre, lorsque la pression de la table de hachage augmente trop, vous avez souvent tendance à agrandir et à réaffecter la table de hachage, ce qui peut être une opération coûteuse. La BST a un comportement plus simple ici et n'a pas tendance à allouer soudainement beaucoup de données et à effectuer une opération de rehashing.

Les arbres ont tendance à être la structure de données moyenne ultime. Ils peuvent agir en tant que listes, peuvent être facilement divisés pour un fonctionnement en parallèle, avoir une extraction, une insertion et une recherche rapides de l'ordre de O (lg n) . Ils ne font rien en particulier bien, mais ils n’ont pas non plus un comportement excessivement mauvais.

Enfin, les BST sont beaucoup plus faciles à implémenter dans les langages fonctionnels (purs) que dans les tables de hachage et ne nécessitent pas de mises à jour destructives (l'argument persistence de Pascal ci-dessus).

50

Les principaux avantages d'un arbre binaire par rapport à une table de hachage sont que l'arbre binaire vous donne deux opérations supplémentaires que vous ne pouvez pas effectuer (facilement, rapidement) avec une table de hachage.

  • trouver l'élément le plus proche de (pas nécessairement égal à) une valeur de clé arbitraire (ou plus proche au-dessus/au-dessous)

  • parcourir le contenu de l'arbre dans un ordre trié

Les deux sont connectés - l'arborescence binaire conserve son contenu dans un ordre de tri, de sorte que les choses qui nécessitent cet ordre de tri sont faciles à faire.

25
Chris Dodd

Un arbre de recherche binaire (équilibré) présente également l'avantage que sa complexité asymptotique est en fait une limite supérieure, tandis que les temps "constants" des tables de hachage sont amortis: Si vous avez une fonction de hachage inadéquate, vous risquez de passer au temps linéaire plutôt que constant.

15
jamesnvc

Une table de hachage occupera plus de place lors de sa création: des emplacements seront disponibles pour les éléments non encore insérés (qu'ils soient ou non insérés), un arbre de recherche binaire sera aussi grand que nécessaire être. De plus, quand une table de hachage a besoin de plus d'espace, le développement d'une autre structure pourrait prend beaucoup de temps, mais cela dépend de la mise en œuvre.

Un arbre de recherche binaire peut être implémenté avec une interface persistent , dans laquelle un nouvel arbre est renvoyé, mais l’ancien arbre continue d’exister. Mis en œuvre avec soin, les anciens et les nouveaux arbres partagent la plupart de leurs nœuds. Vous ne pouvez pas faire cela avec une table de hachage standard.

8
Pascal Cuoq

La recherche et l’insertion dans une arborescence binaire sont plus lentes, mais elle possède la fonctionnalité très agréable de traversée des infixes qui signifie essentiellement que vous pouvez effectuer une itération à travers les nœuds de l’arbre dans un ordre trié.

Itérer dans les entrées d'une table de hachage n'a pas beaucoup de sens car elles sont toutes dispersées dans la mémoire.

6

From Cracking the Coding Interview, 6ème édition

Nous pouvons implémenter la table de hachage avec un arbre de recherche binaire équilibré (BST). Cela nous donne un temps de recherche O (log n). L'avantage de ceci est potentiellement d'utiliser moins d'espace, puisque nous n'allouons plus un grand tableau. Nous pouvons également parcourir les clés dans l’ordre, ce qui peut parfois être utile. 

4
Guy Kahlon

Les BST fournissent également les opérations "findPredecessor" et "findSuccessor" (pour rechercher le prochain élément le plus petit et le plus grand élément suivant) dans O(logn), qui peuvent également être des opérations très utiles. Hash Table ne peut pas fournir une efficacité dans ce temps.

4
Balaji

Si vous souhaitez accéder aux données de manière triée, une liste triée doit être gérée parallèlement à la table de hachage. Dictionnaire en .Net est un bon exemple. (voir http://msdn.Microsoft.com/en-us/library/3fcwy8h6.aspx ).

Cela a pour effet secondaire non seulement de ralentir les insertions, mais également de consommer plus de mémoire qu'un b-tree.

De plus, puisqu'un arbre b est trié, il est simple de trouver des plages de résultats, ou d'effectuer des unions ou des fusions.

1
IamIC

Cela dépend aussi de l'utilisation, Hash permet de localiser la correspondance exacte. Si vous souhaitez interroger une plage, choisissez BST. Supposons que vous avez beaucoup de données e1, e2, e3 ..... en.

Avec la table de hachage, vous pouvez localiser n'importe quel élément en temps constant.

Si vous souhaitez rechercher des valeurs de plage supérieures à e41 et inférieures à e8, BST peut rapidement le trouver.

L'essentiel est la fonction de hachage utilisée pour éviter une collision. Bien sûr, nous ne pouvons pas totalement éviter une collision, auquel cas nous avons recours à l'enchaînement ou à d'autres méthodes. Cela rend la récupération non plus constante dans les pires cas. 

Une fois remplie, la table de hachage doit augmenter la taille de son compartiment et copier à nouveau tous les éléments. Ceci est un coût supplémentaire non présent sur BST.

1
sreeprasad

Les arbres de recherche binaires sont un bon choix pour implémenter le dictionnaire si les clés ont un ordre total (les clés sont comparables) définies et si vous voulez conserver les informations de commande. 

Dans la mesure où BST conserve les informations de commande, il vous fournit quatre autres opérations sur les ensembles dynamiques qui ne peuvent pas être effectuées (efficacement) à l'aide de tables de hachage. Ces opérations sont:

  1. Maximum 
  2. Le minimum
  3. Successeur
  4. Prédécesseur

Toutes ces opérations, comme toutes les opérations BST, ont une complexité temporelle de O (H). En outre, toutes les clés stockées restent triées dans le fichier BST, ce qui vous permet d'obtenir la séquence de clés triée simplement en parcourant l'arborescence dans l'ordre. 

En résumé, si vous ne voulez que des opérations d'insertion, de suppression et de suppression, la table de hachage est imbattable (la plupart du temps) en termes de performances. Toutefois, si vous souhaitez utiliser l'une des opérations répertoriées ci-dessus, vous devez utiliser un fichier BST, de préférence un système BST à équilibrage automatique.

0
mightyWOZ

Les arbres de recherche binaires peuvent être plus rapides lorsqu'ils sont utilisés avec des clés de chaîne. Surtout quand les cordes sont longues.

Arbres de recherche binaires utilisant des comparaisons pour moins/plus qui sont rapides pour les chaînes (quand elles ne sont pas égales). Ainsi, un BST peut répondre rapidement lorsqu'une chaîne n'est pas trouvée . Une fois trouvée, elle n'aura besoin que d'une comparaison complète.

Dans une table de hachage. Vous devez calculer le hachage de la chaîne, ce qui signifie que vous devez parcourir tous les octets au moins une fois pour calculer le hachage. Là encore, lorsqu'une entrée correspondante est trouvée.

0
Calmarius

Les classes HashSet et Table sont des collections non ordonnées. Cela n'est pas évident à partir de l'interface (et pourrait en être autrement) mais des tables de hachage ont été implémentées à l'aide d'arbres AVL. Cela signifie que le code de hachage n'est pas réduit par le modulo d'un tableau (moins de collisions), mais aussi qu'il n'y a pas de redistribution d'un tableau à effectuer (performances plus régulières). Le fait qu'il s'agisse de collections non ordonnées signifie que vous ne fournissez qu'une fonction égale et une fonction hashCode - pas un comparateur complet comme pour les arbres. Ainsi, que vous utilisiez une table de hachage, la table <K, T> ou un arbre binaire Tree <K, T> dépend de la classe K - que ce soit entièrement comparable ou seulement comparable.

Il y a des cas où le type de données est à la fois comparable et comparable, comme String. Cela signifie que HashSet <String> et Set <String> sont tous deux possibles. Les recherches sur un ensemble de chaînes de hachage ont tendance à être environ 10 fois plus rapides que les recherches sur un ensemble ordonné de chaînes. Si le comparateur est cher, les arbres ralentissent par rapport à HashTables. Si le comparateur est rapide (comme pour les entiers et les flottants), les arbres s'exécuteront plus rapidement que les tables de hachage.

0
Benedict NNcNannara

Les tables de hachage ne sont pas bonnes pour l'indexation. Lorsque vous recherchez une plage, les BST sont meilleurs. C'est la raison pour laquelle la plupart des index de base de données utilisent des arbres B + au lieu de tables de hachage

0
ssD

Un hashmap est un tableau associatif défini. Ainsi, votre tableau de valeurs d'entrée est mis en pool dans des compartiments. Dans un schéma d'adressage ouvert, vous avez un pointeur sur un compartiment et chaque fois que vous ajoutez une nouvelle valeur dans un compartiment, vous découvrez où se trouvent des espaces libres dans le compartiment. Il y a plusieurs façons de le faire - vous commencez au début du compartiment, incrémentez le pointeur à chaque fois et testez s'il est occupé. C'est ce qu'on appelle le sondage linéaire. Ensuite, vous pouvez effectuer une recherche binaire comme add, où vous doublez la différence entre le début du compartiment et celle que vous doublez ou redescendez chaque fois que vous recherchez un espace libre. C'est ce qu'on appelle le sondage quadratique ..__ OK. Maintenant, le problème dans ces deux méthodes est que si le seau déborde dans la prochaine adresse de seaux, alors vous devez-

  1. Doubler chaque taille de seau- malloc (N seaux)/changer la fonction de hachage - Temps requis: dépend de la mise en oeuvre de malloc
  2. Transférez/copiez chacune des données des compartiments précédents dans les nouvelles données des compartiments. Ceci est une opération O(N) où N représente l’ensemble des données 

D'ACCORD. mais si vous utilisez une liste de liens, le problème ne devrait pas exister? Oui, dans les listes chaînées, vous n'avez pas ce problème. Considérant que chaque compartiment commence par une liste chaînée, et si vous avez 100 éléments dans un compartiment, vous devez traverser ces 100 éléments pour atteindre la fin de la liste chaînée; par conséquent, List.add (élément E) prendra du temps pour-

  1. Hasher l'élément dans un compartiment - Normal comme dans toutes les implémentations
  2. Prenez le temps de trouver le dernier élément de l'opération de compartiment O(N).

L'avantage de l'implémentation de la liste liée est que vous n'avez pas besoin de l'opération d'allocation de mémoire ni du transfert/copie de O(N) de tous les compartiments, comme dans le cas de l'implémentation d'adressage ouvert.

Pour minimiser l’opération O(N), vous devez donc convertir l’implémentation en une arborescence de recherche binaire où les opérations de recherche sont O(log(N)) et vous ajoutez l’élément dans son position basée sur sa valeur. La fonctionnalité ajoutée d'un BST est qu'il est trié!

0
Vamsavardhana Vijay