Cấu trúc hiệu quả để biểu diễn một hệ thống phân cấp chuyển đổi


9

Bất cứ ai cũng có thể đề xuất một cách hiệu quả bộ nhớ để đại diện cho một cây ma trận, ví dụ như trong một mô hình phân cấp?

Tôi đặc biệt muốn bảo tồn địa phương dữ liệu và tôi nghi ngờ cách tiếp cận kiểu cấu trúc của mảng (ma trận & chỉ số cho ma trận) có thể phù hợp.

Cũng như nhiều tính toán ma trận được xâu chuỗi, cấu trúc này có thể sẽ được sao chép xung quanh trong bộ nhớ một chút công bằng, do đó, việc lưu trữ liền kề sẽ là một phần thưởng lớn.

Câu trả lời:


6

Cây như một mảng âm thanh như một chiến thắng với tôi. Chỉ cần thực hiện một giao dịch theo chiều sâu của hệ thống phân cấp của bạn và điền vào một mảng; khi tua lại qua đệ quy, bạn có thể cập nhật cha mẹ với chỉ số tuyệt đối cho con hoặc chỉ là delta-from-me, và con cái cũng có thể lưu trữ các chỉ số cha mẹ. Thật vậy, nếu bạn sử dụng offset tương đối thì bạn không cần phải mang theo địa chỉ gốc. Tôi cho rằng cấu trúc có thể sẽ trông giống như

struct Transform
{
   Matrix m; // whatever you like
   int parent;   // index or offset, you choose!
   int sibling;
   int firstchild;
};

... vì vậy bạn cũng cần các nút để biết cách đến với anh chị em vì bạn không thể (dễ dàng) có cấu trúc kích thước thay đổi. Mặc dù tôi đoán rằng nếu bạn đã sử dụng offset byte thay vì offset offset, bạn có thể có số lượng con thay đổi trên mỗi biến đổi:

struct Transform
{
   Matrix m; // whatever you like
   int parent;  // negative byte offest
   int numchildren;
   int child[0]; // can't remember if you put a 0 there or leave it empty;
                 // but it's an array of positive byte offsets
};

... Sau đó, bạn chỉ cần đảm bảo rằng bạn đặt Biến đổi liên tiếp vào đúng chỗ.

Đây là cách bạn xây dựng một cây hoàn toàn khép kín với "con trỏ" được nhúng.

int BuildTransforms(Entity* e, OutputStream& os, int parentLocation)
{
    int currentLocation = os.Tell();

    os.Write(e->localMatrix);
    os.Write(parentLocation);
    int numChildren = e->GetNumChildren();
    os.Write(numChildren);

    int childArray = os.Tell();
    os.Skip(numChildren * sizeof(int));
    os.AlignAsNecessary();  // if you need to align transforms

    childLocation = os.Tell();
    for (int i = 0; i < numChildren; ++i) {
        os.Seek(childArray + (i * sizeof(int)));
        os.Write(childLocation);
        os.Seek(childLocation);
        childLocation = BuildTransforms(e->GetChild(i), os, currentLocation);
    }

    return os.Tell();
}

void BuildTransforms(Entity* root)
{
    OutputStream os;
    BuildTransforms(root, os, -1, 0);
}

(Nếu bạn muốn lưu trữ các vị trí tương đối, chỉ cần thêm - currentLocationvào hai "vị trí" ghi.)


Nếu chúng ta đang nói về C ++, bạn sẽ cần chỉ định kích thước cho mảng con của mình hoặc tạo nó trong thời gian chạy với cấp phát bộ nhớ.
tenpn

Cách chính thức được C99 phê duyệt là để trống đặc tả kích thước mảng.

@ tenpn- ý tưởng là bạn có một bộ đệm được xây dựng có mục đích. Toàn bộ quan điểm là để tránh phân bổ thêm; bạn không thể chỉ định kích thước mảng vì bạn không biết nó sẽ lớn như thế nào. Sau khi bạn viết num con, bạn viết vào mảng con của bạn, nhưng sau đó Biến đổi tiếp theo bắt đầu sau khi mảng con kết thúc. (Đây là lý do tại sao bạn cần phải sử dụng offsets byte và không chỉ số cho cấu trúc này, bạn không biết làm thế nào lớn mỗi mục, nhưng nó vẫn còn hiệu quả để đi qua và là khép kín để nó có thể di chuyển như một đơn vị.)
dấu gạch ngang -tom-bang

1
Điều này được gọi là "cấu trúc hack." Xem thêm: notifyit.com/guides/content.aspx?g=cplusplus&seqNum=288
Neverender

1
@tenpn Aka cấu trúc chiều dài thay đổi. Được sử dụng một cách thích hợp, họ có thể giảm một nửa số lượng phân bổ heap.

1

Lập chỉ mục vào mảng ma trận có lẽ sẽ là cách tiếp cận hiệu quả nhất về bộ nhớ.

Một chuỗi các phép biến đổi có thể được tổ chức trong LIFO dưới dạng một loạt các con trỏ hoặc số nguyên hoặc cấu trúc nhỏ khác chỉ mục vào mảng ma trận. Điều này sẽ giúp ngăn lưu trữ ma trận dự phòng và sẽ tách mã lưu trữ dữ liệu khỏi mã truy cập dữ liệu.

Cuối cùng, bạn chỉ cần đẩy và bật các giá trị chỉ mục từ LIFO để lưu trữ hoặc phát lại chuỗi biến đổi của bạn.

Bạn cũng có thể lưu một ít bộ nhớ nếu cấu trúc ma trận của bạn cũng có thể chứa loại biến đổi ... xoay, dịch, v.v. Nếu không, loại sẽ cần được lưu trữ với chỉ mục dẫn đến khả năng trùng lặp nhiều hơn.

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.