Skip to content

Commit

Permalink
Merge pull request #4682 from thestinger/treemap
Browse files Browse the repository at this point in the history
Set trait improvements + minor treemap cleanup
  • Loading branch information
catamorphism committed Jan 30, 2013
2 parents da4b376 + 6b08683 commit b927e48
Show file tree
Hide file tree
Showing 3 changed files with 268 additions and 36 deletions.
22 changes: 22 additions & 0 deletions src/libcore/container.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,4 +65,26 @@ pub trait Set<T>: Mutable {
/// Remove a value from the set. Return true if the value was
/// present in the set.
fn remove(&mut self, value: &T) -> bool;

/// Return true if the set has no elements in common with `other`.
/// This is equivalent to checking for an empty intersection.
pure fn is_disjoint(&self, other: &self) -> bool;

/// Return true if the set is a subset of another
pure fn is_subset(&self, other: &self) -> bool;

/// Return true if the set is a superset of another
pure fn is_superset(&self, other: &self) -> bool;

/// Visit the values representing the difference
pure fn difference(&self, other: &self, f: fn(&T) -> bool);

/// Visit the values representing the symmetric difference
pure fn symmetric_difference(&self, other: &self, f: fn(&T) -> bool);

/// Visit the values representing the intersection
pure fn intersection(&self, other: &self, f: fn(&T) -> bool);

/// Visit the values representing the union
pure fn union(&self, other: &self, f: fn(&T) -> bool);
}
227 changes: 223 additions & 4 deletions src/libcore/hashmap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,17 @@
#[forbid(deprecated_mode)];
#[forbid(deprecated_pattern)];

use container::{Container, Mutable, Map, Set};
use cmp::Eq;
use hash::Hash;
use to_bytes::IterBytes;

