Có cách nào để đo lường cách sắp xếp danh sách không?


161

Có cách nào để đo lường cách sắp xếp danh sách không?

Ý tôi là, đó không phải là về việc biết một danh sách có được sắp xếp hay không (boolean), mà là một cái gì đó giống như tỷ lệ "sắp xếp", một cái gì đó giống như hệ số tương quan trong thống kê.

Ví dụ,

  • Nếu các mục của danh sách theo thứ tự tăng dần, thì tỷ lệ của nó sẽ là 1.0

  • Nếu danh sách được sắp xếp giảm dần, tỷ lệ của nó sẽ là -1.0

  • Nếu danh sách gần như được sắp xếp tăng dần, tỷ lệ của nó sẽ là 0,9 hoặc một số giá trị gần bằng 1.

  • Nếu danh sách hoàn toàn không được sắp xếp (ngẫu nhiên), tỷ lệ của nó sẽ gần bằng 0

Tôi đang viết một thư viện nhỏ ở Scala để thực hành. Tôi nghĩ rằng một tỷ lệ sắp xếp sẽ hữu ích, nhưng tôi không tìm thấy bất kỳ thông tin nào về điều đó. Có lẽ tôi không biết các điều khoản đầy đủ cho khái niệm này.



4
Điều này sẽ được sử dụng để xác định thuật toán lý tưởng để sắp xếp danh sách? Ví dụ: đối với các giá trị gần bằng 0, QuickSort sẽ là lý tưởng, nhưng các giá trị ở hai đầu của thang đo (sắp xếp gần hoặc sắp xếp ngược lại), MergeSort sẽ nhanh hơn nhiều, vì QC phá hủy thành O (N ^ 2) trong các trường hợp đó.
Darrel Hoffman

8
+1 cho "tỷ lệ sắp xếp"
0x499602D2

1
@Fuhrmanator Phiên bản ngẫu nhiên của thuật toán không phải thực hiện sắp xếp để đi đến ước tính xác suất của sự sắp xếp. Chỉ khi bạn muốn có được một thước đo chính xác mà bạn cần thực hiện một loại.
Timothy Shields

1
Sarcastic nhưng bản năng đầu tiên hài hước: Bạn có thể chèn sắp xếp danh sách và xem nó mất bao lâu, sau đó so sánh nó với thời gian để sắp xếp (danh sách hiện được sắp xếp) và đảo ngược của nó.
kqr

Câu trả lời:


142

Bạn chỉ có thể đếm số lượng đảo ngược trong danh sách.

Nghịch đảo

Một nghịch đảo trong một chuỗi các phần tử loại Tlà một cặp các phần tử trình tự xuất hiện không theo thứ tự theo một số thứ tự <trên tập hợp của T.

Từ Wikipedia :

Chính thức, hãy A(1), A(2), ..., A(n)là một chuỗi các nsố.
Nếu i < jA(i) > A(j), sau đó cặp (i,j)được gọi là đảo ngược của A.

Các số nghịch đảo của một chuỗi là một trong những biện pháp phổ biến của sortedness của nó.
Chính thức, số đảo ngược được định nghĩa là số lượng đảo ngược, nghĩa là,

Định nghĩa

Để làm cho các định nghĩa rõ ràng hơn, hãy xem xét trình tự ví dụ 9, 5, 7, 6. Trình tự này có các nghịch đảo (0,1), (0,2), (0,3), (2,3)số đảo ngược 4 .

Nếu bạn muốn một giá trị giữa 01, bạn có thể chia số đảo ngược cho N choose 2.

Để thực sự tạo ra một thuật toán để tính điểm này cho cách sắp xếp danh sách, bạn có hai cách tiếp cận:

Cách tiếp cận 1 (Xác định)

Sửa đổi thuật toán sắp xếp yêu thích của bạn để theo dõi xem có bao nhiêu nghịch đảo khi nó chạy. Mặc dù điều này là không cần thiết và có các triển khai khác nhau tùy thuộc vào thuật toán sắp xếp bạn chọn, nhưng bạn sẽ kết thúc với một thuật toán không đắt hơn (về độ phức tạp) so với thuật toán sắp xếp bạn đã bắt đầu.

Nếu bạn đi theo con đường này, hãy lưu ý rằng nó không đơn giản như đếm "hoán đổi". Mergesort, ví dụ, là trường hợp xấu nhất O(N log N), nhưng nếu nó được chạy trên một danh sách được sắp xếp theo thứ tự giảm dần, nó sẽ sửa tất cả các N choose 2nghịch đảo. Đó là O(N^2)sự đảo ngược được sửa chữa trong O(N log N)hoạt động. Vì vậy, một số thao tác chắc chắn phải được sửa nhiều hơn một lần đảo ngược tại một thời điểm. Bạn phải cẩn thận với việc thực hiện của bạn. Lưu ý: bạn có thể làm điều này với O(N log N)sự phức tạp, nó chỉ là khó khăn.

