2012-01-02 16 views
6

Necesita una colección de cadenas donde los elementos insertados necesitan ser ordenados y también no duplicados, se puede recuperar a través del índice.Cómo hacer un conjunto ordenado con O (1) acceso aleatorio por índice

  • puedo usar TreeSet que elimina los duplicados y ordena todo en orden pero no puede recuperar a través del índice. para recuperar a través del índice , puedo hacer elementos ArrayList y addAll, pero este addAll lleva mucho tiempo.

o

  • puedo usar un ArrayList, inserto requerido y luego eliminar duplicados por algún otro método, y luego usando Collections.sort método para ordenar elementos.

Pero la cuestión es que todo esto lleva tiempo, ¿hay algún camino directo para lograr esto, una colección? Clasificada, no duplicada, con O (1) acceso aleatorio por índice.

+2

¿Por qué no solo usa un TreeSet y luego crea su SortedList con el constructor SortedList (Collection <>)? SortedSet <> implementa Collection <> – fge

+1

Cualquier cosa que haga en una computadora "tome [s] tiempo". ¿Ha medido esta parte particular de su programa y descubrió que toma una * cantidad de tiempo inaceptable *? Y si es así, ¿qué es "irrazonable" en su caso? Horas, segundos o milisegundos? – kdgregory

+1

33082 registros tomaron 710ms para el método addAll, donde los registros pueden extenderse a lakhs, lo que toma mucho tiempo ¿no? Además, construir Treet tomó los mismos 704 ms, pero eso es permisible, pero este addAll toma tanto tiempo como la construcción, por lo que pensé que podría reducir este costo y hacer que mi programa funcione más rápido. – cypronmaya

Respuesta

0

No estoy seguro, ¿prueba el mapa? Me refiero a usar su cadena como clave en un TreeMap.

En un mapa, es una O (1) para que una tecla encuentre su posición (un valor hash). Y KeySet de TreeMap devolverá un conjunto ordenado de claves en TreeMap.

¿Se ajusta esto a su requerimiento?

+2

Solo HashMap tiene * O (1) * semántica; TreeMap es * O (logN) * ​​para la recuperación. – kdgregory

2

Usted puede utilizar la segunda idea:

puedo usar ArrayList, inserción deseada y eliminar duplicados por algún otro método , a continuación, utilizando el método Collections.sort para ordenar los elementos.

pero en lugar de eliminar los duplicados antes de la clase, se puede ordenar la ArrayList en primer lugar, a continuación, todos los duplicados en posiciones consecutivas y se puede retirar en una sola pasada después.

En este punto, ambos métodos tienen la misma complejidad general: O (N * logN) y vale la pena señalar que no se puede obtener una secuencia ordenada más rápido que esto de todos modos (sin explotación adicional de algunos conocimientos sobre los valores).

+0

¿Se puede cuantificar cómo esto podría ser más rápido que la primera opción? Porque si lo descompone por algoritmo, encontrará que está realizando un ordenamiento * O (logN) * ​​y una copia * O (N) * en ambos casos. – kdgregory

+0

@kdgregory: en la versión TreeSet está haciendo inserciones N * O (logN) (o duplicados) para que O (N * logN) sume. En la segunda versión, está haciendo una clasificación O (N * logN) sort + O (N) que sigue siendo O (N * logN). La segunda versión, sin embargo, tiene el beneficio adicional de acceder por índice, que es lo que el OP también quería. – Tudor

+0

Lo siento, pero lo que he querido decir es que tanto la primera como la segunda opción están tomando tiempo, no estoy cuantificando aquí .... – cypronmaya

0

Si usted está limitado a la List al principio y al final de la operación, convertirlo en un Set con el constructor "copia" (o addAll) después de que los elementos están pobladas, esto elimina los duplicados. Si lo convierte en un TreeSet con un Comparator apropiado, incluso lo ordenará. Entonces, puede convertirlo nuevamente a List.

+0

Eso lleva mucho tiempo ...... – cypronmaya

+0

Después de construir un conjunto de árboles en O (nlogn) (árbol rojo-negro) que convertirlo en una lista en O (n), la primera conversión solo es necesaria si tiene que comenzar con una lista. – zeller

1

El rendimiento depende de con qué frecuencia se agregan los elementos y con qué frecuencia se accederá por índice.

Puedo usar TreeSet que elimina duplicados y ordena todo en orden pero no puede recuperar a través del índice. para recuperar a través del índice, puedo hacer elementos de arraylist y addall, pero este addAll toma mucho tiempo.

List.addAll (yourSortedSet) tendrá al menos O tiempo y el espacio (n) cada vez que desee acceder a la SortedSet como la lista (es decir, por el índice del elemento).

Puedo usar ArrayList, insertar como obligatorio y luego eliminar duplicados por algún otro método, luego usar el método Collections.sort para ordenar los elementos.

Sin duda la ordenación tomará más de O (n) cada vez que desee una vista ordenada de su lista.

Una solución más

Si no estás obteniendo por el índice muy a menudo, entonces es más eficiente de hacerlo de la siguiente manera:

tienda sólo String s en un SortedSet puede ser extender TreeSet y proporcione/implemente su propio método get(int i) donde itere hasta el i-ésimo elemento y devuelva ese elemento. En el peor de los casos, esto será O (n) por lo demás mucho menor. De esta manera usted es no realizando cualquier comparación o conversión o copia de cadenas. No se necesita espacio adicional.

