Merge pull request #4682 from thestinger/treemap

Set trait improvements + minor treemap cleanup
This commit is contained in:
Tim Chevalier 2013-01-29 20:09:15 -08:00
commit b927e48a26
3 changed files with 268 additions and 36 deletions

View File

@ -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);
}

View File

@ -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;
@ -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> {
@ -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;
@ -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();
}
}

View File

@ -29,10 +29,10 @@ use core::prelude::*;
// range search - O(log n) retrieval of an iterator from some key
// (possibly) implement the overloads Python does for sets:
// * union: |
// * intersection: &
// * difference: -
// * symmetric difference: ^
// * union: |
// These would be convenient since the methods work like `each`
pub struct TreeMap<K, V> {
@ -49,10 +49,9 @@ impl <K: Eq Ord, V: Eq> TreeMap<K, V>: Eq {
let mut y = other.iter();
for self.len().times {
unsafe { // unsafe as a purity workaround
// ICE: x.next() != y.next()
x = x.next();
y = y.next();
// FIXME: #4492 (ICE), x.get() == y.get()
let (x1, x2) = x.get().unwrap();
let (y1, y2) = y.get().unwrap();
@ -292,22 +291,6 @@ impl <T: Ord> TreeSet<T>: Set<T> {
/// 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) }
}
impl <T: Ord> TreeSet<T> {
/// Create an empty TreeSet
static pure fn new() -> TreeSet<T> { TreeSet{map: TreeMap::new()} }
/// Visit all values in reverse order
pure fn each_reverse(&self, f: fn(&T) -> bool) {
self.map.each_key_reverse(f)
}
/// Get a lazy iterator over the values in the set.
/// Requires that it be frozen (immutable).
pure fn iter(&self) -> TreeSetIterator/&self<T> {
TreeSetIterator{iter: self.map.iter()}
}
/// Return true if the set has no elements in common with `other`.
/// This is equivalent to checking for an empty intersection.
@ -336,12 +319,12 @@ impl <T: Ord> TreeSet<T> {
true
}
/// Check of the set is a subset of another
/// Return true if the set is a subset of another
pure fn is_subset(&self, other: &TreeSet<T>) -> bool {
other.is_superset(self)
}
/// Check of the set is a superset of another
/// Return true if the set is a superset of another
pure fn is_superset(&self, other: &TreeSet<T>) -> bool {
let mut x = self.iter();
let mut y = other.iter();
@ -517,6 +500,22 @@ impl <T: Ord> TreeSet<T> {
}
}
impl <T: Ord> TreeSet<T> {
/// Create an empty TreeSet
static pure fn new() -> TreeSet<T> { TreeSet{map: TreeMap::new()} }
/// Visit all values in reverse order
pure fn each_reverse(&self, f: fn(&T) -> bool) {
self.map.each_key_reverse(f)
}
/// Get a lazy iterator over the values in the set.
/// Requires that it be frozen (immutable).
pure fn iter(&self) -> TreeSetIterator/&self<T> {
TreeSetIterator{iter: self.map.iter()}
}
}
/// Lazy forward iterator over a set
pub struct TreeSetIterator<T> {
priv iter: TreeMapIterator<T, ()>
@ -652,14 +651,12 @@ fn remove<K: Ord, V>(node: &mut Option<~TreeNode<K, V>>, key: &K) -> bool {
let mut left = save.left.swap_unwrap();
if left.right.is_some() {
heir_swap(save, &mut left.right);
save.left = Some(left);
remove(&mut save.left, key);
} else {
save.key <-> left.key;
save.value <-> left.value;
}
save.left = Some(left);
remove(&mut save.left, key);
}
} else {
save = save.left.swap_unwrap();
}
@ -969,9 +966,7 @@ mod test_treemap {
let m = m;
let mut iter = m.iter();
// ICE:
//assert iter.next() == Some((&x1, &y1));
//assert iter.next().eq(&Some((&x1, &y1)));
// FIXME: #4492 (ICE): iter.next() == Some((&x1, &y1))
iter = iter.next();
assert iter.get().unwrap() == (&x1, &y1);
@ -984,10 +979,6 @@ mod test_treemap {
iter = iter.next();
assert iter.get().unwrap() == (&x5, &y5);
// ICE:
//assert iter.next() == None;
//assert iter.next().eq(&None);
iter = iter.next();
assert iter.get().is_none();
}