Có thể biểu diễn đột biến của đồ thị đối tượng một cách hiệu quả với các trạng thái bất biến?


12

Tôi đang thực hành sử dụng đối tượng bất biến trong C ++. Mục tiêu cá nhân của tôi là đại diện cho biểu đồ đối tượng chung (trong heap) với chuỗi các biểu đồ bất biến.

Xây dựng đồ thị đa phiên bản không khó lắm. Vấn đề là hiệu suất. Phiên bản Brute-force cần bản sao đầy đủ của biểu đồ và điều này không được chấp nhận.

Tôi đã cố gắng để chia sẻ các nút không thay đổi. Nhưng trong trường hợp này, tôi gặp một vấn đề mới; người giới thiệu. Tham chiếu đến đối tượng khác phải được cập nhật trong toàn bộ biểu đồ. Điều này cần truy cập vào tất cả các nút cho mỗi lần tôi lấy được một phiên bản đồ thị mới. Và điều này làm thay đổi các nút với các tham chiếu, vì vậy chúng cũng nên được dẫn xuất (bằng cách sao chép). Hiệu suất sẽ không tốt hơn nhiều so với sao chép vũ phu.

Theo như tôi có thể tưởng tượng, không có cách nào thực sự hiệu quả để biểu diễn sự đột biến của đồ thị đối tượng với các trạng thái bất biến. Vì vậy, tôi đang yêu cầu một số ý tưởng về điều này.

Có thể biểu diễn đột biến của đồ thị đối tượng một cách hiệu quả với trạng thái bất biến?


1
Điều đó chỉ khó khăn vì bạn đang đặt các cạnh trên các nút. Nếu bạn lưu trữ các cạnh bên ngoài, trong một bộ sưu tập bất biến, nó sẽ dễ dàng.
dan_waterworth

@dan_waterworth Nếu tôi sử dụng danh sách kề, tôi phải tìm kiếm từng cạnh cho mỗi lần. Vì vậy, tôi nghĩ rằng đó là sự đánh đổi giữa hiệu suất đọc và viết.
Eonil

1
Nó không phải là một danh sách.
dan_waterworth

@dan_waterworth Ý bạn là gì đó giống như cây B?
Eonil

2
cây rộng như cây B có xu hướng được sử dụng khi độ trễ cho phương tiện lưu trữ cao. Trong trường hợp này, bạn có thể tốt hơn với một cái gì đó hẹp hơn, nhưng vâng, một loại cây tìm kiếm cân bằng nào đó sẽ là một ý tưởng tốt.
dan_waterworth

Câu trả lời:


11

Những gì bạn đang tìm kiếm được gọi là Cấu trúc dữ liệu liên tục . Tài nguyên chính cho các cấu trúc dữ liệu liên tục là Sách cấu trúc dữ liệu chức năng thuần túy của Chris Okasaki . Các cấu trúc dữ liệu liên tục đã thu hút sự quan tâm trong thời gian gần đây do sự phổ biến của chúng trong Clojure và Scala.

Tuy nhiên, vì một số lý do kỳ lạ, Đồ thị liên tục dường như bị bỏ qua. Chúng tôi có danh sách, hàng chục loại cây, mảng, hàng đợi ưu tiên, bản đồ, nhưng không có biểu đồ.

Tôi thực sự chỉ tìm thấy một bài báo: Đồ thị hoàn toàn bền bỉ - Chọn cái nào?


4

Nếu bạn không coi các kết nối giữa các đối tượng là một phần của tài nguyên được phiên bản của mình (và bạn có thể - trong trường hợp sau đây có thể không giúp được gì nhiều), bạn có thể xem xét chia các đối tượng của mình thành một phần đại diện cho phần kết nối của đối tượng và một phần đại diện cho trạng thái bất biến.

Sau đó, bạn có thể có mỗi đối tượng con kết nối chứa một vectơ của các trạng thái được phiên bản. Bằng cách này, bạn có thể vận hành với số phiên bản biểu đồ để truy cập trạng thái bất biến thích hợp.

Để tránh phải duyệt qua toàn bộ biểu đồ bất cứ khi nào có cập nhật cho một nút cụ thể, bạn có thể làm cho nó để nếu một nút được truy cập với số phiên bản lớn hơn số phiên bản hiện tại của nút, phiên bản hiện tại được sử dụng . Nếu sau đó nút được cập nhật, bạn điền vào tất cả các phiên bản trung gian với phiên bản trước - do đó cho phép bạn thực hiện cập nhật lười biếng vào biểu đồ đối tượng.

