cp_library_rs/data_structure/
multiset.rs1use rustc_hash::FxHashMap;
4use std::{collections::BTreeSet, fmt::Debug, hash::Hash};
5
6pub struct MultiSet<T> {
7 pub counter: FxHashMap<T, usize>,
8 pub items: BTreeSet<(T, usize)>,
9}
10
11impl<T> Default for MultiSet<T>
12where
13 T: Ord + Hash + Copy,
14{
15 fn default() -> Self {
16 Self::new()
17 }
18}
19
20impl<T> MultiSet<T>
21where
22 T: Ord + Hash + Copy,
23{
24 pub fn new() -> Self {
26 MultiSet {
27 counter: FxHashMap::default(),
28 items: BTreeSet::new(),
29 }
30 }
31
32 pub fn insert(&mut self, x: T) {
34 let cnt = self.counter.entry(x).or_insert(0);
36 self.items.insert((x, *cnt));
38 *cnt += 1;
40 }
41
42 pub fn remove(&mut self, x: &T) -> bool {
44 if let Some(v) = self.counter.get_mut(x) {
45 if *v > 0 {
47 *v -= 1;
48 self.items.remove(&(*x, *v));
50 return true;
51 }
52 }
53 false
54 }
55
56 pub fn contains(&self, x: &T) -> bool {
58 self.counter.get(x).is_some_and(|cnt| *cnt > 0)
59 }
60
61 pub fn first(&self) -> Option<&T> {
63 self.items.first().map(|(ref x, _)| x)
64 }
65
66 pub fn last(&self) -> Option<&T> {
68 self.items.last().map(|(ref x, _)| x)
69 }
70
71 pub fn count(&self, x: &T) -> usize {
73 match self.counter.get(x) {
74 Some(&v) => v,
75 None => 0,
76 }
77 }
78
79 pub fn clear(&mut self) {
81 self.counter.clear();
82 self.items.clear();
83 }
84
85 pub fn len(&self) -> usize {
86 self.items.len()
87 }
88
89 pub fn is_empty(&self) -> bool {
90 self.len() == 0
91 }
92}
93
94impl<T> MultiSet<T> {
95 pub fn iter(&self) -> impl Iterator<Item = &T> {
96 self.items.iter().map(|(ref x, _)| x)
97 }
98}
99
100impl<T: Ord + Hash + Copy> FromIterator<T> for MultiSet<T> {
101 fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
102 let mut multiset = MultiSet::new();
103 for x in iter {
104 multiset.insert(x);
105 }
106 multiset
107 }
108}
109
110impl<T: Debug> Debug for MultiSet<T> {
111 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
112 f.debug_set().entries(self.iter()).finish()
113 }
114}