Bir listenin ne kadar sıralandığını ölçmenin bir yolu var mı?


161

Bir listenin nasıl sıralandığını ölçmenin bir yolu var mı?

Yani, bir listenin sıralanıp sıralanmadığını (boolean) bilmekle ilgili değil, "sıralama" oranı gibi bir şey, istatistiklerdeki korelasyon katsayısı gibi bir şey.

Örneğin,

  • Bir listenin öğeleri artan sıradaysa, oranı 1.0 olur

  • Liste azalan şekilde sıralanırsa, oranı -1.0 olur

  • Liste neredeyse artan şekilde sıralanıyorsa, oranı 0,9 veya 1'e yakın bir değer olacaktır.

  • Liste hiç sıralanmamışsa (rastgele), oranı 0'a yakın olacaktır

Uygulama için Scala'da küçük bir kütüphane yazıyorum. Ben bir sıralama oranı yararlı olacağını düşünüyorum, ama böyle bir şey hakkında herhangi bir bilgi bulamıyorum. Belki de kavram için yeterli terimleri bilmiyorum.



4
Bu listeyi sıralamak için ideal algoritmayı belirlemek için kullanılabilir mi? Örneğin, 0'a yakın değerler için QuickSort ideal olur, ancak ölçeğin her iki ucundaki değerler (neredeyse sıralanır veya neredeyse ters sıralanır), bu durumlarda QC O'ya (N ^ 2) dönüştüğü için MergeSort çok daha hızlı olacaktır.
Darrel Hoffman

8
"Oranlama oranı" için +1
0x499602D2

1
@Fuhrmanator Algoritmanın stokastik versiyonunun, sıralamanın olasılıklı bir tahminine ulaşmak için bir sıralama yapması gerekmez. Sadece bir tür bir işlem yapmanız gereken kesin bir ölçü almak istiyorsanız .
Timothy Shields

1
Alaycı ama komik ilk içgüdü: Listeyi ekleyebilir ve listenin ne kadar sürdüğünü görebilir ve ardından listeyi (şimdi sıralanan) listenin ve bunun tersinin ne kadar süreceği ile karşılaştırabilirsiniz.
kqr

Yanıtlar:


142

Listedeki ters çevirme sayısını sayabilirsiniz.

ters çevirme

Bir dizi eleman dizisindeki ters çevirme , 's setindeki Tbazı sıralamaya göre sıra dışı görünen bir çift dizi elemanıdır .<T

Gönderen Vikipedi :

Resmi olarak, A(1), A(2), ..., A(n)bir nsayı dizisi olsun .
Eğer i < jve A(i) > A(j)ardından çifti (i,j)bir denir inversiyon arasındaA .

Ters numarası bir sekansın kendi sortedness biri ortak bir ölçüsüdür.
Resmi olarak, ters çevirme sayısı, ters çevirme sayısı, yani,

tanım

Bu tanımları daha açık hale getirmek için örnek sıralamayı göz önünde bulundurun 9, 5, 7, 6. Bu sekansın inversiyonları (0,1), (0,2), (0,3), (2,3) ve inversiyon sayısı vardır 4 .

0Ve arasında bir değer 1istiyorsanız, ters çevirme numarasınıN choose 2 .

Bir listenin nasıl sıralandığına ilişkin bu puanı hesaplamak için bir algoritma oluşturmak için iki yaklaşımınız vardır:

Yaklaşım 1 (Deterministik)

Çalışırken kaç ters çevirme olduğunu takip etmek için favori sıralama algoritmanızı değiştirin. Bu önemsiz olsa da ve seçtiğiniz sıralama algoritmasına bağlı olarak farklı uygulamalara sahip olsa da, başladığınız sıralama algoritmasından daha pahalı olmayan (karmaşıklık açısından) bir algoritma elde edeceksiniz.

Bu rotayı izlerseniz, bunun "swap" saymak kadar basit olmadığını unutmayın. Örneğin, Mergesort en kötü durumdur O(N log N), ancak azalan düzende sıralanmış bir listede çalıştırılırsa, tüm N choose 2inversiyonları düzeltir . Bu O(N^2), O(N log N)işlemlerde düzeltmeler düzeltildi . Bu nedenle, bazı işlemler kaçınılmaz olarak bir seferde birden fazla evirmeyi düzeltiyor olmalıdır. Uygulamanıza dikkat etmelisiniz. Not: Bunu O(N log N)karmaşıklıkla yapabilirsiniz, sadece zor.