+0

Almacenar las cadenas dentro de un TreeSet requiere O (N * logN) porque tiene N cadenas y toma O (logN) para encontrar su posición mediante comparaciones sucesivas. – Tudor

0

Utilice un Hashmap para resolver problemas con valores únicos y ordenarlos por algunos de los métodos de clasificación. Si es posible, use quicksort.

+0

Tenga en cuenta que (1) 'HashMap' no conserva ningún orden; (2) No puede ordenar un 'HashMap' en absoluto. Quicksort puede ser de alguna relevancia aquí, pero es bastante limitado: tan pronto como comience a actualizar una colección, casi cualquier otro algoritmo lo hará mejor. – alf

+0

Bien, ¿puedes usar un LinkedMap esta extensión de Map se puede usar para la determinación de valores únicos y se puede ordenar con punteros de cada elemento del mapa – pesoklp13

+0

No hay 'LinkedMap' en' java.util'.'LinkedHashMap' no es una buena opción para ningún algoritmo de clasificación. ¿Podrías verificar tus consejos primero? – alf

0

Quizás usando LinkedList (que toma menos memoria que el arraylist) con el método booleano que determina si ese elemento ya está en la lista y un algoritmo QuickSort. Todas las estructuras en Java tienen que clasificarse y protegerse de duplicados de alguna manera, así que todo lleva su tiempo ...

+2

1) LinkedList toma * más * memoria que ArrayList. 2) Determinar si un elemento ya está en una lista es una operación * O (N) * en una Lista Vinculada; es una operación * O (N) * en una ArrayList ordenada, pero clasificando que ArrayList será * O (NlogN) * ​​en el mejor de los casos; 3) Java proporciona métodos de ordenamiento integrados en el JDK, y usa MergeSort para listas; 4) Ni siquiera puedo entender la oración que comienza con "Todas las estructuras en Java". – kdgregory

2

El verdadero problema aquí es que el PO no nos ha dicho el verdadero problema. Entonces, mucha gente adivina las estructuras de datos y publica respuestas sin pensar realmente.

El verdadero síntoma, como el OP se indica en un comentario, es que se tarda 700ms para poner las cadenas en un TreeSet, y otros 700 ms para copiar que TreeSet en un ArrayList. Obviamente, el programa no está haciendo lo que el OP cree que es, ya que la copia debería tomar como máximo unos pocos microsegundos. De hecho, el siguiente programa, que se ejecuta en mi antiguo Thinkpad, requiere solo 360 ms para crear 100.000 cadenas aleatorias, colocarlas en un TreeSet y copiar ese TreeSet en ArrayList.

Dicho esto, el OP ha seleccionado una respuesta (dos veces). Tal vez si/cuando el OP decide pensar sobre el problema real, este ejemplo de un SSCCE será útil. Es CW, así que siéntete libre de editarlo.


import java.lang.management.ManagementFactory; 
import java.lang.management.ThreadMXBean; 
import java.util.ArrayList; 
import java.util.List; 
import java.util.Random; 
import java.util.TreeSet; 


public class Microbench 
{ 
    public static void main(String[] argv) 
    throws Exception 
    {   
     ThreadMXBean threadBean = ManagementFactory.getThreadMXBean(); 
     long start = threadBean.getCurrentThreadCpuTime(); 
     executeTest(); 
     long finish = threadBean.getCurrentThreadCpuTime(); 
     double elapsed = (finish - start)/1000000.0; 
     System.out.println(String.format("elapsed time = %7.3f ms", elapsed)); 
    } 


    private static List<String> executeTest() 
    { 
     String[] data = generateRandomStrings(100000); 

     TreeSet<String> set = new TreeSet<String>(); 
     for (String s : data) 
      set.add(s); 

     return new ArrayList<String>(set); 
    } 


    private static String[] generateRandomStrings(int size) 
    { 
     Random rnd = new Random(); 
     String[] result = new String[size]; 
     for (int ii = 0 ; ii < size ; ii++) 
      result[ii] = String.valueOf(rnd.nextLong()); 
     return result; 
    } 
} 
0

hay dos maneras de hacer que el uso LinkedMap que cada elemento de mapa es único o hacer su propia extensión de lista y método de reemplazo añadir

import java.util.ArrayList; 

public class MyList<V> extends ArrayList<V>{ 

    private static final long serialVersionUID = 5847609794342633994L; 

    public boolean add(V object) { 
     //make each object unique 
     if(contains(object)){ 
      return false; 
     } 

     //you can make here ordering and after save it at position 

     //your ordering here 

     //using extended method add 
     super.add(yourposition,object); 
    } 
} 
0

también me enfrenté al problema de encontrar elemento en una posición determinada en un TreeMap. Mejoré el árbol con pesos que permiten acceder a los elementos por índice y encontrar elementos en los índices. El proyecto se llama indexed-tree-map http://code.google.com/p/indexed-tree-map/. La implementación para encontrar el índice de un elemento o elemento en un índice en un mapa ordenado no se basa en la iteración lineal sino en una búsqueda binaria de árbol. La actualización de los pesos del árbol también se basa en el ascenso vertical del árbol. Entonces no hay iteraciones lineales.

Cuestiones relacionadas