2009-07-11 23 views
35

Tôi có một std :: bản đồ mà tôi đang sử dụng để lưu trữ các giá trị cho x & y tọa độ. Dữ liệu của tôi rất thưa thớt, vì vậy tôi không muốn sử dụng mảng hoặc vectơ, điều này sẽ dẫn đến lãng phí bộ nhớ lớn. Dữ liệu của tôi dao động từ -250000 đến 250000 nhưng tôi sẽ chỉ có một vài nghìn điểm nhiều nhất.Cách tốt nhất để sử dụng hai khóa với std :: map là gì?

Hiện tại tôi đang tạo chuỗi std :: với hai tọa độ (nghĩa là "12x45") và sử dụng nó làm khóa. Điều này dường như không phải là cách tốt nhất để làm điều đó.

Suy nghĩ khác của tôi là sử dụng int64 và đẩy hai int32 vào đó và sử dụng nó làm khóa.

Hoặc sử dụng lớp học với hai tọa độ. Các yêu cầu trên một lớp được sử dụng làm khóa là gì?

Cách tốt nhất để làm điều này là gì? Tôi không muốn sử dụng bản đồ bản đồ.

+0

Bạn có thể dễ dàng và hợp pháp nhét hai chờ đợi vào một _int64, hoặc như trong câu trả lời của tôi dưới đây, một số sê-ri, PID, và nodeID. Vì MAX_PID là (1 << 22) trên Linux, điều này thực sự để lại 64 - (32 + 22) còn lại cho NodeId, là 10 bit, giữ bất kỳ giá trị nào lên tới (1 << 10) IE: 1024 – RocketRoy

+0

Giả sử bạn làm không muốn lặp lại bản đồ theo một số thứ tự cụ thể, sử dụng một bản đồ băm như std :: unordered_map. Hiệu quả hơn nhiều đặc biệt là khi bạn có nhiều giá trị. – hyde

Trả lời

96

Sử dụng std :: cặp < int32, int32> cho phím:

std::map<std::pair<int,int>, int> myMap; 

myMap[std::make_pair(10,20)] = 25; 
std::cout << myMap[std::make_pair(10,20)] << std::endl; 
+4

một cặp hoạt động nhưng là chung chung. Có thể là một ý tưởng hay để xác định loại tùy chỉnh thể hiện ý nghĩa của cặp thực sự, tọa độ Descartes hoặc bất kỳ thứ gì. – bames53

+2

@ bames53 Vấn đề chính với điều đó là bạn phải thực hiện toán tử so sánh cho kiểu mới, điều này có thể không có ý nghĩa nếu tất cả những gì bạn muốn đảm bảo là duy nhất. –

+0

Thậm chí không biết cho đến bây giờ rằng có quá tải của các toán tử so sánh cho std :: pair. – zett42

3

Boost có một thùng chứa đồ có sử dụng một hoặc nhiều chỉ số.

Multi Index Map

+0

Có thể đạt được bằng cách sử dụng các bộ dữ liệu tăng cường. – Frizi

25

tôi thường giải quyết các loại vấn đề như thế này:

struct Point 
{ 
    Point() : x(), y() {} 
    Point(int x, int y) : x(x), y(y) {} 
    int x, y; 
}; 

bool operator<(const Point & lhs, const Point & rhs) // lhs = left-hand side 
                 // rhs = right-hand side 
{ 
    if (lhs.x != rhs.x) 
    { 
     return lhs.x < rhs.x; 
    } 
    else 
    { 
     return lhs.y < rhs.y; 
    } 
} 

int main() 
{ 
    Point p1(0, 1); 
    Point p2(0, 2); 
    std::map<Point, std::string> mapping; 
    mapping[p1] = "p1"; 
    mapping.insert(std::make_pair(p2, "p2")); 
} 
+8

Điều này rõ ràng, điều này tốt. Chỉ cần lưu ý điều này giống với 'typedef std :: pair Point;' – GManNickG

+9

Heh, cho đến bây giờ tôi không biết rằng std :: pair có toán tử StackedCrooked

+2

@GManNickG ngoại trừ giao diện của 'x' và' y' là 'first' và' second' cho cặp 'std ::'. – rubenvb

5

các yêu cầu về một lớp học mà là để được sử dụng như chìa khóa là gì?

