목록이 얼마나 정렬되어 있는지 측정하는 방법이 있습니까?


161

목록이 얼마나 정렬되어 있는지 측정하는 방법이 있습니까?

목록이 정렬되어 있는지 아닌지 (부울) 아는 것이 아니라 통계의 상관 계수와 같은 "정렬"의 비율과 같은 것입니다.

예를 들어

  • 목록의 항목이 오름차순 인 경우 비율은 1.0입니다.

  • 목록이 내림차순으로 정렬되면 비율은 -1.0입니다.

  • 목록이 거의 오름차순으로 정렬되면 비율은 0.9 또는 1에 가까운 값입니다.

  • 목록이 전혀 정렬되지 않은 경우 (임의의 경우) 비율은 0에 가깝습니다.

실습을 위해 스칼라에 작은 도서관을 쓰고 있습니다. 정렬 속도가 유용하다고 생각하지만 그와 관련된 정보는 찾지 못했습니다. 어쩌면 나는 그 개념에 대한 적절한 용어를 모른다.



4
목록을 정렬하기위한 이상적인 알고리즘을 결정하는 데 사용됩니까? 예를 들어 0에 가까운 값의 경우 QuickSort가 이상적이지만 스케일의 양쪽 끝에있는 값 (거의 정렬되거나 거의 거꾸로 정렬 된 값)은 QC가 O (N ^ 2)로 이동하기 때문에 MergeSort가 훨씬 빠릅니다.
Darrel Hoffman 2016 년

8
"정렬 비율"+1
0x499602D2

1
@Fuhrmanator 확률 론적 알고리즘 버전은 정렬의 확률 론적 추정치에 도달하기 위해 정렬을 수행 할 필요가 없다. 정렬을 수행해야하는 정확한 측정 값 을 얻으려는 경우에만 해당됩니다 .
Timothy Shields 2016 년

1
냉소적이지만 재미있는 첫 번째 본능 : 삽입을 정렬하여 목록을 정렬하는 데 걸리는 시간을 확인한 다음 목록을 정렬하는 데 걸리는 시간 (이제 정렬 된 목록)과 그 반대 순서를 비교할 수 있습니다.
kqr

답변:


142

목록에서 반전 수를 간단히 계산할 수 있습니다.

전도

유형의 요소 시퀀스에서 반전 T은의 세트에서 일부 순서 <에 따라 순서가 다르게 나타나는 한 쌍의 시퀀스 요소입니다 T.

에서 위키 백과 :

공식적으로 A(1), A(2), ..., A(n)일련의 n숫자를 보자 .
만약i < jA(i) > A(j), 그 쌍은 (i,j)이라고 반전 의를 A.

그만큼 시퀀스 반전 번호 는 정렬의 일반적인 측정 방법 중 하나입니다.
공식적으로, 반전 번호는 반전 횟수, 즉,

정의

이러한 정의를보다 명확하게하려면 sequence 예제를 고려하십시오 9, 5, 7, 6. 이 순서는 반전 (0,1), (0,2), (0,3), (2,3)반전 번호가 4 있습니다.

0와 사이의 값을 원하면 1반전 숫자를로 나눌 수 있습니다 N choose 2.

목록 정렬 방식에 대해이 점수를 계산하는 알고리즘을 실제로 만들려면 다음 두 가지 방법이 있습니다.

접근법 1 (결정 론적)

자주 사용하는 정렬 알고리즘을 수정하여 실행시 수정되는 반전 수를 추적하십시오. 이것은 사소하지 않으며 선택한 정렬 알고리즘에 따라 다양한 구현이 있지만, 시작한 정렬 알고리즘보다 비싸지 않은 (복잡성 측면에서) 알고리즘으로 끝납니다.

이 경로를 사용하는 경우 "스왑"을 계산하는 것만 큼 간단하지는 않습니다. 예를 들어 Mergesort는 최악의 경우 O(N log N)이지만 내림차순으로 정렬 된 목록에서 실행하면 모든 N choose 2반전 이 수정됩니다 . 그것은 작업 O(N^2)에서 수정 된 반전 O(N log N)입니다. 따라서 일부 작업은 불가피하게 한 번에 두 개 이상의 반전을 수정해야합니다. 구현에주의를 기울여야합니다. 참고 : O(N log N)복잡 하게이 작업을 수행 할 수 있습니다 .

관련 : 순열에서 "반전"수 계산

접근법 2 (확률 론적)

  • 무작위로 샘플 쌍 (i,j),i != j
  • 각 쌍에 대해 list[min(i,j)] < list[max(i,j)](0 또는 1)
  • 이 비교의 평균을 계산 한 다음 N choose 2

나는 당신이 정확성을 요구하지 않는 한 개인적으로 확률 론적 접근을 할 것입니다-구현하기가 쉽기 때문입니다.


