S'il existait une telle structure, tout le monde l'utiliserait à la place des tableaux. Cependant, je pense à une structure plus proche dont on m'a parlé dans une conférence universitaire. Il a un temps d'accès constant et le temps d'ajouter/enlever un élément à une position arbitraire est principalement O (sqrt (N)) et seulement quand N croise le carré de la valeur entière, il prend O (N). Le temps amorti est O (sqrt (N)). Voici l'idée. N éléments dans cette structure sont stockés dans un tableau contigu, qui est divisé en sqrt (N) blocs d'éléments contigus sqrt (N) (peut-être, le dernier morceau contient moins d'éléments). Chaque fragment est un ring buffer, pour lequel la position du premier élément est stockée dans un tableau distinct de sqrt (N). Pour accéder à un élément, vous devez déterminer à quel bloc il appartient (prend une division) et effectuer un décalage approprié dans le tampon circulaire (somme et module). C'est une heure constante d'accès.
Pour ajouter un élément avant la position i-ème, déterminer le tronçon k
l'élément se terminera, puis marquer tous les derniers éléments dans chaque tronçon dans k
.. sqrt(N)-1
plage. Décalez l'élément marqué dans l'avant-dernier bloc vers l'emplacement libre dans un dernier morceau qui sera la tête d'un tampon d'anneau là (accédez à un tableau supplémentaire pour déterminer où exactement). Ensuite, à la position de l'élément déplacé par rapport à l'avant-dernier bloc, déplacez l'élément marqué du segment pré-avant-dernier. Répétez ceci et vous obtiendrez un emplacement libre au milieu du tableau pour placer l'élément que vous alliez ajouter. La magie est que vous ne devez augmenter les valeurs que d'une unité dans le tableau supplémentaire (en prenant le temps O (sqrt (N))), rendant ainsi la structure cohérente pour y accéder à nouveau. La magie de sqrt (N) est également ici: vous devez opérer sur chacun des morceaux X et sur chacun des éléments N/X d'un tableau auxilliaire. min (X + N/X) est atteint pour X = sqrt (N).
S'il n'y a pas de place dans le dernier morceau d'ajouter un élément (à savoir le sqrt (N) utilisé jusqu'à présent est trop petit), remballer le tableau avec sqrt (N) a augmenté d'un. Cela prend le temps O (N). Le temps amorti est toujours O (sqrt (N)) par élément.
Par conséquent, en ajoutant un élément dans un endroit arbitraire de tableau prend O (sqrt (N)). La suppression prend le même temps. Le temps d'accès prend O (1).
C'est l'idée.Je ne sais pas comment ça s'appelle, et le professeur ne le savait pas non plus parce qu'il l'avait inventé tout seul. Toute référence serait appréciée. Et l'OP pourrait l'implémenter, mais je parie que quelqu'un l'a déjà fait.
Donc, vous avez une liste où vous devez régulièrement développer la liste et en extraire les éléments par index? – aperkins
AFAIK, ArrayList double sa capacité lorsque sa capacité actuelle est dépassée. Il y aura donc O (log (n)) copies où n est la capacité finale de la Liste. Cela signifie que le nombre de fois que la liste entière doit être copiée est très très faible. Vous commencerez probablement à manquer de mémoire bien avant que le surcoût ne devienne significatif. OTOH, si vous devez arrêter des copies et savoir à l'avance une limite supérieure sur le nombre d'éléments que cette liste devra contenir, vous pouvez simplement passer la taille maximale comme argument au constructeur ArrayList. – MAK
Y at-il une raison pratique pour laquelle vous avez besoin de cela? a un benchmark/profil montré l'arraylist à être votre goulot d'étranglement? – basszero