2008-10-17 32 views
8

Tôi cần cấu trúc dữ liệu có thể lưu trữ các phạm vi không trùng lặp trong một thứ nguyên duy nhất. Toàn bộ phạm vi của kích thước không cần phải được bao phủ hoàn toàn.Cấu trúc dữ liệu cho các phạm vi không trùng lặp trong một kích thước duy nhất

Ví dụ sẽ là bộ lập lịch biểu phòng hội nghị. Kích thước là thời gian. Không có hai lịch biểu có thể trùng lặp. Phòng hội nghị không phải lúc nào cũng được lên lịch. Nói cách khác, trong một thời gian nhất định, có thể có tối đa một lịch biểu.

Giải pháp nhanh là phạm vi lưu trữ thời gian bắt đầu và kết thúc.

Range { 
    Date start 
    Date end 
} 

Điều này không được chuẩn hóa và yêu cầu thùng chứa thực thi không chồng chéo. Đối với hai phạm vi liền kề, kết thúc trước đó sẽ bị dư thừa với lần bắt đầu tiếp theo.

Một sơ đồ khác có thể bao gồm việc lưu trữ một giá trị biên với mỗi phạm vi. Nhưng đối với một chuỗi các dải ô liền nhau, sẽ luôn có thêm một giá trị ranh giới hơn các dải ô. Để làm được việc này các chuỗi có thể được biểu diễn dưới dạng xen kẽ các giá trị ranh giới và phạm vi:

B = ranh giới giá trị, r = phạm vi

BrBrB

Cấu trúc dữ liệu có thể trông giống như:

Boundary { 
    Date value 
    Range prev 
    Range next 
} 

Range { 
    Boundary start 
    Boundary end 
} 

Bản chất đó là danh sách được liên kết kép với các loại xen kẽ.

Cuối cùng, bất kỳ cấu trúc dữ liệu nào tôi sử dụng sẽ được thể hiện trong cả bộ nhớ (mã ứng dụng) và cơ sở dữ liệu quan hệ.

Tôi tò mò về những giải pháp học tập hoặc ngành đã cố gắng tồn tại.

Trả lời

1

được chuẩn hóa cách đại diện cho dữ liệu của bạn sẽ là lưu trữ bản ghi cho từng đơn vị thời gian. Điều này có thể được thực hiện trong ví dụ về ứng dụng lập kế hoạch hội nghị. Ràng buộc của bạn sẽ là một ràng buộc duy nhất cho

(RoomId, StartTime) 

Trong phạm vi liên tục, bạn nhất thiết phải lưu trữ 2 thứ, một ranh giới và ranh giới thứ hai hoặc chiều dài thứ hai. Nó thường được thực hiện bằng cách lưu trữ ranh giới thứ hai và sau đó tạo ra một hạn chế trên cả ranh giới của các loại

(boundary not between colBoudaryA and colBoundaryB) 

với các hạn chế bổ sung mà

(startBoundary < endBoundary) 
1

Một danh sách gấp đôi liên kết hoạt động tốt vì bạn chỉ sử dụng như nhiều bộ nhớ như bạn đã điền vào phạm vi, và bạn chỉ cần kiểm tra chồng chéo vào chèn - nó gần như tầm thường để làm như vậy tại thời điểm đó. Nếu có chồng chéo mục mới bị từ chối.

 
RoomID 
ReservationID 
PreviousReservationID 
NextReservationID 
StartTimeDate 
EndTimeDate 
Priority 
UserID 

Ưu tiên và UserID cho phép lịch trình để có những ưu tiên (giáo sư có thể có ảnh hưởng nhiều hơn một nhóm sinh viên) để mục mới có thể 'hạ gục' các mục ưu tiên thấp hơn ra khỏi con đường trong một cuộc chèn, và UserID cho phép một email được gửi đến các nhà tổ chức cuộc họp.

Bạn sẽ muốn xem xét thêm bảng trỏ đến cuộc họp đầu tiên mỗi ngày để tìm kiếm có thể được tối ưu hóa.

-Adam

0

Rất nhiều phụ thuộc vào những gì bạn sẽ làm với dữ liệu và do đó hoạt động nào cần hiệu quả. Tuy nhiên, tôi muốn xem xét một danh sách liên kết gấp đôi các Ranges với logic trong các setters Start và End để kiểm tra xem nó có chồng chéo các láng giềng của nó hay không và thu hẹp chúng nếu có (hoặc ném một ngoại lệ, hoặc bạn muốn xử lý một lần nữa) chồng lên nhau).

