stringtranslate.com

Saltar lista

En informática , una lista de omisión (o skiplist ) es una estructura de datos probabilística que permite una complejidad promedio para la búsqueda, así como una complejidad promedio para la inserción dentro de una secuencia ordenada de elementos. Por lo tanto, puede obtener las mejores características de una matriz ordenada (para búsqueda) mientras mantiene una estructura similar a una lista vinculada que permite la inserción, lo cual no es posible con una matriz estática. La búsqueda rápida es posible manteniendo una jerarquía vinculada de subsecuencias, donde cada subsecuencia sucesiva omite menos elementos que la anterior (consulte la imagen a continuación a la derecha). La búsqueda comienza en la subsecuencia más escasa hasta que se encuentran dos elementos consecutivos, uno más pequeño y otro más grande o igual que el elemento buscado. A través de la jerarquía vinculada, estos dos elementos se vinculan a elementos de la siguiente subsecuencia más dispersa, donde la búsqueda continúa hasta que finalmente se busca en la secuencia completa. Los elementos que se omiten pueden elegirse de forma probabilística [2] o determinista [3] , siendo el primero más común.

Descripción

Una imagen esquemática de la estructura de datos de la lista de omisión. Cada cuadro con una flecha representa un puntero y una fila es una lista enlazada que proporciona una subsecuencia dispersa; los cuadros numerados (en amarillo) en la parte inferior representan la secuencia de datos ordenada. La búsqueda continúa hacia abajo desde la subsecuencia más escasa en la parte superior hasta que se encuentran elementos consecutivos que se encuentran entre corchetes del elemento de búsqueda.

Una lista de omisión se construye en capas. La capa inferior es una lista enlazada ordenada ordinaria . Cada capa superior actúa como un "carril rápido" para las listas siguientes, donde un elemento de una capa aparece en una capa con una probabilidad fija (dos valores comúnmente utilizados para son o ). En promedio, cada elemento aparece en listas y el elemento más alto (normalmente un elemento principal especial al principio de la lista de omisión) aparece en todas las listas. La lista de omisión contiene (es decir, base logarítmica de ) listas.

La búsqueda de un elemento objetivo comienza en el elemento principal de la lista superior y continúa horizontalmente hasta que el elemento actual sea mayor o igual que el objetivo. Si el elemento actual es igual al objetivo, se ha encontrado. Si el elemento actual es mayor que el objetivo, o la búsqueda llega al final de la lista vinculada, el procedimiento se repite después de regresar al elemento anterior y descender verticalmente a la siguiente lista inferior. El número esperado de pasos en cada lista vinculada es como máximo , lo que se puede ver rastreando la ruta de búsqueda hacia atrás desde el objetivo hasta llegar a un elemento que aparece en la siguiente lista superior o llegar al comienzo de la lista actual. Por tanto, el coste total esperado de una búsqueda es cuál es , cuando es una constante. Al elegir diferentes valores de , es posible intercambiar los costos de búsqueda con los costos de almacenamiento.

Detalles de implementacion

Insertar elementos en una lista de omisión

Los elementos utilizados para una lista de omisión pueden contener más de un puntero ya que pueden participar en más de una lista.

Las inserciones y eliminaciones se implementan de manera muy similar a las operaciones de lista vinculada correspondientes, excepto que los elementos "altos" deben insertarse o eliminarse de más de una lista vinculada.

Las operaciones, que nos obligan a visitar cada nodo en orden ascendente (como imprimir la lista completa), brindan la oportunidad de realizar una desrandomización detrás de escena de la estructura de niveles de la lista de omisión de una manera óptima, trayendo la omisión lista para buscar el tiempo. (Elija que el nivel del i-ésimo nodo finito sea 1 más el número de veces que es posible dividir i entre 2 repetidamente antes de que se vuelva impar. Además, i=0 para el encabezado infinito negativo, ya que existe el caso especial habitual de elegir el nivel más alto posible para nodos infinitos negativos y/o positivos). Sin embargo, esto también permite que alguien sepa dónde están todos los nodos superiores al nivel 1 y los elimine.

