PEU:à l'Aide d'un binaire indexé arbre?
Binaire indexé arbre a très peu ou relativement peu de théorie à l'étude par rapport à d'autres structures de données. Le seul endroit où il est enseigné de manière succincte est le topcoder tutoriel. Bien que le tutoriel est complet dans toutes les explications, je ne comprends pas que ce qui est l'intuition derrière un arbre? Et comment prouver que c'est correct?
Je présume que la preuve est complexe à expliquer. Donc, lorsque vous utilisez PEU, quelle approche avez-vous suivi?
- Wikipédia donne une idée assez succinct explication: en.wikipedia.org/wiki/Fenwick_tree
- il ne dit rien à propos de l'algorithme qui est effectivement un emploi , et rien de l'exactitude de l'algorithme.
- C'est du moins la plus courte. Il aide à comprendre l'essentiel de l'algorithme. Je l'ai posté pour d'autres potentiels answerers.
- N'avez-vous pas également demander à ce sur cs.stackexchange.com?
- Oui je l'ai fait. Je l'ai posté ici parce que je ne m'attendais pas du cs.stackexchange de la communauté à être forts ou engagés pour répondre à un établissement entièrement non-trivial question qui n'avait pratiquement aucune des ressources de lire.J'espère que je ne t'ai pas offensé la communauté.En outre, j'ai ajouté votre réponse ci-dessous que je voulais répondre à la question pour les futurs visiteurs avant que la question ne se ferme.
Vous devez vous connecter pour publier un commentaire.
J'ai trouvé cette réponse par @templatetypedef très clairement expliquer au sujet de l'intuition et de la preuve d'un binaire indexé arbre:
La réponse....
De manière intuitive, on peut penser à un binaire indexé arbre comme une représentation compressée d'un arbre binaire qui est elle-même une optimisation d'une gamme standard de représentation. Cette réponse va dans une dérivation possible.
Supposons, par exemple, que vous souhaitez stocker des fréquences cumulées pour un total de 7 éléments. Vous pourriez commencer par écrire sept seaux dans lesquels les chiffres seront distribués:
Maintenant, supposons que les fréquences cumulées ressembler à quelque chose comme ceci:
L'utilisation de cette version de la matrice, vous pouvez incrémenter la fréquence cumulée de n'importe quel élément à l'augmentation de la valeur du nombre stocké à cet endroit, puis en incrémentant les fréquences de tout ce qui arrivent par la suite. Par exemple, pour augmenter la fréquence cumulée de 3 par 7, on pourrait ajouter 7 pour chaque élément du tableau à ou après la position 3, comme illustré ici:
Le problème, c'est que cela prend un temps O(n) le temps de faire ce qui est assez lent si n est grand.
D'une façon que nous pouvons penser à l'amélioration de cette opération serait de changer ce que nous stockons dans les seaux. Plutôt que de stocker la fréquence cumulée jusqu'à ce point, vous pouvez au lieu de penser à l'enregistrement de la quantité que de la fréquence actuelle a augmenté par rapport à la précédente seau. Par exemple, dans notre cas, nous réécrire au-dessus des seaux comme suit:
Maintenant, nous avons à augmenter la fréquence à l'intérieur d'un seau en temps O(1) par le simple ajout de la quantité appropriée de ce seau. Cependant, le coût total de faire une recherche devient O(n), puisque nous avons à recalculer le total dans le seau en additionnant les valeurs de tous les petits seaux.
La première grande idée, nous devons obtenir à partir d'ici binaire indexé arbre est la suivante: plutôt que de constamment re-calculer la somme des éléments du tableau qui précèdent un élément particulier, si nous étions à précalculer la somme totale de tous les éléments avant des points spécifiques de la séquence? Si nous pouvions le faire, nous pourrions déterminer la somme cumulée à un point juste en résumant la bonne combinaison de ces précalculées sommes.
Une façon de le faire est de modifier la représentation d'un tableau de seaux d'être un arbre binaire de nœuds. Chaque nœud est associé à une valeur qui représente la somme cumulée de tous les noeuds à gauche de ce nœud donné. Par exemple, supposons que nous construisons le suivant arbre binaire à partir de ces nœuds:
Maintenant, nous pouvons augmenter chaque nœud par le stockage de la somme cumulée de toutes les valeurs, y compris le nœud et son sous-arbre gauche. Par exemple, compte tenu de nos valeurs, nous permettrait de stocker les informations suivantes:
Compte tenu de cette structure de l'arbre, il est facile de déterminer la somme cumulée jusqu'à un certain point. L'idée est la suivante: nous maintenons un compteur, initialement 0, puis une recherche binaire jusqu'à nous de trouver le nœud en question. Comme nous le faisons, nous avons également les éléments suivants: tout le temps que nous passons à droite, nous avons également ajouter de la valeur actuelle du compteur.
Par exemple, supposons que nous voulons regarder jusqu'à la somme de 3. Pour ce faire, nous faisons la suivante:
On pourrait imaginer aussi l'exécution de ce processus dans le sens inverse: à partir d'un nœud donné, initialiser le compteur pour que la valeur du nœud, puis marcher jusqu'à l'arbre à la racine. Tout moment vous suivez un droit de l'enfant lien vers le haut, ajouter de la valeur au nœud, vous arrivez sur. Par exemple, pour trouver la fréquence de 3, nous avons pu effectuer les opérations suivantes:
À l'augmentation de la fréquence d'un nœud (et, implicitement, les fréquences de tous les nœuds qui viennent après lui), nous avons besoin de mettre à jour l'ensemble de noeuds dans l'arbre qui comprennent que le nœud dans son sous-arbre gauche. Pour ce faire, nous ne les suivants: augmentation de la fréquence de ce nœud, puis commencez à marcher jusqu'à la racine de l'arbre. Tout moment vous suivez un lien qui vous emmène jusqu'gauche de l'enfant, l'accroissement de la fréquence du nœud que vous rencontrez en ajoutant de la valeur actuelle.
Par exemple, à l'augmentation de la fréquence de nœud 1 par cinq, nous ferions le suivant:
De départ au niveau du nœud 1, incrémenter sa fréquence par 5 pour obtenir
Maintenant, allez à sa mère:
Nous avons suivi à la gauche de l'enfant lien vers le haut, donc on incrémente de ce nœud, fréquence:
Nous passons maintenant à son parent:
Qui a été de gauche de link enfant, donc on incrémente ce noeud:
Et maintenant, nous sommes de fait!
La dernière étape consiste à convertir à partir de ce binaire indexé arbre, et c'est là que nous arrivons à faire des choses amusantes avec des nombres binaires. Réécrivons chaque seau d'index dans cet arbre binaire:
Ici, nous pouvons faire un très, très cool d'observation. Prenez l'un de ces nombres binaires et de trouver le dernier 1 qui a été définie dans le numéro, puis déposer le peu de, avec tous les bits qui viennent après lui. Vous êtes maintenant à gauche avec le texte suivant:
Ici est vraiment, vraiment cool observation: si vous traiter de 0 à-dire "de gauche" et 1 signifie "droit", les bits restants sur chaque numéro sort exactement comment commencer à la racine, puis marcher vers ce numéro. Par exemple, le nœud 5 a modèle binaire 101. Le dernier 1 est le bit final, nous avons donc tomber que d'obtenir 10. En effet, si vous commencez à partir de la racine, allez à droite (1), puis tournez à gauche (0), vous vous retrouvez au nœud 5!
La raison pour laquelle c'est important, c'est que notre recherche et les opérations de mise à jour dépend de la voie d'accès à partir du nœud de retour jusqu'à la racine, et si on suit à gauche ou à droite de l'enfant des liens. Par exemple, lors d'une recherche, nous venons de soins sur la gauche des liens que nous suivons. Lors d'une mise à jour, nous venons de soins sur les liens à droite nous suivre. Ce binaire indexé arbre tout cela, super efficace en utilisant simplement les bits dans l'index.
La clé astuce est la propriété suivante de cette parfaite arbre binaire:
Par exemple, regardez le chemin d'accès pour le nœud 7, qui est de 111. Les nœuds sur le chemin d'accès à la racine que nous prenons qui impliquent à la suite d'un pointeur vers le haut est
Tous ces liens à droite. Si nous prenons le chemin d'accès pour le nœud 3, qui est le 011, et de regarder les nœuds où nous allons à droite, nous obtenons
Cela signifie que nous sommes très, très efficace calculer la somme cumulée jusqu'à un nœud comme suit:
De la même façon, nous allons réfléchir sur la façon dont nous allions faire une mise à jour de l'étape. Pour ce faire, on aurait envie de suivre le chemin d'accès à remonter à la racine, la mise à jour de tous les nœuds où nous avons suivi un lien de gauche vers le haut. Nous pouvons faire cela en fait l'algorithme ci-dessus, mais le passage de tous les 1 à 0 et de 0 à 1.
L'étape finale dans le binaire indexé arbre est à noter qu'en raison de ce bit à bit de la tricherie, nous n'avons même pas besoin d'avoir l'arborescence contenue explicitement plus. Il nous suffit de stocker tous les nœuds dans un tableau de longueur n, alors l'utilisation de l'or au niveau du bit se tourner les techniques pour naviguer dans l'arborescence implicitement. En fait, c'est exactement ce que le bit à bit indexé arbre n'est - il stocke les nœuds dans un tableau, puis utilise ces bit à bit des astuces pour simuler efficacement la marche vers le haut de cet arbre.
Espérons que cette aide!