Điều đó cung cấp danh sách liên kết đơn giản được đặt sẵn để đọc, nhưng không có vùng chứa nào chịu trách nhiệm duy trì quy tắc không trùng lặp.

0

Đây được gọi là hạn chế "Unary Resource" trong thế giới Constraint Programming. Có rất nhiều nghiên cứu trong lĩnh vực này, đặc biệt đối với trường hợp khi thời gian sự kiện không được khắc phục và bạn cần tìm thời gian cho mỗi người trong số họ. Có một gói C++ thương mại có vấn đề của bạn và nhiều hơn nữa Ilog CP, nhưng có khả năng là quá mức cần thiết. Ngoài ra còn có một phiên bản phần mềm mã nguồn mở được gọi là eclipse (không liên quan đến IDE).

0

Điều này là không tầm thường vì (trong thế giới cơ sở dữ liệu) bạn phải so sánh nhiều hàng để xác định phạm vi không trùng lặp. Rõ ràng, khi thông tin nằm trong bộ nhớ, thì các biểu diễn khác như danh sách theo thứ tự thời gian là có thể. Tuy nhiên, tôi nghĩ rằng bạn nên sử dụng ký hiệu 'bắt đầu + kết thúc' của mình, ngay cả trong danh sách.

Có toàn bộ sách về chủ đề - một phần của xử lý 'Cơ sở dữ liệu tạm thời'. Hai bạn có thể xem là Darwen, Date và Lorentzos "Temporal Data and the Relational Model" và (ở cực kỳ khác cực kỳ) "Developing Time-Oriented Database Applications in SQL", Richard T. Snodgrass, Nhà xuất bản Morgan Kaufmann, Inc., San Francisco, tháng 7 năm 1999, trang 504 + xxiii, ISBN 1-55860-436-7. Đó là hết in nhưng có sẵn dưới dạng PDF trên trang web của mình tại cs.arizona.edu (do đó, tìm kiếm của Google giúp bạn dễ dàng tìm thấy).

Một trong những cấu trúc dữ liệu có liên quan là, tôi tin rằng, R-Tree. Điều đó thường được sử dụng cho các cấu trúc 2 chiều, nhưng cũng có thể có hiệu quả đối với các cấu trúc 1 chiều.

Bạn cũng có thể tìm kiếm "Allen's Relations" trong khoảng thời gian - chúng có thể hữu ích cho bạn.

0

Tôi đã lưu trữ thành công thời gian bắt đầu và thời lượng. Các thử nghiệm cho chồng chéo sẽ là một cái gì đó giống như

WHERE NOT EXISTS (
    SELECT 1 FROM table 
    WHERE BeginTime < NewBeginTime AND BeginTime + Duration > NewBeginTime 
) 
AND NOT EXISTS (
    SELECT 1 FROM table 
    WHERE NewBeginTime < BeginTime AND NewBeginTime + NewDuration > BeginTime 
) 

Tôi nghĩ nếu không thử nghiệm, nhưng hy vọng bạn sẽ có được trôi

1
  1. Đối với những khoảng thời gian không chồng chéo bạn chỉ có thể loại bạn khoảng thời gian với điểm khởi đầu. Khi bạn thêm một khoảng thời gian mới vào cấu trúc này, bạn chỉ có thể kiểm tra điểm bắt đầu và điểm kết thúc đó không thuộc về tập khoảng thời gian này. Để kiểm tra xem một số điểm X thuộc về khoảng thời gian đặt bạn có thể sử dụng tìm kiếm nhị phân để tìm điểm bắt đầu gần nhất và kiểm tra xem X có thuộc về khoảng thời gian của nó hay không. Cách tiếp cận này không quá tối ưu cho các hoạt động sửa đổi.

  2. Bạn có thể xem cấu trúc Interval tree - trong khoảng thời gian không chồng chéo, nó có truy vấn và sửa đổi hoạt động tối ưu.

1

Nếu bạn may mắn (!) đủ để sử dụng Postgres, bạn có thể sử dụng cột tstzrange và áp dụng ràng buộc để ngăn trùng lặp. Tiền thưởng của việc sử dụng một loại phạm vi là nó sẽ cố gắng ngăn chặn bắt đầu lớn hơn kết thúc.

ALTER TABLE "booking" 
ADD CONSTRAINT "overlapping_bookings" 
EXCLUDE USING gist ("period" WITH &&, "room" WITH =); 

Bạn có thể cần phải CREATE EXTENSION IF NOT EXISTS btree_gist, như tạo ra một ý chính sử dụng & & không được hỗ trợ mà không cần mở rộng đó.

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