リストがどの程度ソートされているかを測定する方法はありますか?
つまり、リストがソートされているかどうか(ブール値)を知ることではなく、「ソート度」の比率、統計の相関係数のようなものです。
例えば、
リストの項目が昇順の場合、そのレートは1.0になります
リストが降順でソートされている場合、そのレートは-1.0になります
リストがほとんど昇順でソートされている場合、そのレートは0.9または1に近い値になります。
リストがまったく(ランダムに)ソートされていない場合、そのレートは0に近くなります。
私はScalaで小さなライブラリを作成しています。ソートレートは便利だと思いますが、そのようなものについての情報は見つかりません。コンセプトの用語。
リスト(または他の順次構造)のソート方法の従来の尺度は、反転の数です。
反転の数は、ペアの数(a、b)a <b AND b <<
aのstインデックスです。これらの目的のために、<<
は、特定の並べ替えに対して選択した順序関係を表します。
完全にソートされたリストには反転はなく、完全に反転したリストには最大数の反転があります。
実際の相関を使用できます。
ソートされたリスト内の各アイテムに、ゼロから始まる整数ランクを割り当てると仮定します。要素の位置インデックスとランクのグラフは、直線上の点のように見えることに注意してください(位置とランクの相関関係は1.0)。
このデータの相関を計算できます。逆ソートの場合は、-1などを取得します。
すばらしい回答がありました。完全性のために数学的な側面を追加したいと思います。
リストがどの程度ソートされているかを測定するには、リストがソートされたリストとどの程度相関しているかを測定します。これを行うには、ランク相関(最もよく知られている スピアマン )を使用できます。これは通常の相関とまったく同じですが、アナログ値の代わりにリスト内の要素のランクを使用しますそのアイテムの。
相関coefficient(正確な並べ替えの場合は+1、正確な反転の場合は-1)など、多くの拡張機能が存在します
これにより、順列中心極限定理のように、このメジャーの統計的特性を得ることができ、ランダムリストに対するこのメジャーの分布を知ることができます。
反転カウントとは別に、数値リストの場合、ソートされた状態からの平均平方距離が考えられます。
#! 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
「最善」の方法はわかりませんが、単純な方法は、すべての要素をその後の要素と比較し、element2> element 1(またはテストするもの)の場合にカウンターを増やし、合計数で除算することです。要素の。割合が表示されます。
比較をカウントし、それを比較の総数に分割します。以下に簡単な 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
このようなものはどうですか?
#!/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()
リストを取得する場合、そのリスト内の値のランクを計算し、ランクのリスト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)操作になります。