Alternativamente, la estructura de niveles podría hacerse casi aleatoria de la siguiente manera:

hacer que todos los nodos sean nivel 1j ← 1mientras que el número de nodos en el nivel j > 1 lo hace  para cada i-ésimo nodo en el nivel j si i es impar y no es el último nodo en el nivel j  elige aleatoriamente si promocionarlo al nivel j+1 de lo contrario, si i es par y el nodo i-1 no fue promovido promoverlo al nivel j+1 terminar si  se repite j ← j + 1repetir

Al igual que la versión desaleatorizada, la cuasi-aleatorización solo se realiza cuando hay alguna otra razón para ejecutar una operación (que visita todos los nodos).

La ventaja de esta cuasi aleatoriedad es que no revela tanta información relacionada con la estructura de niveles a un usuario adversario como el usuario no aleatorizado. Esto es deseable porque un usuario adversario que es capaz de saber qué nodos no están en el nivel más bajo puede pesimizar el rendimiento simplemente eliminando nodos de nivel superior. (Bethea y Reiter, sin embargo, argumentan que, no obstante, un adversario puede utilizar métodos probabilísticos y de sincronización para forzar la degradación del rendimiento. [4] ) Aún se garantiza que el rendimiento de la búsqueda será logarítmico.

Sería tentador hacer la siguiente "optimización": En la parte que dice "Siguiente, para cada i ésimo...", olvídate de lanzar una moneda al aire para cada par par-impar. Simplemente lanza una moneda una vez para decidir si promocionas solo las pares o solo las impares. En lugar de lanzamientos de monedas, solo habría ellos. Desafortunadamente, esto le da al usuario adversario una probabilidad de 50/50 de acertar al adivinar que todos los nodos pares (entre los de nivel 1 o superior) son superiores al nivel uno. Esto a pesar de la propiedad de que existe una probabilidad muy baja de adivinar que un nodo particular está en el nivel N para algún número entero N.

Una lista de omisión no proporciona las mismas garantías absolutas de rendimiento en el peor de los casos que las estructuras de datos de árbol balanceadas más tradicionales , porque siempre es posible (aunque con una probabilidad muy baja [5] ) que los lanzamientos de monedas utilizados para construir la lista de omisión produzcan una estructura mal equilibrada. Sin embargo, funcionan bien en la práctica y se ha argumentado que el esquema de equilibrio aleatorio es más fácil de implementar que los esquemas de equilibrio deterministas utilizados en los árboles de búsqueda binarios equilibrados. Las listas de omisión también son útiles en computación paralela , donde las inserciones se pueden realizar en diferentes partes de la lista de omisión en paralelo sin ningún reequilibrio global de la estructura de datos. Este paralelismo puede ser especialmente ventajoso para el descubrimiento de recursos en una red inalámbrica ad-hoc porque una lista de omisión aleatoria puede hacerse robusta ante la pérdida de un solo nodo. [6]

Lista de omisión indexable

Como se describió anteriormente, una lista de omisión es capaz de insertar y eliminar rápidamente valores de una secuencia ordenada, pero sólo tiene búsquedas lentas de valores en una posición determinada de la secuencia (es decir, devuelve el valor número 500); sin embargo, con una pequeña modificación, la velocidad de las búsquedas indexadas de acceso aleatorio se puede mejorar a .

Para cada enlace, almacene también el ancho del enlace. El ancho se define como el número de enlaces de la capa inferior que atraviesa cada uno de los enlaces de "carril rápido" de la capa superior.

Por ejemplo, aquí están los anchos de los enlaces en el ejemplo en la parte superior de la página:

 1 10 o---> o-------------------------------------------- -------------> o Nivel superior 1 3 2 5 o---> o---------------> o---------> o---------------- -----------> o Nivel 3 1 2 1 2 3 2 o---> o---------> o---> o---------> o---------------> o ---------> o Nivel 2 1 1 1 1 1 1 1 1 1 1 1 o---> o---> o---> o---> o---> o---> o---> o---> o---> o---> o---> o Nivel inferiorCabeza 1.º 2.º 3.º 4.º 5.º 6.º 7.º 8.º 9.º 10.º NINGUNO Nodo Nodo Nodo Nodo Nodo Nodo Nodo Nodo Nodo Nodo

