2011-03-22 11 views
25

He leído un par de artículos que dicen que List.RemoveAt() está en O (n) hora.C# Lista eliminar del final, realmente O (n)?

Si hago algo como:

var myList = new List<int>(); 

/* Add many ints to the list here. */ 

// Remove item at end of list: 
myList.RemoveAt(myList.Count - 1); // Does this line run in O(n) time? 

Extracción desde el final de la lista debe ser O (1), ya que sólo tiene que disminuir el número de lista.

¿Necesito escribir mi propia clase para tener este comportamiento, o eliminar el elemento al final de una lista C# que ya funciona en O (1) vez?

+4

Soy consciente de que podría perfilar esto y ver, o usar .NET reflector. El objetivo de crear esta pregunta es crear un resultado de búsqueda para lo que creo que es una pregunta importante. No pude encontrar una respuesta a esto en mi propia búsqueda. – Olhovsky

Respuesta

24

En general List<T>::RemoveAt es O (N) debido a la necesidad de desplazar elementos después del índice hacia arriba de una ranura en la matriz. Sin embargo, para el caso específico de la eliminación de la final de la lista no se necesita ningún cambio y, en consecuencia, O (1)

+3

¿Sería el caso que es O (N) pero 'N' aquí es' list.Count - indexRemoved'? – Blorgbeard

+0

¿Dónde leíste esto? Sus documentos sugerirían lo contrario, parece que el procedimiento es O (n) sin importar qué, también conocido como, no están haciendo un caso especial. –

+1

@KevinDepue. No es realmente un caso especial que están creando, es un caso especial en sí mismo. Similar a iterar a través de una lista, que siempre es O (N), pero cuando la lista solo tiene 1 elemento, también es O (1) porque N es 1 en este caso. No hay ninguna razón para tratarlo como un caso especial, pero de todos modos sigue siendo un caso especial. – Nolonar

2

Esto debe darle una idea

public void RemoveAt(int index) { 
     if ((uint)index >= (uint)_size) { 
      ThrowHelper.ThrowArgumentOutOfRangeException(); 
     } 
     _size--; 
     if (index < _size) { 
      Array.Copy(_items, index + 1, _items, index, _size - index); 
     } 
     _items[_size] = default(T); 
     _version++; 
    } 
5

Extracción último elemento será realmente O(1) operación dado que solo en este caso List no cambia los siguientes elementos en el conjunto. Aquí es un código de reflector:

this._size--; 
if (index < this._size) // this statement is false if index equals last index in List 
{ 
    Array.Copy(this._items, index + 1, this._items, index, this._size - index); 
} 
this._items[this._size] = default(T); 
+0

'Array.Copy' solo copia datos, no los asigna. – Gabe

+0

@Gabe, gracias, arregló eso. – Snowbear

-2

Me parece que si esto era realmente relevantes para su aplicación, se podría haber medido en menos tiempo del que se tomó para hacer la pregunta. Y ahora tiene al menos dos respuestas contradictorias, por lo que tendrá que probarlo de todos modos.

Lo que quiero decir es que, a menos que los documentos de MSDN digan que removeAt es O (1) para los elementos al final de la lista, no podría contar con que funcione de esa manera, y podría cambio en cualquier actualización de .NET dada. Para el caso, el comportamiento podría ser diferente para diferentes tipos, para todo lo que sabes.

If List es la estructura de datos "natural" que se debe usar, y luego úselo. Si eliminar elementos de la Lista termina siendo un punto caliente en su perfil, entonces tal vez sea el momento de implementar su propia clase.

+0

Si se hubiera tomado la molestia de leer el comentario que agregué a la pregunta, vería que abordé el tema del perfilado o el uso del reflector. En cuanto a su segundo punto sobre las propiedades de la clase de lista que cambia en futuras revisiones, creo que es un punto válido, pero también creo que todavía es razonable hacer la pregunta sobre el estado actual de las cosas. Especialmente porque no es probable que vea un cambio por un largo tiempo. Después de todo, la industria de programación cambia relativamente rápido, la mayoría de las preguntas específicas de la implementación solo son relevantes por un tiempo limitado. – Olhovsky

+5

Si eliminar desde el final es O (1) hoy hay 99.999999% de probabilidad de que siga siendo así. No sugeriría que él comience a implementar sus propias estructuras de datos en las probabilidades muy poco probables de que esto cambie. Acerca de la parte de "mídelo tú mismo", no es verdad que hubiera sido más rápido. Las personas de confianza de SO como JaredPar pueden dar una buena respuesta en cuestión de minutos o incluso segundos ;-) –

Cuestiones relacionadas