Nếu kết nối giữa các đối tượng là một phần của trạng thái phiên bản của bạn, thì những điều đã nói ở trên không hoạt động. Nhưng có lẽ bạn có thể mở rộng nó như sau:

Đối với mỗi đối tượng trong biểu đồ, tạo một "đối tượng xử lý". Đối tượng xử lý chứa danh sách các trạng thái bất biến được phiên bản. Thay vì lưu trữ các tham chiếu đối tượng trong bất kỳ đối tượng nào của biểu đồ, bạn sẽ lưu trữ một tham chiếu đến đối tượng xử lý. Sau đó, mỗi tham chiếu đến các đối tượng sẽ được xác định lại thông qua tay cầm bằng cách sử dụng tay cầm và số phiên bản của chế độ xem biểu đồ đối tượng hiện đang được xử lý. Điều này sẽ trả về trạng thái bất biến chính xác cho đối tượng. Các trạng thái bất biến sử dụng tay cầm để tham chiếu đến các đối tượng khác trong biểu đồ, vì vậy bạn luôn có được ngày nhất quán cho phiên bản của biểu đồ bạn muốn xử lý.

Logic tương tự được mô tả ở trên áp dụng cho việc cập nhật các phiên bản trong tay cầm - cho phép cập nhật lười biếng, cục bộ.


3

Có một giải pháp được công bố cho vấn đề này với độ phức tạp thời gian khấu hao rất tốt, nhưng thật khó để tìm ra khi bạn không biết chính xác những gì cần tìm. Bạn có thể tìm thấy một bản tóm tắt hay trong các ghi chú bài giảng này (kiểm tra phần 2.2.3) hoặc đọc bài báo gốc Tạo cấu trúc dữ liệu liên tục . Nếu biểu đồ đối tượng của bạn có kết nối hạn chế (ví dụ: các cấu trúc giống như cây), bạn thậm chí có thể đạt được độ phức tạp O (1) được khấu hao cho cả việc đọc và cập nhật biểu đồ bất biến, rất ấn tượng.

Ý tưởng là mỗi đối tượng, ngoài việc lưu trữ trạng thái bất biến hiện tại, còn có không gian để ghi lại các thay đổi. Khi bạn muốn tạo một biểu đồ bất biến mới từ một biểu đồ hiện có bằng cách áp dụng các thay đổi, bạn phải xem xét hai trường hợp:

  • Đối tượng bạn muốn thay đổi vẫn còn chỗ để thay đổi. Bạn có thể lưu trữ các thay đổi trực tiếp trong đối tượng.

  • Đối tượng không còn chỗ để thay đổi. Bạn tạo phiên bản mới dựa trên các giá trị hiện tại và các bản ghi thay đổi trống. Bây giờ bạn cần cập nhật đệ quy tất cả các đối tượng tham chiếu đối tượng cũ để tham chiếu đối tượng mới.

    Nếu bản thân đối tượng tham chiếu vẫn còn chỗ cho các thay đổi, bạn có thể lưu trữ thay đổi trong tham chiếu trực tiếp, nếu không, nó sẽ được xếp theo cách đệ quy.

Mặc dù lược đồ này hỗ trợ tạo hiệu quả các thế hệ đồ thị đối tượng bất biến mới, nhưng nó làm phức tạp việc đọc từ nó, bởi vì bây giờ bạn cần chỉ định "phiên bản" nào bạn muốn truy cập khi đọc dữ liệu từ một đối tượng không thay đổi. Điều này là do đối tượng không thay đổi có thể có thông tin cho nhiều phiên bản do các bản ghi thay đổi được lưu trữ, vì vậy bạn cần chỉ định phiên bản nào bạn muốn xem xét.

Khi thực hiện điều này, tôi cố gắng che giấu sự phức tạp này trong API. Khi tham chiếu một cái gì đó trong biểu đồ bất biến từ bên ngoài, tôi sử dụng các sơ khai được tạo thay vì tham chiếu trực tiếp, vì vậy người gọi không cần phải tiếp tục chuyển phiên bản mong muốn xung quanh theo cách thủ công. Điều này làm cho các tài liệu tham khảo đắt hơn một chút so với một con trỏ trực tiếp, nhưng tôi thấy nó có giá trị thuận tiệ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.