Bản đồ cần để có thể nói cho dù giá trị một chìa khóa là ít hơn giá trị của phím khác: theo mặc định này có nghĩa là (key1 < khóa2) phải là một biểu thức boolean hợp lệ, tức là loại chìa khóa nên thực hiện toán tử 'ít hơn'.

Mẫu bản đồ cũng triển khai một hàm tạo quá tải cho phép bạn truyền tham chiếu đến đối tượng hàm của loại key_compare, có thể thực hiện toán tử so sánh: để so sánh có thể được thực hiện như một phương thức của hàm ngoài này đối tượng, thay vì cần phải được nướng vào bất kỳ loại khóa nào của bạn.

+0

Yêu cầu khác là khóa phải là hằng số và không thể thay đổi – Emiliano

0

Sử dụng std :: pair. Tốt hơn là sử dụng QHash<QPair<int,int>,int> nếu bạn có nhiều ánh xạ như vậy.

0

Đầu tiên và trước hết, mương chuỗi và sử dụng 2 int, mà bạn có thể đã thực hiện ngay bây giờ. Kudos cho việc tìm ra rằng một cây là cách tốt nhất để thực hiện một ma trận thưa thớt. Thông thường một nam châm để thực hiện xấu có vẻ như.

FYI, khóa hợp chất ba cũng hoạt động và tôi cũng giả sử một cặp.

Nó làm cho một số kịch bản phụ xấu xí mặc dù, do đó, một chút ma thuật vĩ mô sẽ làm cho cuộc sống của bạn dễ dàng hơn. Tôi đã để lại một mục đích chung này, nhưng việc nhập các đối số trong macro là một ý tưởng hay nếu bạn tạo các macro cho các bản đồ cụ thể. TresKey12 được kiểm tra và chạy tốt. QuadKeys cũng sẽ hoạt động.

LƯU Ý: Miễn là các bộ phận quan trọng của bạn là các loại dữ liệu cơ bản, bạn KHÔNG cần phải viết gì thêm. AKA, không cần phải băn khoăn về các chức năng so sánh. STL có bạn bảo hiểm. Chỉ cần mã nó lên và để cho nó rip.

using namespace std; // save some typing 
#define DosKeys(x,y)  std::make_pair(std::make_pair(x,y)) 
#define TresKeys12(x,y,z) std::make_pair(x,std::make_pair(y,z)) 
#define TresKeys21(x,y,z) std::make_pair(std::make_pair(x,y),z)) 

#define QuadKeys(w,x,y,z) std::make_pair(std::make_pair(w,x),std::make_pair(y,z)) 


map<pair<INT, pair<ULLNG, ULLNG>>, pIC_MESSAGE> MapMe; 
MapMe[TresKey12(Part1, Part2, Part3)] = new fooObject; 

Nếu ai đó muốn gây ấn tượng với tôi, chỉ cho tôi làm thế nào để làm cho một nhà điều hành so sánh cho TresKeys mà không dựa vào cặp làm tổ để tôi có thể sử dụng một đơn struct với 3 thành viên và sử dụng một chức năng so sánh.

PS: TresKey12 đã cho tôi sự cố với bản đồ được khai báo là cặp, vì nó làm cho x, ghép nối và hai thứ đó không phát đẹp. Không phải là một vấn đề đối với DosKeys, hoặc QuadKeys. Nếu đó là một mùa hè nóng thứ sáu mặc dù, bạn có thể tìm thấy một tác dụng phụ bất ngờ của việc gõ vào DosEquis ... err .. DosKeys một loạt các lần, là một khát cho bia Mexico. Emptor caveat. Như Sheldon Cooper nói, "Cuộc sống không có gì hay thay đổi?"

+4

. xấu xí. Tại sao một macro cho những gì nên là một chức năng? Và đây là cách quá nhiều cặp lồng nhau. Để trả lời câu hỏi của bạn về cách giải quyết nó: 'struct location {int x, y, z; }; toán tử bool <(const location & lhs, const location & rhs) {return std :: tie (lhs.x, lhs.y, lhs.z) GManNickG

+2

@GManNickG, cảm ơn bạn đã trả lời. Sẽ cung cấp cho một thử và báo cáo lại. Phải, anh chàng này sẽ mỉm cười nếu điều này hoạt động! – user2548100

+0

@GManNickG, Điều này không hoàn toàn biên dịch. Tôi sẽ futz xung quanh với nó ở đây trong VS 2012 C++. Có lẽ làm cho nó hoạt động, nhưng nếu bạn có một phút để rảnh rỗi, có thể đăng một cái gì đó đang biên dịch? TVMIA – user2548100

