¿Hay alguna manera de medir qué tan ordenada está una lista?
Quiero decir, no se trata de saber si una lista está ordenada o no (booleana), sino algo así como una relación de "clasificación", algo así como el coeficiente de correlación en las estadísticas.
Por ejemplo,
Si los elementos de una lista están en orden ascendente, su tasa sería 1.0
Si la lista se ordena descendente, su tasa sería -1.0
Si la lista está casi ordenada ascendente, su tasa sería 0.9 o algún valor cercano a 1.
Si la lista no está ordenada (aleatoria), su tasa sería cercana a 0
Estoy escribiendo una pequeña biblioteca en Scala para practicar. Creo que una tasa de clasificación sería útil, pero no encuentro ninguna información sobre algo así. Tal vez no conozco los términos adecuados para el concepto.
Respuestas:
Simplemente puede contar el número de inversiones en la lista.
Inversión
Una inversión en una secuencia de elementos de tipo
T
es un par de elementos de secuencia que aparecen fuera de orden de acuerdo con algún orden<
en el conjunto deT
's.De Wikipedia :
Para aclarar estas definiciones, considere la secuencia de ejemplo
9, 5, 7, 6
. Esta secuencia tiene las inversiones(0,1), (0,2), (0,3), (2,3)
y el número de inversión4
.Si desea un valor entre
0
y1
, puede dividir el número de inversión entreN choose 2
.Para crear realmente un algoritmo para calcular este puntaje según la clasificación de una lista, tiene dos enfoques:
Enfoque 1 (determinista)
Modifique su algoritmo de clasificación favorito para realizar un seguimiento de cuántas inversiones está corrigiendo mientras se ejecuta. Aunque esto no es trivial y tiene implementaciones diferentes según el algoritmo de clasificación que elija, terminará con un algoritmo que no es más costoso (en términos de complejidad) que el algoritmo de clasificación con el que comenzó.
Si toma esta ruta, tenga en cuenta que no es tan simple como contar "intercambios". Mergesort, por ejemplo, es el peor de los casos
O(N log N)
, pero si se ejecuta en una lista ordenada en orden descendente, corregirá todas lasN choose 2
inversiones. Eso esO(N^2)
inversiones corregidas en lasO(N log N)
operaciones. Por lo tanto, algunas operaciones inevitablemente deben corregir más de una inversión a la vez. Tienes que tener cuidado con tu implementación. Nota: puedes hacer esto conO(N log N)
complejidad, es complicado.Relacionado: calcular el número de "inversiones" en una permutación
Enfoque 2 (estocástico)
(i,j)
, dondei != j
list[min(i,j)] < list[max(i,j)]
(0 o 1)N choose 2
Yo personalmente seguiría el enfoque estocástico a menos que tenga un requisito de exactitud, aunque solo sea porque es muy fácil de implementar.
Si lo que realmente quiere es un valor (
z'
) entre-1
(ordenado descendente) a1
(ordenado ascendente), simplemente puede asignar el valor anterior (z
), que está entre0
(ordenado ascendente) y1
(ordenado descendente), a este rango utilizando esta fórmula :fuente
La medida tradicional de cuán ordenada es una lista (u otra estructura secuencial) es el número de inversiones.
El número de inversiones es el número de pares (a, b) st index de a <b AND b
<<
a. Para estos fines,<<
representa cualquier relación de orden que elija para su tipo particular.Una lista completamente ordenada no tiene inversiones, y una lista completamente invertida tiene el número máximo de inversiones.
fuente
5 4 3 2 1
está completamente ordenado ya que el orden no está especificado, pero estoy siendo pedante :-)<
.n choose 2
.Puedes usar la correlación real.
Suponga que a cada elemento de la lista ordenada, le asigna un rango entero a partir de cero. Tenga en cuenta que un gráfico del índice de posición de los elementos versus el rango se verá como puntos en línea recta (correlación de 1.0 entre la posición y el rango).
Puede calcular una correlación en estos datos. Para un orden inverso obtendrá -1 y así sucesivamente.
fuente
Ha habido excelentes respuestas, y me gustaría agregar un aspecto matemático para completar:
Puede medir qué tan ordenada está una lista midiendo cuánto está correlacionada con una lista ordenada. Para hacer eso, puede usar la correlación de rango (la más conocida es Spearman ), que es exactamente la misma que la correlación habitual, pero usa el rango de elementos en una lista en lugar de los valores analógicos de sus elementos.
Existen muchas extensiones, como un coeficiente de correlación (+1 para la clasificación exacta, -1 para la inversión exacta)
Esto le permite tener propiedades estadísticas para esta medida, como el teorema del límite central permutacional, que le permite conocer la distribución de esta medida para listas aleatorias.
fuente
Además del recuento de inversión, para las listas numéricas, la distancia cuadrática media desde el estado ordenado es imaginable:
fuente
No estoy seguro del "mejor" método, pero uno simple sería comparar cada elemento con el siguiente, incrementando un contador si element2> element 1 (o lo que quiera probar) y luego dividir por el número total de elementos Debería darte un porcentaje.
fuente
Contaría las comparaciones y las dividiría entre el número total de comparaciones. Aquí hay un ejemplo simple de Python .
fuente
¿Qué tal algo como esto?
fuente
Si toma su lista, calcule los rangos de los valores en esa lista y llame a la lista de rangos
Y
y otra lista,X
que contiene los enteros de1
alength(Y)
, puede obtener exactamente la medida de ordenación que está buscando calculando el coeficiente de correlación ,r
, entre las dos listas.Para una lista completamente ordenada
r = 1.0
, para una lista ordenada inversamenter=-1.0
, yr
varía entre estos límites para distintos grados de ordenación.Un posible problema con este enfoque, dependiendo de la aplicación, es que calcular el rango de cada elemento de la lista es equivalente a ordenarlo, por lo que es una operación O (n log n).
fuente