당신이 정말로 원하는 것은 값 (경우 z'사이) -1에 (정렬 내림차순) 1(정렬 오름차순)는, 당신은 단순히 위의 값 (매핑 할 수 있습니다 z사이에), 0(정렬 오름차순) 및 1공식을 사용하여이 범위 (정렬 내림차순) :

z' = -2 * z + 1

2
목록을 정렬하는 것이 (일반적으로) O (n * logn)이고, 역전을 계산하는 순진하고 명백한 방법은 O (n ^ 2)라는 것이 흥미 롭습니다. 반전 수를 계산하기 위해 더 나은 알고리즘이 있는지 궁금합니다.
Mark Bessey

5
이 SO 질문에는 몇 가지 흥미로운 접근법이 있습니다. stackoverflow.com/questions/6523712/… 기본적으로, 얼마나 많은 반전이 있는지 파악하기 위해 배열을 정렬하는 데 도움이됩니다.
Mark Bessey 2018 년

4
순진하게 당신이 순서가 맞지 않는 인접한 쌍을 셀 수 있다고 생각했습니다. 그러나 그것은 심각하게 과소 평가 될 것입니다 : 1 2 3 1 2 3은 하나의 인접한 반전을 가지고 있지만,보다 정확한 측정에 의해 50 % 반전됩니다.
Barmar

2
@Barmar 나는 목록 1 2 3 1 2 3이 일종의 분류 된 자격이 있다고 생각한다 ;-)
scunliffe

2
@TimothyShields는 그렇지 않습니다. 그러나 나는 요점을 다루지 않을 것이다. 덜 상징적 인 경향에 더 접근하기 쉬운 비 형식적 정의를 추가하라는 제안.
Chris Calo 2016 년

24

목록 (또는 다른 순차적 구조)을 정렬하는 방법에 대한 전통적인 측정 방법은 반전의 수입니다.

반전 수는 a <b AND b a의 쌍 (a, b) st 인덱스 수입니다 <<. 이러한 목적 <<을 위해 특정 정렬에 대해 선택한 주문 관계를 나타냅니다.

완전히 정렬 된 목록에는 반전이없고 완전히 반대의 목록에는 최대 반전 수가 있습니다.


5
기술적으로, 5 4 3 2 1주문이 지정되지 않았으므로 완전히 정렬되었지만, 나는
paxdiablo

7
@paxdiablo의 정의에 따라 다릅니다 <.
Marcin

@ paxdiablo, 반전 수에서 0 또는 가장 가까운 거리까지의 정렬을 측정 할 수 n choose 2있습니다.
huon

17

실제 상관 관계를 사용할 수 있습니다.

정렬 된 목록의 각 항목에 0부터 시작하는 정수 순위를 지정한다고 가정하십시오. 요소 위치 인덱스 대 순위의 그래프는 직선의 점처럼 보입니다 (위치와 순위 사이의 상관 관계는 1.0).

이 데이터에 대한 상관 관계를 계산할 수 있습니다. 역 정렬의 경우 -1 등이 표시됩니다.


1
죄송하지만 정수를 할당하는 방법과 같이 설명 할 수없는 부분이 너무 많습니다.
Marcin

2
정수를 할당하려면 정렬 된 목록이 필요합니다. 그런 다음 항목의 열거입니다.
Kaz

1
정확히 내가 제안하려고했던 것. 원본 목록의 객체 위치와 정렬 된 목록의 위치 사이의 상관 관계를 결정하십시오. 나쁜 소식은 상관 루틴이 O (n ^ 2)에서 실행될 수 있다는 것입니다. 좋은 소식은 아마도 여러분의 환경에 적합 할 것입니다.
Peter Webb

2
네, 스피어 맨의 rho en.wikipedia.org/wiki/…
Lucas

궁금합니다 ...이 방법은 반전 횟수를 확장하는 것과 같습니다.
Clayton Stanley

4