Liên quan: tính toán số lần đảo ngược của người Viking trong một hoán vị

Cách tiếp cận 2 (Stochastic)

  • Các cặp mẫu ngẫu nhiên (i,j), trong đói != j
  • Đối với mỗi cặp, xác định xem list[min(i,j)] < list[max(i,j)](0 hoặc 1)
  • Tính trung bình của các so sánh này và sau đó bình thường hóa bằng N choose 2

Cá nhân tôi sẽ đi theo phương pháp ngẫu nhiên trừ khi bạn có yêu cầu về tính chính xác - nếu chỉ vì nó rất dễ thực hiện.


Nếu thứ bạn thực sự muốn là một giá trị ( z') nằm giữa -1(được sắp xếp giảm dần) đến 1(được sắp xếp tăng dần), bạn có thể chỉ cần ánh xạ giá trị ở trên ( z), nằm giữa 0(sắp xếp tăng dần) và 1(sắp xếp giảm dần), cho phạm vi này bằng công thức này :

z' = -2 * z + 1

2
Đối với tôi, việc sắp xếp một danh sách là (thường) O (n * logn) và phương pháp nghịch đảo tính toán rõ ràng / rõ ràng là O (n ^ 2). Tôi tự hỏi nếu có các thuật toán tốt hơn ngoài kia để tính toán số lượng nghịch đảo?
Mark Bessey

5
Có một vài cách tiếp cận thú vị trong câu hỏi SO này: stackoverflow.com/questions/6523712/NH Về cơ bản, họ tính đến việc sắp xếp mảng để tìm ra có bao nhiêu nghịch đảo.
Mark Bessey

4
Tôi ngây thơ nghĩ rằng bạn chỉ có thể đếm các cặp liền kề không theo thứ tự. Nhưng điều đó sẽ giảm đáng kể: 1 2 3 1 2 3 chỉ có một đảo ngược liền kề, nhưng nó đảo ngược 50% bằng biện pháp chính xác hơn.
Barmar

2
@Barmar Tôi nghĩ rằng danh sách 1 2 3 1 2 3 sẽ đủ điều kiện được sắp xếp theo thứ tự ;-)
scunliffe

2
@TimothyShields, tốt, không, không phải vậy. Nhưng tôi sẽ không tin vào quan điểm. Chỉ cần một đề xuất để thêm một định nghĩa không chính thức dễ tiếp cận hơn với khuynh hướng ít tượng trưng hơn.
Chris Calo

24

Thước đo truyền thống về cách sắp xếp danh sách (hoặc cấu trúc tuần tự khác) là số lượng đảo ngược.

Số lượng nghịch đảo là số chỉ số (a, b) st của a <b AND b <<a. Đối với những mục đích này <<đại diện cho bất kỳ mối quan hệ đặt hàng nào bạn chọn cho loại cụ thể của bạn.

Một danh sách được sắp xếp đầy đủ không có nghịch đảo và một danh sách đảo ngược hoàn toàn có số lượng đảo ngược tối đa.


5
Về mặt kỹ thuật, 5 4 3 2 1được sắp xếp đầy đủ vì đơn hàng không được chỉ định, nhưng tôi là người phạm tội :-)
paxdiablo

7
@paxdiablo Điều đó phụ thuộc vào định nghĩa của <.
Marcin

@paxdiablo, người ta có thể đo lường sự sắp xếp theo khoảng cách từ số lần đảo ngược đến gần nhất bằng 0 hoặc n choose 2.
huon

17

Bạn có thể sử dụng tương quan thực tế.

Giả sử rằng với mỗi mục trong danh sách được sắp xếp, bạn chỉ định thứ hạng nguyên bắt đầu từ số không. Lưu ý rằng một biểu đồ của chỉ số vị trí các yếu tố so với xếp hạng sẽ trông giống như các chấm trên một đường thẳng (tương quan 1.0 giữa vị trí và xếp hạng).

Bạn có thể tính toán một mối tương quan trên dữ liệu này. Đối với một loại ngược lại, bạn sẽ nhận được -1 và như vậy.


1
Tôi xin lỗi, nhưng điều này để lại quá nhiều điều không giải thích được, như cách bạn gán các số nguyên.
Marcin

2
Bạn cần danh sách được sắp xếp để gán các số nguyên; sau đó nó chỉ là một bảng liệt kê của các mặt hàng.
Kaz

1
Chính xác những gì tôi sẽ đề nghị. Xác định mối tương quan giữa vị trí của đối tượng trong danh sách ban đầu và vị trí của nó trong danh sách được sắp xếp. Tin xấu là các thói quen tương quan có thể chạy trong O (n ^ 2); tin tốt là chúng có thể không phù hợp với môi trường của bạn.
Peter Webb

2
Vâng, chỉ là Spearman's rho en.wikipedia.org/wiki/ Kẻ
Lucas