/// Open addressing with linear probing.
pub mod linear {
use super::*;
use iter::BaseIter;
use container::{Container, Mutable, Map, Set};
use cmp::Eq;
use cmp;
use hash::Hash;
use iter;
use kinds::Copy;
use option::{None, Option, Some};
use option;
Expand Down Expand Up @@ -453,6 +453,60 @@ pub mod linear {
/// Remove a value from the set. Return true if the value was
/// present in the set.
fn remove(&mut self, value: &T) -> bool { self.map.remove(value) }

/// Return true if the set has no elements in common with `other`.
/// This is equivalent to checking for an empty intersection.
pure fn is_disjoint(&self, other: &LinearSet<T>) -> bool {
iter::all(self, |v| !other.contains(v))
}

/// Return true if the set is a subset of another
pure fn is_subset(&self, other: &LinearSet<T>) -> bool {
iter::all(self, |v| other.contains(v))
}

/// Return true if the set is a superset of another
pure fn is_superset(&self, other: &LinearSet<T>) -> bool {
other.is_subset(self)
}

/// Visit the values representing the difference
pure fn difference(&self, other: &LinearSet<T>, f: fn(&T) -> bool) {
for self.each |v| {
if !other.contains(v) {
if !f(v) { return }
}
}
}

/// Visit the values representing the symmetric difference
pure fn symmetric_difference(&self, other: &LinearSet<T>,
f: fn(&T) -> bool) {
self.difference(other, f);
other.difference(self, f);
}

/// Visit the values representing the intersection
pure fn intersection(&self, other: &LinearSet<T>, f: fn(&T) -> bool) {
for self.each |v| {
if other.contains(v) {
if !f(v) { return }
}
}
}

/// Visit the values representing the union
pure fn union(&self, other: &LinearSet<T>, f: fn(&T) -> bool) {
for self.each |v| {
if !f(v) { return }
}

for other.each |v| {
if !self.contains(v) {
if !f(v) { return }
}
}
}
}

pub impl <T: Hash IterBytes Eq> LinearSet<T> {
Expand All @@ -462,7 +516,7 @@ pub mod linear {
}

#[test]
pub mod test {
mod test_map {
use container::{Container, Mutable, Map, Set};
use option::{None, Some};
use hashmap::linear::LinearMap;
Expand Down Expand Up @@ -610,3 +664,168 @@ pub mod test {
assert !m.is_empty();
}
}

#[test]
mod test_set {
use super::*;

#[test]
fn test_disjoint() {
let mut xs = linear::LinearSet::new();
let mut ys = linear::LinearSet::new();
assert xs.is_disjoint(&ys);
assert ys.is_disjoint(&xs);
assert xs.insert(5);
assert ys.insert(11);
assert xs.is_disjoint(&ys);
assert ys.is_disjoint(&xs);
assert xs.insert(7);
assert xs.insert(19);
assert xs.insert(4);
assert ys.insert(2);
assert ys.insert(-11);
assert xs.is_disjoint(&ys);
assert ys.is_disjoint(&xs);
assert ys.insert(7);
assert !xs.is_disjoint(&ys);
assert !ys.is_disjoint(&xs);
}

#[test]
fn test_subset_and_superset() {
let mut a = linear::LinearSet::new();
assert a.insert(0);
assert a.insert(5);
assert a.insert(11);
assert a.insert(7);

let mut b = linear::LinearSet::new();
assert b.insert(0);
assert b.insert(7);
assert b.insert(19);
assert b.insert(250);
assert b.insert(11);
assert b.insert(200);

assert !a.is_subset(&b);
assert !a.is_superset(&b);
assert !b.is_subset(&a);
assert !b.is_superset(&a);

assert b.insert(5);

assert a.is_subset(&b);
assert !a.is_superset(&b);
assert !b.is_subset(&a);
assert b.is_superset(&a);
}

#[test]
fn test_intersection() {
let mut a = linear::LinearSet::new();
let mut b = linear::LinearSet::new();

assert a.insert(11);
assert a.insert(1);
assert a.insert(3);
assert a.insert(77);
assert a.insert(103);
assert a.insert(5);
assert a.insert(-5);

assert b.insert(2);
assert b.insert(11);
assert b.insert(77);
assert b.insert(-9);
assert b.insert(-42);
assert b.insert(5);
assert b.insert(3);

let mut i = 0;
let expected = [3, 5, 11, 77];
for a.intersection(&b) |x| {
assert vec::contains(expected, x);
i += 1
}
assert i == expected.len();
}

#[test]
fn test_difference() {
let mut a = linear::LinearSet::new();
let mut b = linear::LinearSet::new();

assert a.insert(1);
assert a.insert(3);
assert a.insert(5);
assert a.insert(9);
assert a.insert(11);

assert b.insert(3);
assert b.insert(9);

let mut i = 0;
let expected = [1, 5, 11];
for a.difference(&b) |x| {
assert vec::contains(expected, x);
i += 1
}
assert i == expected.len();
}

#[test]
fn test_symmetric_difference() {
let mut a = linear::LinearSet::new();
let mut b = linear::LinearSet::new();

assert a.insert(1);
assert a.insert(3);
assert a.insert(5);
assert a.insert(9);
assert a.insert(11);

assert b.insert(-2);
assert b.insert(3);
assert b.insert(9);
assert b.insert(14);
assert b.insert(22);

let mut i = 0;
let expected = [-2, 1, 5, 11, 14, 22];
for a.symmetric_difference(&b) |x| {
assert vec::contains(expected, x);
i += 1
}
assert i == expected.len();
}

#[test]
fn test_union() {
let mut a = linear::LinearSet::new();
let mut b = linear::LinearSet::new();

assert a.insert(1);
assert a.insert(3);
assert a.insert(5);
assert a.insert(9);
assert a.insert(11);
assert a.insert(16);
assert a.insert(19);
assert a.insert(24);

assert b.insert(-2);
assert b.insert(1);
assert b.insert(5);
assert b.insert(9);
assert b.insert(13);
assert b.insert(19);

let mut i = 0;
let expected = [-2, 1, 3, 5, 9, 11, 13, 16, 19, 24];
for a.union(&b) |x| {
assert vec::contains(expected, x);
i += 1
}
assert i == expected.len();
}
}
Loading

0 comments on commit b927e48

Please sign in to comment.