Skip to content

Commit d29b68b

Browse files
committed
provide drop_left(_shallow) drop_right(_shallow) for different purposes; tag 0.0.9
1 parent 5c6e91b commit d29b68b

File tree

5 files changed

+297
-3
lines changed

5 files changed

+297
-3
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11

22
[package]
33
name = "im_ternary_tree"
4-
version = "0.0.8"
4+
version = "0.0.9"
55
edition = "2021"
66
authors = ["jiyinyiyong <jiyinyiyong@gmail.com>"]
77
license = "MIT"

benches/creating.rs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,38 @@ fn criterion_benchmark(c: &mut Criterion) {
139139
})
140140
});
141141

142+
c.bench_function("drop-left-shallow", |b| {
143+
let mut data = TernaryTreeList::Empty;
144+
145+
for idx in 0..1000 {
146+
data = data.push(idx);
147+
}
148+
149+
b.iter(move || {
150+
let mut d = data.to_owned();
151+
152+
while d.len() > 1 {
153+
d = d.drop_left_shallow()
154+
}
155+
})
156+
});
157+
158+
c.bench_function("drop-right-shallow", |b| {
159+
let mut data = TernaryTreeList::Empty;
160+
161+
for idx in 0..1000 {
162+
data = data.push(idx);
163+
}
164+
165+
b.iter(move || {
166+
let mut d = data.to_owned();
167+
168+
while d.len() > 1 {
169+
d = d.drop_right_shallow()
170+
}
171+
})
172+
});
173+
142174
c.bench_function("drop-left from push_right", |b| {
143175
let mut data = TernaryTreeList::Empty;
144176

src/lib.rs

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -238,8 +238,21 @@ where
238238
}
239239
}
240240

