CẬP NHẬT: Câu hỏi này là chủ đề trên blog của tôi vào ngày 8 tháng 6 năm 2012 . Cảm ơn vì câu hỏi tuyệt vời của bạn!
Câu hỏi tuyệt vời. Chúng tôi đã tranh luận về các vấn đề bạn nêu ra trong một thời gian dài.
Chúng tôi muốn có một cấu trúc dữ liệu có các đặc điểm sau:
- Bất biến.
- Các hình thức của một cái cây.
- Truy cập rẻ vào các nút cha từ các nút con.
- Có thể ánh xạ từ một nút trong cây sang một ký tự bù đắp trong văn bản.
- Kiên trì .
Tính bền bỉ, ý tôi là khả năng sử dụng lại hầu hết các nút hiện có trong cây khi chỉnh sửa được thực hiện đối với bộ đệm văn bản. Vì các nút là bất biến, không có rào cản nào đối với việc sử dụng lại chúng. Chúng tôi cần điều này cho hiệu suất; chúng tôi không thể phân tích cú pháp lại các wod rất lớn của tệp mỗi khi bạn nhấn một phím. Chúng tôi cần phải tái lex và chỉ phân tích cú pháp lại các phần của cây đã bị ảnh hưởng bởi chỉnh sửa.
Bây giờ khi bạn cố gắng đặt tất cả năm thứ đó vào một cấu trúc dữ liệu, bạn ngay lập tức gặp vấn đề:
- Làm thế nào để bạn xây dựng một nút ngay từ đầu? Cha mẹ và con đều tham chiếu lẫn nhau, và là bất biến, vậy cái nào được xây dựng trước?
- Giả sử bạn xoay sở để giải quyết vấn đề đó: bạn làm cách nào để khiến nó tồn tại lâu dài? Bạn không thể sử dụng lại một nút con trong một nút cha khác vì điều đó sẽ liên quan đến việc nói với nút con rằng nó có nút cha mới. Nhưng đứa trẻ là bất biến.
- Giả sử bạn có thể giải quyết vấn đề đó: khi bạn chèn một ký tự mới vào bộ đệm chỉnh sửa, vị trí tuyệt đối của mọi nút được ánh xạ tới một vị trí sau điểm đó sẽ thay đổi. Điều này gây khó khăn cho việc tạo cấu trúc dữ liệu liên tục, vì bất kỳ chỉnh sửa nào cũng có thể thay đổi nhịp của hầu hết các nút!
Nhưng trong đội Roslyn, chúng tôi thường xuyên làm những điều không thể. Chúng tôi thực sự làm điều không thể bằng cách giữ hai cây phân tích cú pháp. Cây "xanh" là bất biến, bền bỉ, không có tham chiếu cha, được xây dựng "từ dưới lên" và mọi nút đều theo dõi chiều rộng nhưng không phải vị trí tuyệt đối của nó . Khi một chỉnh sửa xảy ra, chúng tôi chỉ xây dựng lại các phần của cây xanh bị ảnh hưởng bởi chỉnh sửa, thường là khoảng O (log n) của tổng số nút phân tích cú pháp trong cây.
Cây "đỏ" là mặt tiền bất di bất dịch được xây dựng xung quanh cây xanh; nó được xây dựng "từ trên xuống" theo yêu cầu và được loại bỏ sau mỗi lần chỉnh sửa. Nó tính toán các tham chiếu gốc bằng cách sản xuất chúng theo yêu cầu khi bạn đi xuống cây từ trên cùng . Nó tạo ra các vị trí tuyệt đối bằng cách tính toán chúng từ độ rộng, một lần nữa, khi bạn đi xuống.
Bạn, người dùng, chỉ bao giờ nhìn thấy cây đỏ; cây xanh là một chi tiết thực hiện. Nếu bạn nhìn vào trạng thái bên trong của một nút phân tích cú pháp, trên thực tế, bạn sẽ thấy rằng có một tham chiếu đến một nút phân tích cú pháp khác trong đó thuộc loại khác; đó là nút cây xanh.
Ngẫu nhiên, chúng được gọi là "cây đỏ / xanh" bởi vì đó là những màu đánh dấu trên bảng trắng mà chúng tôi sử dụng để vẽ cấu trúc dữ liệu trong cuộc họp thiết kế. Không có ý nghĩa nào khác đối với màu sắc.
Lợi ích của chiến lược này là chúng tôi nhận được tất cả những điều tuyệt vời đó: tính bất biến, tính bền bỉ, tài liệu tham khảo dành cho cha mẹ, v.v. Cái giá phải trả là hệ thống này phức tạp và có thể tiêu tốn nhiều bộ nhớ nếu các mặt "đỏ" trở nên lớn. Hiện tại, chúng tôi đang thực hiện các thí nghiệm để xem liệu chúng tôi có thể giảm một số chi phí mà không làm mất đi lợi ích hay không.