1use std::fmt::{Debug, Formatter, Result as FResult};
4use std::mem::transmute_copy;
5use std::ptr::write;
6
7#[derive(Debug)]
8pub struct Item<T>{
9 elem: T,
10 count: usize, amount: usize, }
13
14pub struct WeightTree<T>(Vec<Item<T>>);
15
16impl<T> WeightTree<T> {
17
18 pub fn new() -> Self{
20 WeightTree(Vec::new())
21 }
22
23 pub fn with_capacity(capacity: usize) -> Self{
25 WeightTree(Vec::with_capacity(capacity))
26 }
27
28 pub fn amount(&self) -> usize{
30 match self.0.len(){
31 0 => 0,
32 _ => self.0[0].amount
33 }
34 }
35
36 pub fn len(&self) -> usize{
38 self.0.len()
39 }
40
41 pub fn clear(&mut self) {
43 self.0.clear();
44 }
45
46 pub fn push(&mut self, elem: T, weight: usize){
48 let len = self.0.len();
49 self.0.push(Item{
50 elem: elem,
51 count: weight,
52 amount: weight,
53 });
54 self.up(len)
55 }
56
57 pub fn pop(&mut self, weight: usize) -> (T, usize){
59 let index = self.find(weight, 0);
60 self.delete(index)
61 }
62
63 pub fn try_pop(&mut self, weight: usize) -> Option<(T, usize)>{
65 match self.0.len(){
66 0 => None,
67 _ => match self.0[0].amount <= weight{
68 true => None,
69 false => {
70 let index = self.find(weight, 0);
71 Some(self.delete(index))
72 }
73 }
74 }
75 }
76
77 #[inline]
79 fn find(&mut self, mut weight: usize, cur_index:usize) -> usize{
80 let cur_weight = self.0[cur_index].count;
81 match weight < cur_weight{
82 true => {return cur_index;
84 },
85 false => {weight = weight - cur_weight;
87 let left_index = (cur_index << 1) + 1;
88 match self.0[left_index].amount <= weight{ true => {
90 weight = weight - self.0[left_index].amount;
92 return self.find(weight, left_index + 1);},
94 false => return self.find(weight, left_index)};
96
97 }
98 };
99 }
100
101 #[inline]
103 fn delete(&mut self, index: usize) -> (T, usize){
104 let len = self.0.len();
105 let (index_count, index_amount) = {
106 let e = &self.0[index];
107 (e.count, e.amount)
108 };
109 if index + 1 < len{let last = len - 1;
112 let (last_count, last_amount) = {
113 let e = &self.0[last];
114 (e.count, e.amount)
115 };
116 self.0.swap(last, index);
117 self.0[index].count = index_count;
118 self.0[index].amount = index_amount;
119 self.0[last].count = last_count;
120 self.0[last].amount = last_amount;
121 self.up_update(index, last_count);
122 self.up_update(last, 0);
123 self.down(index);
124 }else{
125 self.up_update(index, 0);
126 }
127 let elem = self.0.pop().unwrap();
128 (elem.elem, index_count)
129 }
130
131 fn up_update(&mut self, mut cur: usize, weight: usize) -> usize{
133 let arr = &mut self.0;
134 let old_count = arr[cur].count;
135 {
136 let elem = &mut arr[cur];
137 elem.count = weight;
138 elem.amount = elem.amount - old_count + weight;
139 }
140 if cur > 0{
141 let mut parent = (cur - 1) >> 1;
142
143 let mut elem: Item<T> = unsafe{ transmute_copy(&arr[cur])};
144 while weight > arr[parent].count{
145 let new_amount = elem.amount;
146 elem.amount = arr[parent].amount - old_count + weight;
147 arr[parent].amount = new_amount - elem.count + arr[parent].count;
149 let src = arr.as_mut_ptr();
150 unsafe{src.wrapping_offset(parent as isize).copy_to(src.wrapping_offset(cur as isize), 1)};
151
152 cur = parent;
154 if parent == 0{
155 break;
156 }
157 parent = (cur - 1) >> 1;
158 }
159 unsafe{write(arr.as_mut_ptr().wrapping_offset(cur as isize), elem)};
160
161 let mut i = cur;
162 while i > 0{
163 i = (i - 1) >> 1;arr[i].amount = arr[i].amount + weight - old_count;
169 }
170 }
171 cur
172 }
173
174 fn up(&mut self, mut cur: usize){
176 let arr = &mut self.0;
177 if cur > 0{
178 let mut parent = (cur - 1) >> 1;
179
180 let mut elem: Item<T> = unsafe{ transmute_copy(&arr[cur])};
181 while elem.count > arr[parent].count {
182 let ew = elem.amount;
183 elem.amount = arr[parent].amount + elem.count;
184 arr[parent].amount = ew + arr[parent].count - elem.count;
185 let src = arr.as_mut_ptr();
186 unsafe{src.wrapping_offset(parent as isize).copy_to(src.wrapping_offset(cur as isize), 1)};
187
188 cur = parent;
190 if parent == 0{
191 break;
192 }
193 parent = (cur - 1) >> 1;
194 }
195 unsafe{write(arr.as_mut_ptr().wrapping_offset(cur as isize), elem)};
196
197 let w = arr[cur].count;
198 let mut i = cur;
199 while i > 0{
200 i = (i - 1) >> 1;arr[i].amount += w;
202 }
203 }
204 }
205
206 fn down(&mut self, index: usize) -> usize {
211
212 let mut cur = index;
213 let arr = &mut self.0;
214 let mut left = (cur << 1) + 1;
215 let mut right = left + 1;
216 let len = arr.len();
217 let mut elem: Item<T> = unsafe{ transmute_copy(&arr[cur])};
218 while left < len {
219
220 let mut child = left;
222 if right < len && arr[right].count > arr[left].count {
223 child = right;
224 }
225 match arr[cur].count >= arr[child].count{
227 true => break,
228 false => {
229 let cw = arr[child].amount;
230 arr[child].amount = elem.amount;
231 elem.amount = cw - arr[child].count + elem.count;
232 let src = arr.as_mut_ptr();
233 unsafe{src.wrapping_offset(child as isize).copy_to(src.wrapping_offset(cur as isize), 1)};
234 cur = child;
236 left = (cur << 1) + 1;
237 right = left + 1;
238 }
239 }
240 }
241 unsafe{write(arr.as_mut_ptr().wrapping_offset(cur as isize), elem)};
242 cur
243 }
244}
245
246impl<T: Debug> Debug for WeightTree<T> where T: Debug {
247 fn fmt(&self, fmt: &mut Formatter) -> FResult {
248 write!(fmt,
249 "WeightTree({:?})",
250 self.0,
251 )
252 }
253}
254
255#[cfg(test)]
256use rand::Rng;
257
258#[test]
259fn test_effic(){
260 let mut weight_tree: WeightTree<u32> = WeightTree::new();
261 let max = 100000;
262 let now = std::time::Instant::now();
263 for i in 0..max{
264 weight_tree.push(i, (i+1) as usize);
265 }
266 println!("fast_wtree: push max_heap time{:?}", std::time::Instant::now() - now);
267
268 let now = std::time::Instant::now();
269 for _ in 0..max{
270 rand::thread_rng().gen_range(0, 100000);
271 }
272 println!("fast_wtree: rand time{:?}", std::time::Instant::now() - now);
273
274
275 let now = std::time::Instant::now();
276 for _ in 0..max{
277 let r = rand::thread_rng().gen_range(0, weight_tree.amount());
278 weight_tree.pop(r);
279 }
280 println!("fast_wtree: remove_by_weight time{:?}", std::time::Instant::now() - now);
281
282 }
284