2009-01-06 58 views

Trả lời

12

Làm thế nào về một số loại Knuth-Fisher-Yates shuffle algorithm?

for (int i = cards.Length - 1; i > 0; i--) 
{ 
    int n = rand.Next(i + 1); 
    Swap(ref cards[i], ref cards[n]); 
} 

Mã lấy từ Coding Horror. Đây cũng là một đề nghị đọc về cách mọi người thường làm điều này sai.

+0

Mã định dạng là mã Nhưng thuật toán tốt – recursive

+0

@recursive Cảm ơn, tôi định dạng lại mã. – Gant

1

Giải pháp yêu thích của tôi để xáo trộn nội dung là sử dụng N * log N sắp xếp và chuyển cho nó một biến vị ngữ sắp xếp trả về kết quả ngẫu nhiên. Nó có tính năng tốt đẹp có thể được thực hiện với tối thiểu mã mới bằng cách sử dụng các khối xây dựng mà hầu hết các ngôn ngữ có ích ngay cả trong các phiên bản sọc nhất.

+0

Trên Mặt khác, shuffle chỉ là O (n) và chỉ có khoảng 5 dòng mã, như được hiển thị trong các câu trả lời khác. (Và có thể được thực hiện chỉ một lần với generics rất dễ dàng.) –

+0

5 dòng đến 1 dòng hoặc là không nhiều (chỉ có 4 dòng) hoặc rất nhiều (80%). Nó cũng đơn giản hơn để nhớ. – BCS

+0

Và lợi thế khác là việc sắp xếp có thể tận dụng một cái gì đó để có được sự hoàn hảo tốt trên các giao dịch hoán đổi để nhỏ n nó có thể nhanh hơn. – BCS

2

Bạn có thể sử dụng thuật toán Fisher-Yates shuffle chạy trong thời gian tuyến tính.

+0

Tạo kết quả không chính xác - xem http://www.codinghorror.com/blog/archives/001015.html –

+0

@LFSR: đọc lại bài viết? – Jimmy

+0

Còn về Knuth? :( – configurator

2

Hãy để tôi hướng dẫn bạn đến một WRONG cách để làm việc đó, và là một cách tôi thú nhận tôi đã sử dụng trước đó, và không bao giờ nhìn thấy lỗi của nó cho đến khi bài đăng blog:

http://www.codinghorror.com/blog/archives/001015.html

+0

Điều đó cũng cho thấy cách * đúng * để làm điều đó :) –

0

tôi sẽ tạo một Danh sách mới và điền vào nó với các mục được chọn ngẫu nhiên và xóa khỏi Danh sách gốc.

6

Check-out này LINQ cách mát mẻ để làm việc đó:

public class Employee 
{ 
    public int Id 
    { 
     get; 
     set; 
    } 
    public string Name 
    { 
     get; 
     set; 
    } 
} 

cư một danh sách:

List<Employee> list = new List<Employee>(); 

    list.Add(new Employee { Id = 1, Name = "Davolio Nancy" }); 
    list.Add(new Employee { Id = 2, Name = "Fuller Andrew" }); 
    list.Add(new Employee { Id = 3, Name = "Leverling Janet" }); 
    list.Add(new Employee { Id = 4, Name = "Peacock Margaret" }); 
    list.Add(new Employee { Id = 5, Name = "Buchanan Steven" }); 
    list.Add(new Employee { Id = 6, Name = "Suyama Michael" }); 
    list.Add(new Employee { Id = 7, Name = "King Robert" }); 
    list.Add(new Employee { Id = 8, Name = "Callahan Laura" }); 
    list.Add(new Employee { Id = 9, Name = "Dodsworth Anne" }); 

Sau đó sắp xếp:

list = list.OrderBy(emp => Guid.NewGuid()).ToList(); 

Credit

+0

Không chính xác nhanh, nhưng friggen tuyệt vời. – Will

+0

Ai quan tâm đến hiệu suất khi bạn có thể roi ra thanh LINQ lớn của bạn và hiển thị những người khác bạn tốt hơn họ? :-P – BFree

+0

Chỉ cần nhớ rằng GUID's ** NOT ** được coi là số ngẫu nhiên cho mục đích mã hóa. Họ sẽ làm việc cho loại điều này, nhưng họ không thể hoán đổi cho nhau. –

0

Hãy thử điều này đồng de here

Nó sử dụng IComparer.Compare

Nó sẽ là một thực hành tốt nếu bạn làm như chức năng sử dụng generics

Các vấn đề liên quan