Czy istnieje sposób sprawdzenia, jak posortowana jest lista?
Chodzi mi o to, że nie chodzi o to, aby wiedzieć, czy lista jest posortowana, czy nie (boolean), ale coś w rodzaju współczynnika „sortowania”, czegoś w rodzaju współczynnika korelacji w statystyce.
Na przykład,
Jeśli pozycje na liście są w porządku rosnącym, to jej kurs wyniesie 1,0
Jeśli lista jest posortowana malejąco, jej współczynnik wyniesie -1,0
Jeśli lista jest prawie posortowana rosnąco, jej współczynnik wyniesie 0,9 lub jakąś wartość bliską 1.
Jeśli lista nie jest w ogóle posortowana (losowa), jej współczynnik byłby bliski 0
Piszę małą bibliotekę w Scali do ćwiczeń. Myślę, że przydałby się współczynnik sortowania, ale nie znajduję żadnych informacji o czymś takim. Może nie znam odpowiednich terminów na to pojęcie.
Odpowiedzi:
Możesz po prostu policzyć liczbę inwersji na liście.
Odwrócenie
Odwrócenie w ciągu elementów typu
T
to para elementów sekwencji, które pojawiają się nie w porządku według pewnego uporządkowania<
na zbiorze elementówT
.Z Wikipedii :
Aby wyjaśnić te definicje, rozważ przykładową sekwencję
9, 5, 7, 6
. Ta sekwencja ma inwersje(0,1), (0,2), (0,3), (2,3)
i numer inwersji4
.Jeśli chcesz uzyskać wartość między
0
a1
, możesz podzielić liczbę inwersji przezN choose 2
.Aby faktycznie utworzyć algorytm obliczający ten wynik dla posortowania listy, masz dwa podejścia:
Podejście 1 (deterministyczne)
Zmodyfikuj swój ulubiony algorytm sortowania, aby śledzić, ile inwersji koryguje podczas działania. Chociaż jest to nietrywialne i ma różne implementacje w zależności od wybranego algorytmu sortowania, otrzymasz algorytm, który nie jest droższy (pod względem złożoności) niż algorytm sortowania, od którego zacząłeś.
Jeśli wybierzesz tę trasę, pamiętaj, że nie jest to tak proste, jak liczenie „zamiany”. Na przykład scalanie jest najgorszym przypadkiem
O(N log N)
, ale jeśli zostanie uruchomione na liście posortowanej w porządku malejącym, poprawi wszystkieN choose 2
inwersje. To jestO(N^2)
odwrócenie poprawione wO(N log N)
operacjach. Dlatego niektóre operacje muszą nieuchronnie korygować więcej niż jedną inwersję naraz. Musisz uważać na swoją implementację. Uwaga: możesz to zrobić zeO(N log N)
złożonością, to po prostu trudne.Powiązane: obliczanie liczby „inwersji” w permutacji
Podejście 2 (stochastyczne)
(i,j)
, gdziei != j
list[min(i,j)] < list[max(i,j)]
(0 czy 1)N choose 2
Osobiście wybrałbym podejście stochastyczne, chyba że masz wymóg dokładności - choćby dlatego, że jest tak łatwy do wdrożenia.
Jeśli naprawdę potrzebujesz wartości (
z'
) między-1
(posortowane malejąco) do1
(posortowane rosnąco), możesz po prostu zmapować wartość powyżej (z
), która znajduje się pomiędzy0
(posortowano rosnąco) i1
(posortowano malejąco), na ten zakres przy użyciu tej formuły :źródło
Tradycyjną miarą sortowania listy (lub innej struktury sekwencyjnej) jest liczba inwersji.
Liczba inwersji to liczba par (a, b). Indeks a <b ORAZ b
<<
a. W tym celu<<
reprezentuje dowolną relację porządkową wybraną dla określonego rodzaju.W pełni posortowana lista nie zawiera inwersji, a całkowicie odwrócona lista ma maksymalną liczbę inwersji.
źródło
5 4 3 2 1
jest w pełni posortowane, ponieważ kolejność nie jest określona, ale jestem pedantyczny :-)<
.n choose 2
.Możesz użyć rzeczywistej korelacji.
Załóżmy, że każdemu elementowi na posortowanej liście przypisujesz liczbę całkowitą, zaczynając od zera. Zwróć uwagę, że wykres wskaźnika pozycji elementów w funkcji rangi będzie wyglądał jak kropki w linii prostej (korelacja 1,0 między pozycją a pozycją).
Możesz obliczyć korelację na tych danych. W przypadku sortowania odwrotnego otrzymasz -1 i tak dalej.
źródło
Były świetne odpowiedzi i chciałbym dodać matematyczny aspekt dla kompletności:
Posortowaną listę można zmierzyć, mierząc, w jakim stopniu jest ona skorelowana z posortowaną listą. Aby to zrobić, możesz użyć korelacji rang (najbardziej znanej jest korelacja Spearmana ), która jest dokładnie taka sama jak zwykła korelacja, ale używa rangi elementów na liście zamiast wartości analogowych jej elementów.
Istnieje wiele rozszerzeń, takich jak współczynnik korelacji (+1 dla dokładnego sortowania, -1 dla dokładnej inwersji)
Pozwala to mieć właściwości statystyczne dla tej miary, takie jak permutacyjne centralne twierdzenie graniczne, które pozwala poznać rozkład tej miary dla list losowych.
źródło
Oprócz liczby inwersji, w przypadku list numerycznych można sobie wyobrazić średnią kwadratową odległość od posortowanego stanu:
źródło
Nie jestem pewien "najlepszej" metody, ale prostą metodą byłoby porównanie każdego elementu z kolejnym, zwiększając licznik, jeśli element2> element 1 (lub cokolwiek chcesz przetestować), a następnie podzielenie przez całkowitą liczbę elementów. Powinien dać ci procent.
źródło
Policzyłbym porównania i podzieliłbym je na całkowitą liczbę porównań. Oto prosty przykład w języku Python .
źródło
A może coś takiego?
źródło
Jeśli weźmiesz swoją listę, obliczysz rangi wartości na tej liście i wywołaj listę rang
Y
oraz inną listę,X
która zawiera liczby całkowite od1
dolength(Y)
, możesz uzyskać dokładnie taką miarę sortowania, której szukasz, obliczając współczynnik korelacji ,r
między dwiema listami.W przypadku w pełni posortowanej listy,, w przypadku listy posortowanej
r = 1.0
odwrotnier=-1.0
, ir
waha się między tymi limitami dla różnych stopni sortowania .Możliwym problemem związanym z tym podejściem, w zależności od aplikacji, jest to, że obliczenie rangi każdego elementu na liście jest równoważne jego sortowaniu, więc jest to operacja O (n log n).
źródło