2011-12-19 4 views
5

Tôi đang tìm một phương pháp hiệu quả để chọn truy cập vào từng phần tử của std::vector<T> theo thứ tự ngẫu nhiên mà không cần thay đổi hoặc sao chép chúng. std::random_shuffle và đảm bảo rằng mỗi phần tử chỉ được chọn một lần.Phương pháp hiệu quả để chọn ngẫu nhiên tất cả các phần tử của std :: vectơ chính xác một lần KHÔNG thay đổi lại

Tôi không muốn sao chép hoặc cải tổ lại dưới dạng a) mỗi trường hợp T có thể là đối tượng rất lớn và b) cho các hoạt động khác mà tôi sẽ thực hiện trên các phần tử của vectơ. để giữ nguyên theo thứ tự.

Hơn nữa, tôi thực sự không muốn đi xuống con đường liên tục chọn và từ chối trùng lặp. Có thể tôi sẽ có rất nhiều đối tượng lớn được lưu trữ trong vector và hiệu quả là chìa khóa vì tôi sẽ tìm cách gọi phương thức chọn ngẫu nhiên này nhiều lần trong một giây.

+0

Bạn có thể triển khai phương thức hoán đổi cho loại của mình không? Nếu việc thực thi thư viện chuẩn sử dụng tra cứu phụ thuộc vào đối số để trao đổi (nó nên), thì bạn sẽ nhận được 'O (1)' trao đổi các phần tử trong vectơ. –

Trả lời

4

Bạn không cho chúng tôi biết bạn có muốn lặp lại toàn bộ mảng một cách ngẫu nhiên hay không. .

Tôi giả định trường hợp đầu tiên. Bạn sẽ cần thêm bộ nhớ để lưu giữ sổ sách và bạn sẽ cần thời gian tuyến tính để xáo trộn. Vì vậy, tạo ra một hoán vị, và giữ cho bộ nhớ của nó còn sống để bạn có thể cải tổ nó như bạn muốn. Với C++ 11:

#include <algorithm> 
#include <random> 
#include <numeric> 

struct permutation 
{ 
    permutation(size_t n) 
     : perm(n), g(std::random_device()) 
    { 
     std::iota(perm.begin(), perm.end(), size_t(0)); 
    } 

    void shuffle() { std::shuffle(perm.begin(), perm.end(), g); } 

    size_t operator[](size_t n) const { return perm[n]; } 

private: 
    std::vector<size_t> perm; 
    std::mt19937 g; 
}; 

Cách sử dụng:

std::vector<huge_t> v; 
... 

permutation sigma(v.size()); 
sigma.shuffle(); 

const huge_t& x = v[sigma[0]]; 

... 
sigma.shuffle(); // No extra allocation 
const huge_t& y = v[sigma[0]]; 

Bạn có thể thích ứng với mã để sử dụng C++ 03 std::random_shuffle, nhưng xin lưu ý rằng có rất ít bảo đảm trên bộ tạo số ngẫu nhiên.

+0

Thật không may tôi đang sử dụng VS2008, mà tôi tin rằng không hỗ trợ C++ 11 – oracle3001

+0

+1, câu trả lời của bạn mát hơn tôi :) –

+0

Lưu ý rằng 'std :: random_shuffle()' có một quá tải chấp nhận một trình tạo số ngẫu nhiên. Bạn có thể vượt qua trong một máy phát điện chất lượng cao hơn nếu bạn muốn. –

6

Tạo vectơ có cùng kích thước với hình ảnh hiện tại sử dụng con trỏ đến các phần tử trong vectơ. Thay ngẫu nhiên các vector con trỏ thay vào đó và đọc từ đó - đó là chi phí thấp.

2

Tôi nghĩ giải pháp dễ nhất (và một trong những giải pháp hiệu quả hơn) là tạo một chỉ số nắm giữ std::vector<size_t> vào số vector<T> hoặc std::vector<T*> giữ con trỏ của bạn vào vector. Sau đó, bạn có thể xáo trộn một cái bằng cách sử dụng std::random_shuffle, lặp lại qua nó và chọn các phần tử tương ứng từ vectơ gốc của bạn. Bằng cách đó bạn không thay đổi thứ tự của vectơ gốc của bạn và các con trỏ ngẫu nhiên hoặc size_t là khá rẻ

+0

Phương pháp std :: vector là cách tôi hiện đã triển khai, nhưng chỉ muốn kiểm tra xem có cách nào tốt hơn không. Đã trở lại mã hóa C++ sau một vài năm nghỉ ngơi. – oracle3001

+0

+1 Về cơ bản tương đương với cách tiếp cận của w00te, nhưng mối quan hệ với vector ban đầu rõ ràng hơn, vector ban đầu có thể được sửa đổi ở giữa và có thể hiệu quả hơn 50% bộ nhớ trên hệ thống LP64 nếu bạn quyết định rằng bạn lười biếng và sử dụng 'int' over' size_t'. – delnan

+0

Cảm ơn các bạn .... Phương pháp std :: vector là cách tôi hiện đang triển khai nó, nhưng chỉ muốn kiểm tra không có cách nào tốt hơn để làm điều này. Đã trở lại mã hóa C++ sau một vài năm nghỉ ngơi. Theo sau từ này .... Cho phép nói tiêu chuẩn :: vector ObjVector và std :: vector chỉ số là có thể sử dụng for_each (index.begin(), index.end(), someMethod) để đạt được sau đây ... someMethod trong someway kết thúc trong một cuộc gọi đến phương pháp Obj.method tức là for_each kết quả trong các cuộc gọi đến phương pháp trong mỗi trường hợp của đối tượng trong ObjVector theo một thứ tự ngẫu nhiên? – oracle3001