Tôi tò mò ... cách tiếp cận này có tương đương với việc nhân rộng số lượng đảo ngược không?
Clayton Stanley

4

Đã có câu trả lời tuyệt vời, và tôi muốn thêm một khía cạnh toán học cho đầy đủ:

  • Bạn có thể đo lường cách sắp xếp danh sách bằng cách đo mức độ tương quan với danh sách được sắp xếp. Để làm điều đó, bạn có thể sử dụng tương quan xếp hạng (được biết đến nhiều nhất là Spearman ), giống hệt như tương quan thông thường, nhưng nó sử dụng thứ hạng của các thành phần trong danh sách thay vì giá trị tương tự của các mục.

  • Nhiều tiện ích mở rộng tồn tại, như hệ số tương quan (+1 cho loại chính xác, -1 cho đảo ngược chính xác)

  • Điều này cho phép bạn có các thuộc tính thống kê cho biện pháp này, như định lý giới hạn trung tâm hoán vị, cho phép bạn biết phân phối của biện pháp này cho các danh sách ngẫu nhiên.


3

Ngoài số lượng đảo ngược, đối với danh sách số, khoảng cách bình phương trung bình từ trạng thái được sắp xếp là có thể tưởng tượng:

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

Tôi nghĩ đó là bình phương của hàm tương quan chuẩn, xem en.wikipedia.org/wiki/Correlation_ratio . Và áp dụng như nhau cho danh sách không số; hai giá trị được so sánh là vị trí của đối tượng trong hai danh sách.
Peter Webb

Tôi là một người đơn giản. Tôi thậm chí không biết tỷ lệ tương quan là gì. Khi tôi đọc bài viết Wikipedia đó, ngay trên đầu trang, tôi được yêu cầu tìm hiểu "phân tán thống kê" là gì, sau đó là "độ lệch chuẩn", sau đó là "biến thể", sau đó là "hệ số tương quan giữa các lớp". Tôi đã học được tất cả những điều đó, nhiều lần và nhiều lần, tôi lại quên nó. Trong câu trả lời thực dụng này của tôi, tôi chỉ đơn giản là đo khoảng cách giữa hai vectơ với định lý Pythagoras, mà tôi nhớ từ thời tiểu học, đó là tất cả.
Boris Stitnicky

1

Tôi không chắc chắn về phương pháp "tốt nhất", nhưng một phương pháp đơn giản sẽ là so sánh mọi phần tử với phần tử sau nó, tăng bộ đếm nếu phần tử 2> phần tử 1 (hoặc bất cứ điều gì bạn muốn kiểm tra) và sau đó chia cho tổng số của các yếu tố. Nó sẽ cung cấp cho bạn một tỷ lệ phần trăm.


1

Tôi sẽ đếm các so sánh và chia nó cho tổng số so sánh. Đây là một ví dụ Python đơn giản .

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

Còn những thứ như thế này thì sao?

#!/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
Điều này chỉ tính nghịch đảo liền kề. Nếu bạn nhìn vào các câu trả lời khác, bạn sẽ thấy rằng điều này là không đủ.
Konrad Rudolph

1
@KonradRudolph: Tôi nghĩ câu trả lời này thỏa mãn câu hỏi khi được hỏi. Thực tế là các câu trả lời khác toàn diện hơn không có nghĩa là câu trả lời này là không đủ; nó phụ thuộc vào yêu cầu của OP.
LarsH

0

Nếu bạn đưa danh sách của bạn, tính toán hàng ngũ của các giá trị trong danh sách đó và gọi danh sách các cấp bậc Yvà danh sách khác, Xcó chứa các số nguyên từ 1đến length(Y), bạn có thể có được chính xác số đo sortedness mà bạn đang tìm kiếm bằng cách tính hệ số tương quan , rgiữa hai danh sách.

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

Đối với danh sách được sắp xếp đầy đủ r = 1.0, đối với danh sách được sắp xếp ngược r=-1.0và sự rkhác nhau giữa các giới hạn này đối với các mức độ sắp xếp khác nhau.

Một vấn đề có thể xảy ra với cách tiếp cận này, tùy thuộc vào ứng dụng, đó là việc tính thứ hạng của từng mục trong danh sách tương đương với việc sắp xếp nó, do đó, đây là thao tác O (n log n).


Nhưng điều đó sẽ không bỏ qua hình dạng đường cong. Nếu mảng của anh ta được sắp xếp, nhưng, giả sử, chứa các giá trị tăng theo cấp số nhân, thì mối tương quan sẽ nhỏ khi anh ta muốn nó là 1.0.
Lee Daniel Crocker

@LeeDanielCrocker: Vâng, đó là một điểm tốt. Tôi đã sửa đổi câu trả lời của mình để giải quyết vấn đề này bằng cách xếp hạng các giá trị.
Simon
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.