editor: Optimize selection overlap checking with binary search (#39773)
Replace O(n²) linear search with O(log n) binary search for checking selection overlaps when finding next selection range. Pre-sort selection ranges and use binary search to significantly improve performance when working with many selections. Release Notes: - N/A --------- Signed-off-by: Xiaobo Liu <cppcoffee@gmail.com>
This commit is contained in:
@@ -14448,6 +14448,10 @@ impl Editor {
|
||||
let last_selection = selections.iter().max_by_key(|s| s.id).unwrap();
|
||||
let mut next_selected_range = None;
|
||||
|
||||
// Collect and sort selection ranges for efficient overlap checking
|
||||
let mut selection_ranges: Vec<_> = selections.iter().map(|s| s.range()).collect();
|
||||
selection_ranges.sort_by_key(|r| r.start);
|
||||
|
||||
let bytes_after_last_selection =
|
||||
buffer.bytes_in_range(last_selection.end..buffer.len());
|
||||
let bytes_before_first_selection = buffer.bytes_in_range(0..first_selection.start);
|
||||
@@ -14469,11 +14473,20 @@ impl Editor {
|
||||
|| (!buffer.is_inside_word(offset_range.start, None)
|
||||
&& !buffer.is_inside_word(offset_range.end, None))
|
||||
{
|
||||
// TODO: This is n^2, because we might check all the selections
|
||||
if !selections
|
||||
.iter()
|
||||
.any(|selection| selection.range().overlaps(&offset_range))
|
||||
{
|
||||
// Use binary search to check for overlap (O(log n))
|
||||
let overlaps = selection_ranges
|
||||
.binary_search_by(|range| {
|
||||
if range.end <= offset_range.start {
|
||||
std::cmp::Ordering::Less
|
||||
} else if range.start >= offset_range.end {
|
||||
std::cmp::Ordering::Greater
|
||||
} else {
|
||||
std::cmp::Ordering::Equal
|
||||
}
|
||||
})
|
||||
.is_ok();
|
||||
|
||||
if !overlaps {
|
||||
next_selected_range = Some(offset_range);
|
||||
break;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user