509 lines
14 KiB
Rust
509 lines
14 KiB
Rust
use std::borrow::Borrow;
|
|
use std::cmp::Ordering;
|
|
use std::iter::FromIterator;
|
|
use std::mem;
|
|
use std::ops::{RangeBounds, Bound, Index, IndexMut};
|
|
|
|
/// `SortedMap` is a data structure with similar characteristics as BTreeMap but
|
|
/// slightly different trade-offs: lookup, insertion, and removal are O(log(N))
|
|
/// and elements can be iterated in order cheaply.
|
|
///
|
|
/// `SortedMap` can be faster than a `BTreeMap` for small sizes (<50) since it
|
|
/// stores data in a more compact way. It also supports accessing contiguous
|
|
/// ranges of elements as a slice, and slices of already sorted elements can be
|
|
/// inserted efficiently.
|
|
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default, Debug, RustcEncodable,
|
|
RustcDecodable)]
|
|
pub struct SortedMap<K: Ord, V> {
|
|
data: Vec<(K, V)>
|
|
}
|
|
|
|
impl<K: Ord, V> SortedMap<K, V> {
|
|
#[inline]
|
|
pub fn new() -> SortedMap<K, V> {
|
|
SortedMap {
|
|
data: vec![]
|
|
}
|
|
}
|
|
|
|
/// Construct a `SortedMap` from a presorted set of elements. This is faster
|
|
/// than creating an empty map and then inserting the elements individually.
|
|
///
|
|
/// It is up to the caller to make sure that the elements are sorted by key
|
|
/// and that there are no duplicates.
|
|
#[inline]
|
|
pub fn from_presorted_elements(elements: Vec<(K, V)>) -> SortedMap<K, V>
|
|
{
|
|
debug_assert!(elements.windows(2).all(|w| w[0].0 < w[1].0));
|
|
|
|
SortedMap {
|
|
data: elements
|
|
}
|
|
}
|
|
|
|
#[inline]
|
|
pub fn insert(&mut self, key: K, mut value: V) -> Option<V> {
|
|
match self.lookup_index_for(&key) {
|
|
Ok(index) => {
|
|
let slot = unsafe {
|
|
self.data.get_unchecked_mut(index)
|
|
};
|
|
mem::swap(&mut slot.1, &mut value);
|
|
Some(value)
|
|
}
|
|
Err(index) => {
|
|
self.data.insert(index, (key, value));
|
|
None
|
|
}
|
|
}
|
|
}
|
|
|
|
#[inline]
|
|
pub fn remove(&mut self, key: &K) -> Option<V> {
|
|
match self.lookup_index_for(key) {
|
|
Ok(index) => {
|
|
Some(self.data.remove(index).1)
|
|
}
|
|
Err(_) => {
|
|
None
|
|
}
|
|
}
|
|
}
|
|
|
|
#[inline]
|
|
pub fn get<Q>(&self, key: &Q) -> Option<&V>
|
|
where K: Borrow<Q>,
|
|
Q: Ord + ?Sized
|
|
{
|
|
match self.lookup_index_for(key) {
|
|
Ok(index) => {
|
|
unsafe {
|
|
Some(&self.data.get_unchecked(index).1)
|
|
}
|
|
}
|
|
Err(_) => {
|
|
None
|
|
}
|
|
}
|
|
}
|
|
|
|
#[inline]
|
|
pub fn get_mut<Q>(&mut self, key: &Q) -> Option<&mut V>
|
|
where K: Borrow<Q>,
|
|
Q: Ord + ?Sized
|
|
{
|
|
match self.lookup_index_for(key) {
|
|
Ok(index) => {
|
|
unsafe {
|
|
Some(&mut self.data.get_unchecked_mut(index).1)
|
|
}
|
|
}
|
|
Err(_) => {
|
|
None
|
|
}
|
|
}
|
|
}
|
|
|
|
#[inline]
|
|
pub fn clear(&mut self) {
|
|
self.data.clear();
|
|
}
|
|
|
|
/// Iterate over elements, sorted by key
|
|
#[inline]
|
|
pub fn iter(&self) -> ::std::slice::Iter<'_, (K, V)> {
|
|
self.data.iter()
|
|
}
|
|
|
|
/// Iterate over the keys, sorted
|
|
#[inline]
|
|
pub fn keys(&self) -> impl Iterator<Item = &K> + ExactSizeIterator {
|
|
self.data.iter().map(|&(ref k, _)| k)
|
|
}
|
|
|
|
/// Iterate over values, sorted by key
|
|
#[inline]
|
|
pub fn values(&self) -> impl Iterator<Item = &V> + ExactSizeIterator {
|
|
self.data.iter().map(|&(_, ref v)| v)
|
|
}
|
|
|
|
#[inline]
|
|
pub fn len(&self) -> usize {
|
|
self.data.len()
|
|
}
|
|
|
|
#[inline]
|
|
pub fn is_empty(&self) -> bool {
|
|
self.len() == 0
|
|
}
|
|
|
|
#[inline]
|
|
pub fn range<R>(&self, range: R) -> &[(K, V)]
|
|
where R: RangeBounds<K>
|
|
{
|
|
let (start, end) = self.range_slice_indices(range);
|
|
(&self.data[start .. end])
|
|
}
|
|
|
|
#[inline]
|
|
pub fn remove_range<R>(&mut self, range: R)
|
|
where R: RangeBounds<K>
|
|
{
|
|
let (start, end) = self.range_slice_indices(range);
|
|
self.data.splice(start .. end, ::std::iter::empty());
|
|
}
|
|
|
|
/// Mutate all keys with the given function `f`. This mutation must not
|
|
/// change the sort-order of keys.
|
|
#[inline]
|
|
pub fn offset_keys<F>(&mut self, f: F)
|
|
where F: Fn(&mut K)
|
|
{
|
|
self.data.iter_mut().map(|&mut (ref mut k, _)| k).for_each(f);
|
|
}
|
|
|
|
/// Inserts a presorted range of elements into the map. If the range can be
|
|
/// inserted as a whole in between to existing elements of the map, this
|
|
/// will be faster than inserting the elements individually.
|
|
///
|
|
/// It is up to the caller to make sure that the elements are sorted by key
|
|
/// and that there are no duplicates.
|
|
#[inline]
|
|
pub fn insert_presorted(&mut self, mut elements: Vec<(K, V)>) {
|
|
if elements.is_empty() {
|
|
return
|
|
}
|
|
|
|
debug_assert!(elements.windows(2).all(|w| w[0].0 < w[1].0));
|
|
|
|
let start_index = self.lookup_index_for(&elements[0].0);
|
|
|
|
let drain = match start_index {
|
|
Ok(index) => {
|
|
let mut drain = elements.drain(..);
|
|
self.data[index] = drain.next().unwrap();
|
|
drain
|
|
}
|
|
Err(index) => {
|
|
if index == self.data.len() ||
|
|
elements.last().unwrap().0 < self.data[index].0 {
|
|
// We can copy the whole range without having to mix with
|
|
// existing elements.
|
|
self.data.splice(index .. index, elements.drain(..));
|
|
return
|
|
}
|
|
|
|
let mut drain = elements.drain(..);
|
|
self.data.insert(index, drain.next().unwrap());
|
|
drain
|
|
}
|
|
};
|
|
|
|
// Insert the rest
|
|
for (k, v) in drain {
|
|
self.insert(k, v);
|
|
}
|
|
}
|
|
|
|
/// Looks up the key in `self.data` via `slice::binary_search()`.
|
|
#[inline(always)]
|
|
fn lookup_index_for<Q>(&self, key: &Q) -> Result<usize, usize>
|
|
where K: Borrow<Q>,
|
|
Q: Ord + ?Sized
|
|
{
|
|
self.data.binary_search_by(|&(ref x, _)| x.borrow().cmp(key))
|
|
}
|
|
|
|
#[inline]
|
|
fn range_slice_indices<R>(&self, range: R) -> (usize, usize)
|
|
where R: RangeBounds<K>
|
|
{
|
|
let start = match range.start_bound() {
|
|
Bound::Included(ref k) => {
|
|
match self.lookup_index_for(k) {
|
|
Ok(index) | Err(index) => index
|
|
}
|
|
}
|
|
Bound::Excluded(ref k) => {
|
|
match self.lookup_index_for(k) {
|
|
Ok(index) => index + 1,
|
|
Err(index) => index,
|
|
}
|
|
}
|
|
Bound::Unbounded => 0,
|
|
};
|
|
|
|
let end = match range.end_bound() {
|
|
Bound::Included(ref k) => {
|
|
match self.lookup_index_for(k) {
|
|
Ok(index) => index + 1,
|
|
Err(index) => index,
|
|
}
|
|
}
|
|
Bound::Excluded(ref k) => {
|
|
match self.lookup_index_for(k) {
|
|
Ok(index) | Err(index) => index,
|
|
}
|
|
}
|
|
Bound::Unbounded => self.data.len(),
|
|
};
|
|
|
|
(start, end)
|
|
}
|
|
|
|
#[inline]
|
|
pub fn contains_key<Q>(&self, key: &Q) -> bool
|
|
where K: Borrow<Q>,
|
|
Q: Ord + ?Sized
|
|
{
|
|
self.get(key).is_some()
|
|
}
|
|
}
|
|
|
|
impl<K: Ord, V> IntoIterator for SortedMap<K, V> {
|
|
type Item = (K, V);
|
|
type IntoIter = ::std::vec::IntoIter<(K, V)>;
|
|
|
|
fn into_iter(self) -> Self::IntoIter {
|
|
self.data.into_iter()
|
|
}
|
|
}
|
|
|
|
impl<'a, K, Q, V> Index<&'a Q> for SortedMap<K, V>
|
|
where K: Ord + Borrow<Q>,
|
|
Q: Ord + ?Sized
|
|
{
|
|
type Output = V;
|
|
|
|
fn index(&self, key: &Q) -> &Self::Output {
|
|
self.get(key).expect("no entry found for key")
|
|
}
|
|
}
|
|
|
|
impl<'a, K, Q, V> IndexMut<&'a Q> for SortedMap<K, V>
|
|
where K: Ord + Borrow<Q>,
|
|
Q: Ord + ?Sized
|
|
{
|
|
fn index_mut(&mut self, key: &Q) -> &mut Self::Output {
|
|
self.get_mut(key).expect("no entry found for key")
|
|
}
|
|
}
|
|
|
|
impl<K: Ord, V> FromIterator<(K, V)> for SortedMap<K, V> {
|
|
fn from_iter<T: IntoIterator<Item = (K, V)>>(iter: T) -> Self {
|
|
let mut data: Vec<(K, V)> = iter.into_iter().collect();
|
|
|
|
data.sort_unstable_by(|&(ref k1, _), &(ref k2, _)| k1.cmp(k2));
|
|
data.dedup_by(|&mut (ref k1, _), &mut (ref k2, _)| {
|
|
k1.cmp(k2) == Ordering::Equal
|
|
});
|
|
|
|
SortedMap {
|
|
data
|
|
}
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::SortedMap;
|
|
|
|
#[test]
|
|
fn test_insert_and_iter() {
|
|
let mut map = SortedMap::new();
|
|
let mut expected = Vec::new();
|
|
|
|
for x in 0 .. 100 {
|
|
assert_eq!(map.iter().cloned().collect::<Vec<_>>(), expected);
|
|
|
|
let x = 1000 - x * 2;
|
|
map.insert(x, x);
|
|
expected.insert(0, (x, x));
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn test_get_and_index() {
|
|
let mut map = SortedMap::new();
|
|
let mut expected = Vec::new();
|
|
|
|
for x in 0 .. 100 {
|
|
let x = 1000 - x;
|
|
if x & 1 == 0 {
|
|
map.insert(x, x);
|
|
}
|
|
expected.push(x);
|
|
}
|
|
|
|
for mut x in expected {
|
|
if x & 1 == 0 {
|
|
assert_eq!(map.get(&x), Some(&x));
|
|
assert_eq!(map.get_mut(&x), Some(&mut x));
|
|
assert_eq!(map[&x], x);
|
|
assert_eq!(&mut map[&x], &mut x);
|
|
} else {
|
|
assert_eq!(map.get(&x), None);
|
|
assert_eq!(map.get_mut(&x), None);
|
|
}
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn test_range() {
|
|
let mut map = SortedMap::new();
|
|
map.insert(1, 1);
|
|
map.insert(3, 3);
|
|
map.insert(6, 6);
|
|
map.insert(9, 9);
|
|
|
|
let keys = |s: &[(_, _)]| {
|
|
s.into_iter().map(|e| e.0).collect::<Vec<u32>>()
|
|
};
|
|
|
|
for start in 0 .. 11 {
|
|
for end in 0 .. 11 {
|
|
if end < start {
|
|
continue
|
|
}
|
|
|
|
let mut expected = vec![1, 3, 6, 9];
|
|
expected.retain(|&x| x >= start && x < end);
|
|
|
|
assert_eq!(keys(map.range(start..end)), expected, "range = {}..{}", start, end);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
#[test]
|
|
fn test_offset_keys() {
|
|
let mut map = SortedMap::new();
|
|
map.insert(1, 1);
|
|
map.insert(3, 3);
|
|
map.insert(6, 6);
|
|
|
|
map.offset_keys(|k| *k += 1);
|
|
|
|
let mut expected = SortedMap::new();
|
|
expected.insert(2, 1);
|
|
expected.insert(4, 3);
|
|
expected.insert(7, 6);
|
|
|
|
assert_eq!(map, expected);
|
|
}
|
|
|
|
fn keys(s: SortedMap<u32, u32>) -> Vec<u32> {
|
|
s.into_iter().map(|(k, _)| k).collect::<Vec<u32>>()
|
|
}
|
|
|
|
fn elements(s: SortedMap<u32, u32>) -> Vec<(u32, u32)> {
|
|
s.into_iter().collect::<Vec<(u32, u32)>>()
|
|
}
|
|
|
|
#[test]
|
|
fn test_remove_range() {
|
|
let mut map = SortedMap::new();
|
|
map.insert(1, 1);
|
|
map.insert(3, 3);
|
|
map.insert(6, 6);
|
|
map.insert(9, 9);
|
|
|
|
for start in 0 .. 11 {
|
|
for end in 0 .. 11 {
|
|
if end < start {
|
|
continue
|
|
}
|
|
|
|
let mut expected = vec![1, 3, 6, 9];
|
|
expected.retain(|&x| x < start || x >= end);
|
|
|
|
let mut map = map.clone();
|
|
map.remove_range(start .. end);
|
|
|
|
assert_eq!(keys(map), expected, "range = {}..{}", start, end);
|
|
}
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn test_remove() {
|
|
let mut map = SortedMap::new();
|
|
let mut expected = Vec::new();
|
|
|
|
for x in 0..10 {
|
|
map.insert(x, x);
|
|
expected.push((x, x));
|
|
}
|
|
|
|
for x in 0 .. 10 {
|
|
let mut map = map.clone();
|
|
let mut expected = expected.clone();
|
|
|
|
assert_eq!(map.remove(&x), Some(x));
|
|
expected.remove(x as usize);
|
|
|
|
assert_eq!(map.iter().cloned().collect::<Vec<_>>(), expected);
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn test_insert_presorted_non_overlapping() {
|
|
let mut map = SortedMap::new();
|
|
map.insert(2, 0);
|
|
map.insert(8, 0);
|
|
|
|
map.insert_presorted(vec![(3, 0), (7, 0)]);
|
|
|
|
let expected = vec![2, 3, 7, 8];
|
|
assert_eq!(keys(map), expected);
|
|
}
|
|
|
|
#[test]
|
|
fn test_insert_presorted_first_elem_equal() {
|
|
let mut map = SortedMap::new();
|
|
map.insert(2, 2);
|
|
map.insert(8, 8);
|
|
|
|
map.insert_presorted(vec![(2, 0), (7, 7)]);
|
|
|
|
let expected = vec![(2, 0), (7, 7), (8, 8)];
|
|
assert_eq!(elements(map), expected);
|
|
}
|
|
|
|
#[test]
|
|
fn test_insert_presorted_last_elem_equal() {
|
|
let mut map = SortedMap::new();
|
|
map.insert(2, 2);
|
|
map.insert(8, 8);
|
|
|
|
map.insert_presorted(vec![(3, 3), (8, 0)]);
|
|
|
|
let expected = vec![(2, 2), (3, 3), (8, 0)];
|
|
assert_eq!(elements(map), expected);
|
|
}
|
|
|
|
#[test]
|
|
fn test_insert_presorted_shuffle() {
|
|
let mut map = SortedMap::new();
|
|
map.insert(2, 2);
|
|
map.insert(7, 7);
|
|
|
|
map.insert_presorted(vec![(1, 1), (3, 3), (8, 8)]);
|
|
|
|
let expected = vec![(1, 1), (2, 2), (3, 3), (7, 7), (8, 8)];
|
|
assert_eq!(elements(map), expected);
|
|
}
|
|
|
|
#[test]
|
|
fn test_insert_presorted_at_end() {
|
|
let mut map = SortedMap::new();
|
|
map.insert(1, 1);
|
|
map.insert(2, 2);
|
|
|
|
map.insert_presorted(vec![(3, 3), (8, 8)]);
|
|
|
|
let expected = vec![(1, 1), (2, 2), (3, 3), (8, 8)];
|
|
assert_eq!(elements(map), expected);
|
|
}
|
|
}
|