İlgili: permütasyondaki “inversiyon” sayısının hesaplanması

Yaklaşım 2 (Stokastik)

  • Rastgele örnekleme çiftleri (i,j), buradai != j
  • Her çift için list[min(i,j)] < list[max(i,j)](0 veya 1)
  • Bu karşılaştırmaların ortalamasını hesaplayın ve ardından normalleştirin N choose 2

Kesinlik gereksiniminiz olmadıkça şahsen stokastik yaklaşımla devam ederdim - sadece uygulanması çok kolay olduğu için.


Gerçekten istediğiniz ( (azalan sıralama) ile (artan sıralama z') arasındaki bir değer ( ) ise , bu formülü kullanarak ( artan sıralama) ve (sıralama azalan) arasındaki yukarıdaki ( ) değeri basitçe eşleyebilirsiniz. :-11z01

z' = -2 * z + 1

2
Bir listeyi sıralamanın (tipik olarak) O (n * logn) ve ters / açık hesaplama tersine çevirme yönteminin O (n ^ 2) olması beni büyüleyicidir. Ben ters sayısı hesaplamak için orada daha iyi algoritmalar olup olmadığını merak ediyorum?
Mark Bessey

5
Bu SO sorusunda birkaç ilginç yaklaşım var: stackoverflow.com/questions/6523712/… Temel olarak, kaç tane inversiyon olduğunu anlamak için diziyi sıralamaya değer.
Mark Bessey

4
Saf bir şekilde, sıra dışı olan bitişik çiftleri sayabileceğinizi düşündüm. Ancak bu ciddi bir şekilde az anlaşılacaktır: 1 2 3 1 2 3 sadece bir bitişik ters çevirmeye sahiptir, ancak% 50 daha doğru önlemle ters çevrilir.
Barmar

2
@Barmar Ben liste 1 2 3 1 2 3 sorta sıralı ;-)
scunliffe

2
@TimothyShields, hayır, hayır, değil. Ama konuyu çok şaşırtmayacağım. Daha az sembolik eğime daha kolay erişilebilen, resmi olmayan bir tanım eklemek için bir öneri.
Chris Calo

24

Bir listenin (veya başka bir ardışık yapının) nasıl sıralandığının geleneksel ölçüsü, ters çevirme sayısıdır.

Ters çevirme sayısı bir çiftin (a, b) bir <b AND b <<a çift ​​indeksidir . Bu amaçlar için<< için, kendi sıralamanız için hangi sipariş ilişkisini seçerseniz seçin.

Tamamen sıralanmış bir listede ters çevirme yoktur ve tamamen ters çevrilmiş bir listede maksimum ters çevirme sayısı bulunur.


5
Teknik olarak, 5 4 3 2 1sipariş belirtilmemişse beri tamamen sıralanır ama :-) bilgiçlik açıyorum
paxdiablo

7
@paxdiablo Bu, tanımına bağlıdır <.
Marcin

@paxdiablo, iyi bir sıralama enversiyon sayısı 0 veya en yakın mesafe ölçülebilir n choose 2.
huon

17

Gerçek korelasyon kullanabilirsiniz.

Sıralı listedeki her öğeye sıfırdan başlayarak bir tamsayı sırası atadığınızı varsayalım. Öğelerin konum indeksinin sıralamaya göre grafiğinin düz bir çizgideki noktalara benzeyeceğini unutmayın (konum ve sıralama arasındaki korelasyon 1.0).

Bu veriler üzerinde bir korelasyon hesaplayabilirsiniz. Tersine sıralama için -1 ve benzerlerini alırsınız.


1
Üzgünüm, ama bu tamsayıları nasıl atadığınız gibi çok açıklanmıyor.
Marcin

2
Tamsayıları atamak için sıralı listeye ihtiyacınız vardır; o zaman sadece öğelerin numaralandırmasıdır.
Kaz

1
Tam olarak ne önerecektim. Nesnenin orijinal listedeki konumu ile sıralanan listedeki konumu arasındaki korelasyonu belirleyin. Kötü haber şu ki korelasyon rutinleri muhtemelen O (n ^ 2) 'de çalışıyor; iyi haber, muhtemelen çevreniz için hazır.
Peter Webb

