// Copyright 2016 oauth-client-rs Developers // // Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or // http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or // http://opensource.org/licenses/MIT>, at your option. This file may not be // copied, modified, or distributed except according to those terms.
use std::cmp::Ordering; use std::collections::{HashMap, HashSet}; use std::collections::hash_map::Entry; use std::fmt; use std::hash::Hash; use std::iter::FromIterator;
impl<T: Hash + Eq + Clone> TopologicalSort<T> { /// Creates new empty `TopologicalSort`. /// /// ```rust /// # extern crate topological_sort; /// # fn main() { /// use topological_sort::TopologicalSort; /// let mut ts = TopologicalSort::<&str>::new(); /// ts.add_dependency("hello_world.o", "hello_world"); /// ts.add_dependency("hello_world.c", "hello_world"); /// ts.add_dependency("stdio.h", "hello_world.o"); /// ts.add_dependency("glibc.so", "hello_world"); /// assert_eq!(vec!["glibc.so", "hello_world.c", "stdio.h"], /// { let mut v = ts.pop_all(); v.sort(); v }); /// assert_eq!(vec!["hello_world.o"], /// { let mut v = ts.pop_all(); v.sort(); v }); /// assert_eq!(vec!["hello_world"], /// { let mut v = ts.pop_all(); v.sort(); v }); /// assert!(ts.pop_all().is_empty()); /// # } /// ``` #[inline] pubfn new() -> TopologicalSort<T> {
TopologicalSort {
top: HashMap::new(),
}
}
/// Returns the number of elements in the `TopologicalSort`. #[inline] pubfn len(&self) -> usize { self.top.len()
}
/// Returns true if the `TopologicalSort` contains no elements. #[inline] pubfn is_empty(&self) -> bool { self.top.is_empty()
}
/// Registers the two elements' dependency. /// /// # Arguments /// /// * `prec` - The element appears before `succ`. `prec` is depended on by `succ`. /// * `succ` - The element appears after `prec`. `succ` depends on `prec`. pubfn add_dependency<P, S>(&mutself, prec: P, succ: S) where
P: Into<T>,
S: Into<T>,
{ self.add_dependency_impl(prec.into(), succ.into())
}
fn add_dependency_impl(&mutself, prec: T, succ: T) { matchself.top.entry(prec) {
Entry::Vacant(e) => { letmut dep = Dependency::new(); let _ = dep.succ.insert(succ.clone()); let _ = e.insert(dep);
}
Entry::Occupied(e) => { if !e.into_mut().succ.insert(succ.clone()) { // Already registered return;
}
}
}
/// Inserts an element, without adding any dependencies from or to it. /// /// If the `TopologicalSort` did not have this element present, `true` is returned. /// /// If the `TopologicalSort` already had this element present, `false` is returned. pubfn insert<U>(&mutself, elt: U) -> bool where
U: Into<T>,
{ matchself.top.entry(elt.into()) {
Entry::Vacant(e) => { let dep = Dependency::new(); let _ = e.insert(dep); true
}
Entry::Occupied(_) => false,
}
}
/// Removes the item that is not depended on by any other items and returns it, or `None` if /// there is no such item. /// /// If `pop` returns `None` and `len` is not 0, there is cyclic dependencies. pubfn pop(&mutself) -> Option<T> { self.peek().map(T::clone).map(|key| { let _ = self.remove(&key);
key
})
}
/// Removes all items that are not depended on by any other items and returns it, or empty /// vector if there are no such items. /// /// If `pop_all` returns an empty vector and `len` is not 0, there is cyclic dependencies. pubfn pop_all(&mutself) -> Vec<T> { let keys = self.top
.iter()
.filter(|&(_, v)| v.num_prec == 0)
.map(|(k, _)| k.clone())
.collect::<Vec<_>>(); for k in &keys { let _ = self.remove(k);
}
keys
}
/// Return a reference to the first item that does not depend on any other items, or `None` if /// there is no such item. pubfn peek(&self) -> Option<&T> { self.top
.iter()
.filter(|&(_, v)| v.num_prec == 0)
.map(|(k, _)| k)
.next()
}
/// Return a vector of references to all items that do not depend on any other items, or an /// empty vector if there are no such items. pubfn peek_all(&self) -> Vec<&T> { self.top
.iter()
.filter(|&(_, v)| v.num_prec == 0)
.map(|(k, _)| k)
.collect::<Vec<_>>()
}
fn remove(&mutself, prec: &T) -> Option<Dependency<T>> { let result = self.top.remove(prec); iflet Some(ref p) = result { for s in &p.succ { iflet Some(y) = self.top.get_mut(s) {
y.num_prec -= 1;
}
}
}
result
}
}
impl<T: PartialOrd + Eq + Hash + Clone> FromIterator<T> for TopologicalSort<T> { fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> TopologicalSort<T> { letmut top = TopologicalSort::new(); letmut seen = Vec::<T>::default(); for item in iter { let _ = top.insert(item.clone()); for seen_item in seen.iter().cloned() { match seen_item.partial_cmp(&item) {
Some(Ordering::Less) => {
top.add_dependency(seen_item, item.clone());
}
Some(Ordering::Greater) => {
top.add_dependency(item.clone(), seen_item);
}
_ => (),
}
}
seen.push(item);
}
top
}
}
/// A link between two items in a sort. #[derive(Copy, Clone, Debug)] pubstruct DependencyLink<T> { /// The element which is depened upon by `succ`. pub prec: T, /// The element which depends on `prec`. pub succ: T,
}
impl<T: Eq + Hash + Clone> FromIterator<DependencyLink<T>> for TopologicalSort<T> { fn from_iter<I: IntoIterator<Item = DependencyLink<T>>>(iter: I) -> TopologicalSort<T> { letmut top = TopologicalSort::new(); for link in iter {
top.add_link(link);
}
top
}
}
impl<T: Hash + Eq + Clone> Iterator for TopologicalSort<T> { type Item = T;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.