큰 답이 있었고, 완성도를 위해 수학적 측면을 추가하고 싶습니다.

  • 정렬 된 목록과 얼마나 관련되어 있는지 측정하여 목록이 정렬 된 정도를 측정 할 수 있습니다. 그렇게하려면 순위 상관 관계 (가장 알려진 Spearman 's )를 사용하면 일반적인 상관 관계와 정확히 동일하지만 항목의 아날로그 값 대신 목록에서 요소의 순위를 사용합니다.

  • 상관 계수 (정확한 정렬의 경우 +1, 정확한 반전의 경우 -1) 와 같은 많은 확장이 존재합니다.

  • 이를 통해 순열 중심 한계 정리와 같이이 측정에 대한 통계적 속성을 가질 수 있으며,이를 통해 임의의 목록에 대한이 측정의 분포를 알 수 있습니다.


3

숫자 목록의 경우 반전 수를 제외하고 정렬 된 상태에서 평균 제곱 거리를 상상할 수 있습니다.

#! ruby
d = -> a { a.zip( a.sort ).map { |u, v| ( u - v ) ** 2 }.reduce( :+ ) ** 0.5 }

a = 8, 7, 3, 4, 10, 9, 6, 2, 5, 1
d.( a ) #=> 15.556
d.( a.sort ) #=> 0.0
d.( a.sort.reverse ) # => 18.166 is the worrst case

이것이 표준 상관 함수의 제곱이라고 생각합니다 . en.wikipedia.org/wiki/Correlation_ratio를 참조하십시오 . 숫자가 아닌 목록에도 동일하게 적용됩니다. 비교되는 두 값은 두 목록에서 객체의 위치입니다.
Peter Webb

나는 단순한 사람입니다. 상관 관계 비율이 무엇인지조차조차 알지 못합니다. Wikipedia 기사를 읽으면 "통계 분산"이 무엇인지, "표준 편차", "변이", "인터 클래스 상관 계수"가 무엇인지 배우라는 요청을받습니다. 나는 그 모든 것을 여러 번 배웠다. 나는 그것을 다시 잊었다. 이 실용적인 답변에서, 나는 피타고라스 정리로 두 벡터 사이의 거리를 측정합니다. 초등학교에서 기억하는 것입니다.
Boris Stitnicky 2016 년

1

나는 "최상의"방법을 확신하지 못하지만 간단한 방법은 모든 요소를 ​​그다음 요소와 비교하고 element2> element 1 (또는 테스트하려는 대상)이면 카운터를 증가시킨 다음 총 수로 나눕니다. 요소 그것은 당신에게 백분율을 제공해야합니다.


1

나는 비교를 세어 총 비교 수로 나눕니다. 다음은 간단한 파이썬 예제입니다.

my_list = [1,4,5,6,9,-1,5,3,55,11,12,13,14]

right_comparison_count = 0

for i in range(len(my_list)-1):
    if my_list[i] < my_list[i+1]: # Assume you want to it ascending order
        right_comparison_count += 1

if right_comparison_count == 0:
    result = -1
else:
    result = float(right_comparison_count) / float((len(my_list) - 1))

print result

0

이런 건 어때?

#!/usr/bin/python3

def sign(x, y):
   if x < y:
      return 1
   elif x > y:
      return -1
   else:
      return 0

def mean(list_):
   return float(sum(list_)) / float(len(list_))

def main():
   list_ = [ 1, 2, 3, 4, 6, 5, 7, 8 ]
   signs = []
   # this zip is pairing up element 0, 1, then 1, 2, then 2, 3, etc...
   for elem1, elem2 in zip(list_[:-1], list_[1:]):
      signs.append(sign(elem1, elem2))

   # This should print 1 for a sorted list, -1 for a list that is in reverse order
   # and 0 for a run of the same numbers, like all 4's
   print(mean(signs))

main()

2
인접한 반전 만 계산합니다. 다른 답변을 보면 이것이 불충분하다는 것을 알 수 있습니다.
Konrad Rudolph

1
@ KonradRudolph :이 답변이 요청 된대로 질문을 충족한다고 생각합니다. 다른 답변이 더 포괄적이라는 사실이 이것이 충분하지 않다는 것을 의미하지는 않습니다. OP의 요구 사항에 따라 다릅니다.
LarsH

0

목록을 가져 와서 해당 목록에있는 값의 순위를 계산하고 에서 ~ 까지의 정수를 포함하는 순위 Y목록과 다른 목록을 호출 하면 상관 계수 를 계산하여 찾고있는 정렬 측정 값을 정확하게 얻을 수 있습니다. ,, 두 목록 사이에 있습니다.X1length(Y)r

r = \frac{\sum ^n _{i=1}(X_i - \bar{X})(Y_i - \bar{Y})}{\sqrt{\sum ^n _{i=1}(X_i - \bar{X})^2} \sqrt{\sum ^n _{i=1}(Y_i - \bar{Y})^2}} 

완전 정렬 된 목록의 경우 r = 1.0, 역방향 정렬 된 목록의 경우 r=-1.0,r 다양한 수준에 대한 이러한 한계 사이 차이가 있습니다.

응용 프로그램에 따라이 방법의 가능한 문제점은 목록에서 각 항목의 순위를 계산하는 것이 정렬하는 것과 동일하므로 O (n log n) 연산입니다.


그러나 곡선 모양을 무시하지는 않습니다. 그의 배열이 정렬되지만 지수 적으로 증가하는 값을 포함하면 상관 관계는 1.0이되기를 원하는 곳에서 작습니다.
리 다니엘 크로커

@LeeDanielCrocker : 네, 좋은 지적입니다. 나는 가치를 평가하여 이것을 해결하기 위해 내 대답을 수정했습니다.
Simon
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.