Comment mettre en œuvre une Médiane de tas
Comme une Max-heap et Min-tas, je veux mettre en œuvre une Médiane de tas de garder une trace de la médiane d'un ensemble donné de nombres entiers. L'API doit avoir les trois fonctions suivantes:
insert(int) //should take O(logN)
int median() //will be the topmost element of the heap. O(1)
int delmedian() //should take O(logN)
Je veux utiliser un tableau (a) mise en œuvre pour mettre en œuvre le tas où les enfants d'index de tableau k sont stockés dans des index de tableau 2*k et 2*k + 1. Pour plus de commodité, le tableau commence à peupler éléments de l'index 1.
C'est ce que j'ai à ce jour:
La Médiane de tas disposera de deux entiers de garder une trace du nombre d'entiers inséré jusqu'à présent qui sont > médiane actuelle (gcm) et < médiane actuelle (lcm).
if abs(gcm-lcm) >= 2 and gcm > lcm we need to swap a[1] with one of its children.
The child chosen should be greater than a[1]. If both are greater,
choose the smaller of two.
De même pour les autres cas. Je ne peux pas venir avec un algorithme pour la façon de l'évier et de nager éléments. Je pense qu'il devrait prendre en considération le degré de fermer le nombre est à la médiane, donc quelque chose comme:
private void swim(int k) {
while (k > 1 && absless(k, k/2)) {
exch(k, k/2);
k = k/2;
}
}
Je ne peux pas venir avec la solution complète bien.
- Ce sera difficile, sans une limite à la multiplicité de toute valeur donnée.
Vous devez vous connecter pour publier un commentaire.
Vous avez besoin de deux tas: un min-tas et un max-heap. Chaque segment contient environ la moitié des données. Chaque élément dans le min-segment est supérieure ou égale à la médiane, et chaque élément de la max-heap est inférieur ou égal à la médiane.
Lorsque le min-tas contient un élément de plus que le max-heap, la médiane est dans le haut de la min-tas. Et quand max-tas contient un élément de plus que le min-tas, la médiane est dans le haut de la max-heap.
Lorsque les deux tas contiennent le même nombre d'éléments, le nombre total d'éléments est la même.
Dans ce cas, vous devez choisir selon votre définition de la médiane: a) la moyenne des deux milieu des éléments; b) le plus élevé des deux; c) le moins élevé; d) choisir au hasard l'un des deux...
Chaque fois que vous insérez, de comparer le nouvel élément avec ceux qui sont au sommet du tas afin de décider de l'endroit où l'insérer. Si le nouvel élément est supérieure à la médiane actuelle, il va à la min-tas. Si elle est inférieure à la médiane actuelle, il va au tas max. Ensuite, vous pourriez avoir besoin pour rééquilibrer. Si la taille des tas diffèrent par plus d'un élément, d'extraire les min/max dans le tas avec plus d'éléments et de l'insérer dans l'autre tas.
Pour la construction de la médiane du segment de mémoire pour une liste d'éléments, on doit d'abord utiliser un temps linéaire de l'algorithme et de trouver la médiane. Une fois la médiane est connu, il suffit d'ajouter des éléments à la Min-tas et Max-heap basé sur la valeur médiane. L'équilibrage de l'amas n'est pas nécessaire parce que la médiane de diviser la liste de saisie des éléments en deux moitiés égales.
Si vous extrayez un élément que vous pourriez avoir besoin pour compenser le changement de taille en déplaçant un élément à partir d'un segment à l'autre. De cette façon, vous assurer que, à tout moment, à la fois des tas ont la même taille ou qui diffèrent par un seul élément.
remove()
sur un segment, vous vous attendez à vous donner l'élément qui a été réellement supprimé. Si vous calculer la médiane à la moyenne, alorsremove()
le retour de nombre (vos calculé la médiane) mais en fait de supprimer un numéro différent. Donc, si vous ajoutezn
éléments à ce genre de MedianHeap, puis removeMedian et le mettre dans une autre structure de données pour chaque élément, les éléments de la deuxième structure de données ne seront pas les mêmes que ceux qui sont entrés dans la MedianHeap.Ici est un java implementaion d'un MedianHeap, développé avec l'aide de ci-dessus comocomocomocomo 'explication .
Voici mon code en fonction de la réponse fournie par comocomocomocomo :
N'est pas parfaitement équilibré arbre de recherche binaire (BST), la médiane de tas? Il est vrai que même rouge-noir techniciennes se chargent ne sont pas toujours parfaitement équilibré, mais il pourrait être assez près à vos besoins. Et log(n) le rendement est garanti!
AVL arbres sont beaucoup plus serrées équilibré que rouge-noir techniciennes se chargent alors, ils viennent même près d'être un vrai médiane tas.
O(logN)
pour récupérer un élément d'arbitraire rang dans un BST. Néanmoins, il suffirait de...je sais..Ici est un Scala de mise en œuvre, à la suite de la comocomocomocomo de l'idée ci-dessus.
Un autre moyen de le faire sans l'aide d'un max-heap et un min-tas serait d'utiliser une médiane de tas tout de suite.
Dans un max-heap, le parent est plus grand que les enfants.
Nous pouvons avoir un nouveau type de segment de mémoire où le parent est dans le "milieu" de la les enfants - la gauche de l'enfant est plus petit que le parent et l'enfant est plus grand que le parent. Toutes les entrées sont à gauche, les enfants et toutes les entrées sont droit des enfants.
La même nager et lavabo opérations qui peuvent être exécutées en un max-tas, peut également être effectuée dans cette médiane-tas - avec de légères modifications. Dans un typique nager opération dans un max-heap, l'insertion d'entrée à la nage jusqu'à ce qu'il est plus petit qu'un parent d'entrée, ici, à une médiane de tas, il va nager jusqu'à ce qu'il est moindre qu'un parent (si c'est une drôle d'entrée) ou supérieure à celle d'un parent (si c'est une même entrée).
Voici ma mise en œuvre de cette médiane de tas. J'ai utilisé un tableau d'Entiers pour des raisons de simplicité.
importation edu.princeton.cs.algs4.Sortie standard (StdOut);
public class MedianInsertDelete {
//entrée nage vers le haut de sorte que sa gauche l'enfant est plus petit et la droite est plus grande
private void nager(int k){
//si la gauche l'enfant est plus grand ou si le droit de l'enfant est plus petit, l'entrée du puits de bas
private void évier (int k){
}