2
Evet, sadece Spearman'ın rho en.wikipedia.org/wiki/…
Lucas

Merak ediyorum ... Bu yaklaşım, ters çevirme sayısının ölçeklendirilmesine eşit mi?
Clayton Stanley

4

Harika cevaplar oldu ve bütünlük için matematiksel bir yön eklemek istiyorum:

  • Sıralı listeyle ne kadar ilişkili olduğunu ölçerek listenin ne kadar sıralandığını ölçebilirsiniz. Bunu yapmak için, normal korelasyonla tam olarak aynı olan sıralama korelasyonunu (en bilinen Spearman'tır ) kullanabilirsiniz, ancak öğelerinin analog değerleri yerine bir listedeki öğelerin sıralamasını kullanır.

  • Korelasyon katsayısı gibi birçok uzantı mevcuttur (tam sıralama için +1, tam ters çevirme için -1)

  • Bu, bu hesaplamanın rasgele listeler için bu hesaplamanın dağılımını bilmenizi sağlayan permütasyonel merkezi limit teoremi gibi istatistiksel özelliklere sahip olmanızı sağlar.


3

Ters çevirme sayımı dışında, sayısal listeler için, sıralanan durumdan ortalama kare mesafesi düşünülebilir:

#! 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

Bence bu standart korelasyon fonksiyonunun karesi, bkz. En.wikipedia.org/wiki/Correlation_ratio . Sayısal olmayan listelere de aynı şekilde uygulanır; karşılaştırılan iki değer, nesnenin iki listedeki konumudur.
Peter Webb

Ben bir Simpleton'um. Korelasyon oranının ne olduğunu bile bilmiyorum. Bu Wikipedia makalesini okuduğumda, en üstte, "istatistiksel dağılım", sonra "standart sapma", sonra "varyasyon", sonra "sınıflar arası korelasyon katsayısı" ne olduğunu öğrenmem isteniyor. Tüm bunları öğrendim, birkaç kez ve birkaç kez tekrar unuttum. Benim bu pragmatik cevabımda, ilkokuldan hatırladığım Pisagor teoremi ile iki vektör arasındaki mesafeyi ölçüyorum.
Boris Stitnicky

1

Ben "en iyi" yöntem emin değilim, ama basit bir element2> element 1 (veya test etmek istediğiniz ne olursa olsun) bir sayaç artış ve daha sonra toplam sayıya bölmek, her öğeyi bir sonraki ile karşılaştırmak olacaktır öğeleri kümesi. Size bir yüzde vermelidir.


1

Karşılaştırmaları sayıp toplam karşılaştırma sayısına bölerdim. İşte basit bir Python örneği.

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

Böyle bir şeye ne dersin?

#!/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
Bu sadece bitişik ters çevirmeleri sayar. Diğer cevaplara bakarsanız bunun yetersiz olduğunu göreceksiniz.
Konrad Rudolph

1
@KonradRudolph: Bence bu cevap sorulan soruyu tatmin ediyor. Diğer cevapların daha kapsamlı olması, bu sorunun yetersiz olduğu anlamına gelmez; OP'nin gereksinimlerine bağlıdır.
LarsH

0

Listenizi ele alırsak, o listedeki değerlerin saflarına hesaplamak ve rütbeleri listesini çağırmak Yve başka bir listeye, Xgelen tamsayılar içerir 1için length(Y), size hesaplanarak için size aradığınız o sortedness tam ölçüsünü elde edebilirsiniz korelasyon katsayısı ,, riki liste arasında.

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}} 

Tam sıralı bir liste r = 1.0için, ters sıralı bir liste için r=-1.0ver sortedness değişen derecelerde bu limitler arasında değişiklik gösterir.

Uygulamaya bağlı olarak bu yaklaşımla ilgili olası bir problem, listedeki her bir öğenin sırasının hesaplanmasının onu sıralamaya eşdeğer olmasıdır, bu nedenle O (n log n) işlemidir.


Ancak bu eğri şeklini göz ardı etmez. Dizisi sıralanır, ancak diyelim ki katlanarak artan değerler içeriyorsa, korelasyon 1.0 olmasını istediği yerde küçük olacaktır.
Lee Daniel Crocker

@LeeDanielCrocker: Evet, bu iyi bir nokta. Cevabımı, değerlerin derecelerini alarak bunu ele almak için değiştirdim.
Simon
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.