Observe que el ancho de un vínculo de nivel superior es la suma de los vínculos que lo componen debajo (es decir, el vínculo de ancho 10 abarca los vínculos de ancho 3, 2 y 5 inmediatamente debajo de él). En consecuencia, la suma de todos los anchos es la misma en todos los niveles (10 + 1 = 1 + 3 + 2 + 5 = 1 + 2 + 1 + 2 + 3 + 2).

Para indexar la lista de omisión y encontrar el valor i-ésimo, recorra la lista de omisión mientras cuenta regresivamente los anchos de cada enlace atravesado. Desciende un nivel siempre que el ancho próximo sea demasiado grande.

Por ejemplo, para encontrar el nodo en la quinta posición (Nodo 5), recorra un enlace de ancho 1 en el nivel superior. Ahora se necesitan cuatro pasos más, pero el siguiente ancho en este nivel es diez, lo cual es demasiado grande, así que baje un nivel. Atraviese un eslabón de ancho 3. Dado que otro paso de ancho 2 sería demasiado largo, baje al nivel inferior. Ahora recorra el enlace final de ancho 1 para alcanzar el total objetivo de 5 (1+3+1).

función de búsqueda por índice de posición (i) nodo ← cabeza i ← i + 1 # no cuente la cabeza como un paso  para el nivel de arriba a abajo , hágalo  mientras i ≥ node.width[nivel] haga  # si el siguiente paso no está demasiado lejos i ← i - node.width[level] # restar el ancho actual nodo ← node.next[level] # recorrer hacia adelante en el nivel actual  repetir  repetir  regresar node.value función final

Este método de implementación de indexación se detalla en "Un libro de cocina con lista de omisión" de William Pugh [7].

Historia

Las listas de omisión fueron descritas por primera vez en 1989 por William Pugh . [8]

Para citar al autor:

Las listas de omisión son una estructura de datos probabilística que parece probable que sustituya a los árboles equilibrados como método de implementación elegido para muchas aplicaciones. Los algoritmos de lista de omisión tienen los mismos límites de tiempo esperados asintóticos que los árboles equilibrados y son más simples, más rápidos y utilizan menos espacio.

—  William Pugh, Mantenimiento concurrente de listas de omisión (1989)

Usos

Lista de aplicaciones y marcos que utilizan listas de omisión:

Las listas de omisión también se utilizan en aplicaciones distribuidas (donde los nodos representan computadoras físicas y los punteros representan conexiones de red) y para implementar colas de prioridad concurrentes altamente escalables con menos contención de bloqueo, [17] o incluso sin bloqueo , [18] [19] [ 20] así como diccionarios concurrentes sin bloqueo . [21] También existen varias patentes estadounidenses para el uso de listas de omisión para implementar colas de prioridad (sin bloqueo) y diccionarios concurrentes. [22]

Ver también