1

Thao tác này sẽ thêm nhiều số nguyên vào một số nguyên lớn, trong trường hợp này là _int64. Nó so sánh như là một _int64, AKA dài (Khai báo kiểu xấu nhất bao giờ hết, ngắn ngắn ngắn, sẽ chỉ kém thanh lịch hơn một chút. 10 năm trước nó được gọi là vlong. Tốt hơn nhiều. Vì vậy, nhiều cho "tiến bộ"), vì vậy không so sánh chức năng là cần thiết.

#define ULNG unsigned long 
#define BYTE unsigned char 
#define LLNG long long 
#define ULLNG unsigned long long 

// -------------------------------------------------------------------------- 
ULLNG PackGUID(ULNG SN, ULNG PID, BYTE NodeId) { 
    ULLNG CompKey=0; 

    PID = (PID << 8) + NodeId; 
    CompKey = ((ULLNG)CallSN << 32) + PID; 

    return CompKey; 
} 

Sau khi cung cấp câu trả lời này, tôi nghi ngờ điều này sẽ làm việc cho bạn, như bạn cần hai phím riêng biệt và khác biệt để điều hướng với 2 kích thước, X và Y.

Mặt khác, nếu bạn đã có tọa độ XY, và chỉ muốn kết hợp một giá trị với khóa đó, thì điều này hoạt động một cách ngoạn mục, bởi vì so sánh _int64 mất cùng thời gian với bất kỳ số nguyên nào khác so sánh trên chip Intel X86 - 1 đồng hồ.

Trong trường hợp này, so sánh nhanh hơn 3 lần so với khóa tổng hợp này, so với khóa kết hợp ba.

Nếu sử dụng tính năng này để tạo bảng tính dân cư thưa thớt, tôi sẽ RX sử dụng 2 cây riêng biệt, một cây được lồng vào nhau. Đặt thứ nguyên Y là "sếp" và tìm kiếm không gian Y trước tiên để giải quyết trước khi tiếp tục đến thứ nguyên X. Bảng tính cao hơn chiều rộng và bạn luôn muốn thứ nguyên thứ nhất trong bất kỳ khóa ghép nào có số lượng giá trị duy nhất lớn nhất.

Sắp xếp này sẽ tạo bản đồ cho thứ nguyên Y sẽ có bản đồ cho thứ nguyên X làm dữ liệu của nó. Khi bạn đến một chiếc lá trong kích thước Y, bạn bắt đầu tìm kiếm kích thước X của nó cho cột trong bảng tính.

Nếu bạn muốn tạo một hệ thống bảng tính rất mạnh, hãy thêm thứ nguyên Z theo cùng một cách và sử dụng nó làm ví dụ, đơn vị tổ chức. Đây là cơ sở cho hệ thống kế toán/dự báo/ngân sách rất mạnh, một hệ thống cho phép các đơn vị quản trị có nhiều tài khoản chi tiết để theo dõi chi phí quản trị và không có các tài khoản đó chiếm không gian cho các đơn vị dòng có loại của riêng họ chi tiết để theo dõi.

+2

Tôi tin rằng nhồi nhét hai giây vào một _int64, với giá trị dài là Y, và dài là X, sẽ tìm kiếm Y không gian đầu tiên, và sau đó là không gian X, vì tất cả các giá trị có cùng giá trị cao (cùng giá trị Y) sẽ bằng nhau , để lại độ dài thấp (không gian X) để phá vỡ cà vạt. – user2548100

-1

Hy vọng bạn sẽ tìm thấy nó hữu ích:

map<int, map<int, int>> troyka = { {4, {{5,6}} } }; 
troyka[4][5] = 7; 
+0

OP nói rằng anh ta không muốn sử dụng bản đồ bản đồ, vì vậy câu trả lời này không có khả năng giúp đỡ. Ngoài ra, một số giải thích về mã có thể hữu ích cho những người khác hiểu giải pháp của bạn. Xin lỗi nếu tôi đang phàn nàn quá nhiều, nhưng bạn đã trả lời một câu hỏi rất cũ từ năm 2009 rằng đã có câu trả lời với nhiều upvotes. Vì vậy, rất khó có câu trả lời của bạn sẽ cung cấp một cái gì đó mới hoặc thậm chí tốt hơn so với câu trả lời được chấp nhận. – zett42

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