241-
/// optimized for amortized `O(1)` at best cases
242241
pub fn drop_left(&self) -> Self {
242+
match self {
243+
Empty => TernaryTreeList::Empty,
244+
Tree(t) => {
245+
if t.len() == 1 {
246+
Self::Empty
247+
} else {
248+
Self::Tree(t.drop_left())
249+
}
250+
}
251+
}
252+
}
253+
254+
/// optimized for amortized `O(1)` at best cases, but copies a lot
255+
pub fn drop_left_shallow(&self) -> Self {
243256
match self {
244257
Empty => TernaryTreeList::Empty,
245258
Tree(t) => {
@@ -255,8 +268,21 @@ where
255268
}
256269
}
257270

258-
/// optimized for amortized `O(1)` at best cases
259271
pub fn drop_right(&self) -> Self {
272+
match self {
273+
Empty => Self::Empty,
274+
Tree(t) => {
275+
if t.len() == 1 {
276+
Self::Empty
277+
} else {
278+
Self::Tree(t.drop_right())
279+
}
280+
}
281+
}
282+
}
283+
284+
/// optimized for amortized `O(1)` at best cases, but copies a lot
285+
pub fn drop_right_shallow(&self) -> Self {
260286
match self {
261287
Empty => Self::Empty,
262288
Tree(t) => {

src/tree/finger.rs

Lines changed: 198 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -630,4 +630,202 @@ where
630630
}
631631
}
632632
}
633+
634+
pub fn drop_left(&self) -> Self {
635+
match self {
636+
Leaf(_) => {
637+
unreachable!("not expected empty node inside tree")
638+
}
639+
Branch2 { size, left, middle, .. } => {
640+
if left.len() == 1 {
641+
(**middle).to_owned()
642+
} else {
643+
let changed_branch = left.drop_left();
644+
match changed_branch {
645+
Branch2 {
646+
left: b_left,
647+
middle: b_middle,
648+
..
649+
} => Branch3 {
650+
size: size - 1,
651+
left: b_left,
652+
middle: b_middle,
653+
right: middle.to_owned(),
654+
},
655+
Branch3 {
656+
left: b_left,
657+
middle: b_middle,
658+
right: b_right,
659+
..
660+
} => {
661+
let internal_branch = Branch2 {
662+
size: b_middle.len() + b_right.len(),
663+
left: b_middle,
664+
middle: b_right,
665+
};
666+
Branch3 {
667+
size: size - 1,
668+
left: b_left,
669+
middle: Arc::new(internal_branch),
670+
right: middle.to_owned(),
671+
}
672+
}
673+
_ => Branch2 {
674+
size: size - 1,
675+
left: Arc::new(changed_branch),
676+
middle: middle.to_owned(),
677+
},
678+
}
679+
}
680+
}
681+
Branch3 {
682+
size, left, middle, right, ..
683+
} => {
684+
if left.len() == 1 {
685+
match &**middle {
686+
Branch2 {
687+
left: b_left,
688+
middle: b_middle,
689+
..
690+
} => Branch3 {
691+
size: size - 1,
692+
left: b_left.to_owned(),
693+
middle: b_middle.to_owned(),
694+
right: right.to_owned(),
695+
},
696+
Branch3 {
697+
left: b_left,
698+
middle: b_middle,
699+
right: b_right,
700+
..
701+
} => {
702+
let internal_branch = Branch2 {
703+
size: b_middle.len() + b_right.len(),
704+
left: b_middle.to_owned(),
705+
middle: b_right.to_owned(),
706+
};
707+
Branch3 {
708+
size: size - 1,
709+
left: b_left.to_owned(),
710+
middle: Arc::new(internal_branch),
711+
right: right.to_owned(),
712+
}
713+
}
714+
_ => Branch2 {
715+
size: size - 1,
716+
left: middle.to_owned(),
717+
middle: right.to_owned(),
718+
},
719+
}
720+
} else {
721+
let changed_branch = left.drop_left();
722+
Branch3 {
723+
size: size - 1,
724+
left: Arc::new(changed_branch),
725+
middle: middle.to_owned(),
726+
right: right.to_owned(),
727+
}
728+
}
729+
}
730+
}
731+
}
732+
733+
pub fn drop_right(&self) -> Self {
734+
match self {
735+
Leaf(_) => {
736+
unreachable!("not expected empty node inside tree")
737+
}
738+
Branch2 { size, left, middle, .. } => {
739+
if middle.len() == 1 {
740+
(**left).to_owned()
741+
} else {
742+
let changed_branch = middle.drop_right();
743+
match changed_branch {
744+
Branch2 {
745+
left: b_left,
746+
middle: b_middle,
747+
..
748+
} => Branch3 {
749+
size: size - 1,
750+
left: left.to_owned(),
751+
middle: b_left,
752+
right: b_middle,
753+
},
754+
Branch3 {
755+
left: b_left,
756+
middle: b_middle,
757+
right: b_right,
758+
..
759+
} => {
760+
let internal_branch = Branch2 {
761+
size: b_middle.len() + b_left.len(),
762+
left: b_left,
763+
middle: b_middle,
764+
};
765+
Branch3 {
766+
size: size - 1,
767+
left: left.to_owned(),
768+
middle: Arc::new(internal_branch),
769+
right: b_right,
770+
}
771+
}
772+
_ => Branch2 {
773+
size: size - 1,
774+
left: left.to_owned(),
775+
middle: Arc::new(changed_branch),
776+
},
777+
}
778+
}
779+
}
780+
Branch3 {
781+
size, right, middle, left, ..
782+
} => {
783+
if right.len() == 1 {
784+
match &**middle {
785+
Branch2 {
786+
left: b_left,
787+
middle: b_middle,
788+
..
789+
} => Branch3 {
790+
size: size - 1,
791+
left: left.to_owned(),
792+
middle: b_left.to_owned(),
793+
right: b_middle.to_owned(),
794+
},
795+
Branch3 {
796+
left: b_left,
797+
middle: b_middle,
798+
right: b_right,
799+
..
800+
} => {
801+
let internal_branch = Branch2 {
802+
size: b_middle.len() + b_left.len(),
803+
left: b_left.to_owned(),
804+
middle: b_middle.to_owned(),
805+
};
806+
Branch3 {
807+
size: size - 1,
808+
left: left.to_owned(),
809+
middle: Arc::new(internal_branch),
810+
right: b_right.to_owned(),
811+
}
812+
}
813+
_ => Branch2 {
814+
size: size - 1,
815+
left: left.to_owned(),
816+
middle: middle.to_owned(),
817+
},
818+
}
819+
} else {
820+
let changed_branch = right.drop_right();
821+
Branch3 {
822+
size: size - 1,
823+
left: left.to_owned(),
824+
middle: middle.to_owned(),
825+
right: Arc::new(changed_branch),
826+
}
827+
}
828+
}
829+
}
830+
}
633831
}

tests/list_tests.rs

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,44 @@ fn drop_right_data() -> Result<(), String> {
144144
Ok(())
145145
}
146146

147+
#[test]
148+
fn drop_left_shallow() -> Result<(), String> {
149+
let mut data: Vec<usize> = vec![];
150+
for idx in 0..200 {
151+
data.push(idx);
152+
}
153+
let mut tree: TernaryTreeList<usize> = TernaryTreeList::from(data.to_owned());
154+
155+
// do once less than the length
156+
for _ in 0..data.len() {
157+
tree = tree.drop_left_shallow();
158+
tree.check_structure()?;
159+
data.remove(0);
160+
assert_eq!(tree, TernaryTreeList::from(data.to_owned()));
161+
}
162+
163+
Ok(())
164+
}
165+
166+
#[test]
167+
fn drop_right_shallow() -> Result<(), String> {
168+
let mut data: Vec<usize> = vec![];
169+
for idx in 0..200 {
170+
data.push(idx);
171+
}
172+
let mut tree: TernaryTreeList<usize> = TernaryTreeList::from(data.to_owned());
173+
174+
// do once less than the length
175+
for _ in 0..data.len() {
176+
tree = tree.drop_right_shallow();
177+
tree.check_structure()?;
178+
data.remove(data.len() - 1);
179+
assert_eq!(tree, TernaryTreeList::from(data.to_owned()));
180+
}
181+
182+
Ok(())
183+
}
184+
147185
#[test]
148186
fn dissoc() -> Result<(), String> {
149187
let data = TernaryTreeList::from(&[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);

0 commit comments

Comments
 (0)