Referencias

  1. ^ ab Papadakis, Thomas (1993). Listas de omisión y análisis probabilístico de algoritmos (PDF) (Ph.D.). Universidad de Waterloo.
  2. ^ Pugh, W. (1990). "Listas de omisión: una alternativa probabilística a los árboles equilibrados" (PDF) . Comunicaciones de la ACM . 33 (6): 668–676. doi :10.1145/78973.78977. S2CID  207691558.
  3. ^ Munro, J. Ian ; Papadakis, Thomas; Sedgewick, Robert (1992). "Listas de omisión deterministas" (PDF) . Actas del tercer simposio anual ACM-SIAM sobre algoritmos discretos (SODA '92) . Orlando, Florida, EE.UU.: Sociedad de Matemáticas Industriales y Aplicadas, Filadelfia, PA, EE.UU. págs. 367–375. S2CID  7477119.
  4. ^ Bethea, Darrell; Reiter, Michael K. (21 al 23 de septiembre de 2009). Estructuras de datos con tiempos impredecibles (PDF) . ESORICS 2009, 14º Simposio Europeo sobre Investigación en Seguridad Informática. Saint-Malo, Francia. págs. 456–471, §4 "Listas de omisión". doi :10.1007/978-3-642-04444-1_28. ISBN 978-3-642-04443-4.
  5. ^ Sen, Sandeep (1991). "Algunas observaciones sobre las listas de omisión". Cartas de procesamiento de información . 39 (4): 173-176. doi :10.1016/0020-0190(91)90175-H.
  6. ^ Shah, Gauri (2003). Estructuras de datos distribuidos para sistemas peer-to-peer (PDF) (tesis doctoral). Universidad de Yale.
  7. ^ William Pugh. "Un libro de cocina con lista de omisiones" . 1990. Sección 3.4 Operaciones de lista lineal.
  8. ^ Pugh, William (abril de 1989). Mantenimiento concurrente de listas de omisión (PS, PDF) (Reporte técnico). Departamento de Ciencias de la Computación, U. Maryland. CS-TR-2222.
  9. ^ Documentación de Apache Portable Runtime APR 1.6
  10. ^ Artículo de LWN
  11. ^ "LKML: Con Kolivas: [ANUNCIO] Programador de lista de omisión de colas múltiples versión 0.120". lkml.org . Consultado el 11 de mayo de 2017 .
  12. ^ Servidor IMAP Ciro. archivo fuente de lista de omisión
  13. ^ Mapa Q
  14. ^ "Redis ordenó la implementación del conjunto". GitHub .
  15. ^ Ahora, Matt. "Uso de Rust para escalar Elixir para 11 millones de usuarios simultáneos". Blog de discordia . Consultado el 23 de julio de 2023 .
  16. ^ "MemTable". GitHub . Consultado el 12 de diciembre de 2023 .
  17. ^ Shavit, N.; Lotán, I. (2000). "Colas de prioridad simultánea basadas en listas de omisión" (PDF) . Actas del 14º Simposio Internacional de Procesamiento Distribuido y Paralelo. IPDPS 2000 . pag. 263. CiteSeerX 10.1.1.116.3489 . doi :10.1109/IPDPS.2000.845994. ISBN  978-0-7695-0574-9. S2CID  8664407.
  18. ^ Sundell, H.; Tsigas, P. (2003). "Colas de prioridad simultáneas, rápidas y sin bloqueos para sistemas multiproceso". Actas del Simposio internacional sobre procesamiento distribuido y paralelo . pag. 11. CiteSeerX 10.1.1.113.4552 . doi :10.1109/IPDPS.2003.1213189. ISBN  978-0-7695-1926-5. S2CID  20995116.
  19. ^ Fomitchev, Mikhail; Ruppert, Eric (2004). Listas vinculadas y listas de omisión sin bloqueo (PDF) . Proc. Simposio anual de ACM. sobre Principios de Computación Distribuida (PODC). págs. 50–59. doi :10.1145/1011767.1011776. ISBN 1581138024.
  20. ^ Bajpai, R.; Dhara, KK; Krishnaswamy, V. (2008). "QPID: una cola de prioridad distribuida con localidad de elementos". Simposio internacional IEEE 2008 sobre procesamiento paralelo y distribuido con aplicaciones . pag. 215.doi : 10.1109 /ISPA.2008.90. ISBN 978-0-7695-3471-8. S2CID  15677922.
  21. ^ Sundell, Hong Kong; Tsigas, P. (2004). "Diccionarios simultáneos escalables y sin bloqueos" (PDF) . Actas del simposio ACM de 2004 sobre informática aplicada - SAC '04 . pag. 1438. doi : 10.1145/967900.968188. ISBN 978-1581138122. S2CID  10393486.
  22. ^ Patente estadounidense 7937378 

enlaces externos