web-dev-qa-db-ja.com

リストのソート方法を測定する方法はありますか?

リストがどの程度ソートされているかを測定する方法はありますか?

つまり、リストがソートされているかどうか(ブール値)を知ることではなく、「ソート度」の比率、統計の相関係数のようなものです。

例えば、

  • リストの項目が昇順の場合、そのレートは1.0になります

  • リストが降順でソートされている場合、そのレートは-1.0になります

  • リストがほとんど昇順でソートされている場合、そのレートは0.9または1に近い値になります。

  • リストがまったく(ランダムに)ソートされていない場合、そのレートは0に近くなります。

私はScalaで小さなライブラリを作成しています。ソートレートは便利だと思いますが、そのようなものについての情報は見つかりません。コンセプトの用語。

160
Josell

リスト(または他の順次構造)のソート方法の従来の尺度は、反転の数です。

反転の数は、ペアの数(a、b)a <b AND b << aのstインデックスです。これらの目的のために、<<は、特定の並べ替えに対して選択した順序関係を表します。

完全にソートされたリストには反転はなく、完全に反転したリストには最大数の反転があります。

24
Marcin

実際の相関を使用できます。

ソートされたリスト内の各アイテムに、ゼロから始まる整数ランクを割り当てると仮定します。要素の位置インデックスとランクのグラフは、直線上の点のように見えることに注意してください(位置とランクの相関関係は1.0)。

このデータの相関を計算できます。逆ソートの場合は、-1などを取得します。

17
Kaz

すばらしい回答がありました。完全性のために数学的な側面を追加したいと思います。

  • リストがどの程度ソートされているかを測定するには、リストがソートされたリストとどの程度相関しているかを測定します。これを行うには、ランク相関(最もよく知られている スピアマン )を使用できます。これは通常の相関とまったく同じですが、アナログ値の代わりにリスト内の要素のランクを使用しますそのアイテムの。

  • 相関coefficient(正確な並べ替えの場合は+1、正確な反転の場合は-1)など、多くの拡張機能が存在します

  • これにより、順列中心極限定理のように、このメジャーの統計的特性を得ることができ、ランダムリストに対するこのメジャーの分布を知ることができます。

4
meduz

反転カウントとは別に、数値リストの場合、ソートされた状態からの平均平方距離が考えられます。

#! 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
3
Boris Stitnicky

「最善」の方法はわかりませんが、単純な方法は、すべての要素をその後の要素と比較し、element2> element 1(またはテストするもの)の場合にカウンターを増やし、合計数で除算することです。要素の。割合が表示されます。

1
user2369405

比較をカウントし、それを比較の総数に分割します。以下に簡単な Python の例を示します。

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
1
ibrahim

このようなものはどうですか?

#!/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()
0
dstromberg

リストを取得する場合、そのリスト内の値のランクを計算し、ランクのリストYと、1からlength(Y)までの整数を含む別のリストXを呼び出します。 2つのリスト間で 相関係数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)操作になります。

0
Simon