digitalmars.D - RedBlackTree with Array Store
- %u (137/137) Jan 13 2011 Hi,
- Steven Wawryk (8/19) Jan 13 2011 I haven't looked at your code, but I came across the idea of a vector
- %u (8/9) Jan 13 2011 container would need to be kept sorted.
- Steven Wawryk (4/13) Jan 14 2011 I see. It's not what I meant when I described the vector map. That has...
- Steven Schveighoffer (9/25) Jan 14 2011 Didn't look at your code exactly, but from reading this discussion, what...
- %u (11/13) Jan 14 2011 have implemented is basically a memory pool ;)
- Steven Schveighoffer (4/26) Jan 15 2011 Sure, in fact you could currently use dcollections to test it, since it ...
Hi, I've noticed that, just as you can have a heap with an array-backed store, you can also have a binary search tree with the same store (although structured differently; see attachment for a bare-bones unsorted binary tree implementation -- which I have NOT yet tested, but which I can test if it will be used). The improvement will be in data locality, and while it may seem to use a bit more space than a link-based tree, I think it's worth it to let the RedBlackTree class use a custom store, such as any store that has getLeft/getRight/setLeft/setRight methods, and that uses opaque pointers. How does this idea sound? Thank you! begin 644 arraycontainer.d M<')I=F%T92!I;7!O<G0 <W1D+F%L9V]R:71H;2`Z(&UA>"P <W=A<#L-"G!R M3F]D92A4*0T*>PT*"7!U8FQI8R!4('9A;'5E.PT*"7!R:79A=&4 <'1R9&EF M<FEV871E($)I;F%R>4AE87`A*'!T<F1I9F9?=%M=*2!O<&5N26YD:6-E<SL- M8V *&D[('1H:7,N;W!E;DEN9&EC97,I('L 87-S97)T*'1H:7,N:71E;7-; M96T[('1H:7,N:71E;7,I('L :68 *&ET96TN<V5L9B`^/2`P*2![(&%S<V5R M="AI=&5M+G-E;&8 /3T :2P (DET96T :6YD97 9&ED(&YO="!P;VEN="!T M;R!I=&5M+B(I.R!C;W5N="LK.R!]('T-" D)87-S97)T*&-O=6YT(#T]('1H M:7,N:71E;7,N;&5N9W1H("T =&AI<RYO<&5N26YD:6-E<RYL96YG=& L(")4 M('9O:60 =F%L:61A=&4H:6X 8V]N<W0H3F]D92$H5"DI*B!N;V1E*0T*"7L- M" D):68 *&YO9&4 (3T ;G5L;"D-" D)>PT*"0D)87-S97)T*"9T:&ES+FET M(#P ,"!\?"!T:&ES+F=E=$QE9G0H;F]D92DN<&%R96YT(#T](&YO9&4N<V5L M="AN;V1E*2YP87)E;G0 /3T ;F]D92YS96QF*3L-" D)"6%S<V5R="AN;V1E M(&YO9&4N<V5L9BD ?"`H=&AI<RYG971087)E;G0H;F]D92DN<FEG:'0 /3T M;VYS="A.;V1E(2A4*2DJ(')O;W0H*2![(')E='5R;B!T:&ES+FE2;V]T(#X] M:6, 8V]N<W0H3F]D92$H5"DI*B!G971087)E;G0H8V]N<W0H3F]D92$H5"DI M*B!N;V1E*2!I;B![('1H:7,N=F%L:61A=&4H;F]D92D[('T ;W5T("AP*2![ M('1H:7,N=F%L:61A=&4H<"D[('T 8F]D>2![(')E='5R;B!N;V1E+G!A<F5N M"7!U8FQI8R!C;VYS="A.;V1E(2A4*2DJ(&=E=$QE9G0H8V]N<W0H3F]D92$H M5"DI*B!N;V1E*2!I;B![('1H:7,N=F%L:61A=&4H;F]D92D[('T ;W5T("AP M*2![('1H:7,N=F%L:61A=&4H<"D[('T 8F]D>2![(')E='5R;B!N;V1E+FQE M<'5B;&EC(&-O;G-T*$YO9&4A*%0I*2H 9V5T4FEG:'0H8V]N<W0H3F]D92$H M5"DI*B!N;V1E*2!I;B![('1H:7,N=F%L:61A=&4H;F]D92D[('T ;W5T("AP M*2![('1H:7,N=F%L:61A=&4H<"D[('T 8F]D>2![(')E='5R;B!N;V1E+G)I M9VAT(#X M" T*"7!U8FQI8R!V;VED('-E=$QE9G0H8V]N<W0H3F]D92$H5"DI*B!N;V1E M92`A/2!N=6QL*3L =&AI<RYV86QI9&%T92AN;V1E*3L =&AI<RYV86QI9&%T M92AL969T*3L ?0T*"6)O9'D >R!T:&ES+FET96US6VYO9&4N<V5L9ETN;&5F M="`](&QE9G0 (3T ;G5L;"`_(&QE9G0N<V5L9B`Z("TQ.R!I9B`H;&5F="`A M/2!N=6QL*2![('1H:7,N:71E;7-;;&5F="YS96QF72YP87)E;G0 /2!N;V1E M92$H5"DI*B!N;V1E+"!I;B!C;VYS="A.;V1E(2A4*2DJ(')I9VAT*0T*"6EN M('L 87-S97)T*&YO9&4 (3T ;G5L;"D[('1H:7,N=F%L:61A=&4H;F]D92D[ M;F]D92YS96QF72YR:6=H="`](')I9VAT("$](&YU;&P /R!R:6=H="YS96QF M(#H +3$[(&EF("AR:6=H="`A/2!N=6QL*2![('1H:7,N:71E;7-;<FEG:'0N M<V5L9ETN<&%R96YT(#T ;F]D92YS96QF.R!]('T-" T*"7!U8FQI8R!C;VYS M=&5M<RYL96YG=& *R`Q*3L-" D)875T;R!I(#T =&AI<RYO<&5N26YD:6-E M<RYF<F]N=#L-" D)=&AI<RYI=&5M<UMI72`]($YO9&4A*%0I*%0N:6YI="P M;G0H*3L-" D):68 *'1H:7,N:5)O;W0 /"`P*2![('1H:7,N:5)O;W0 /2!I M('!R979,96X /2!T:&ES+FET96US+FQE;F=T:#L-" D)"71H:7,N:71E;7,N M;&5N9W1H(#T ;6%X*&-A<&%C:71Y+"`R("H =&AI<RYI=&5M<RYL96YG=& I M.PT*"0D)875T;R!I;F1I8V5S(#T ;F5W('!T<F1I9F9?=%MT:&ES+FET96US M;W!E;DEN9&EC97,N96UP='DI('L :6YD:6-E<UMI*RM=(#T =&AI<RYO<&5N M26YD:6-E<RYF<F]N=#L =&AI<RYO<&5N26YD:6-E<RYR96UO=F5&<F]N=" I M9W1H*2![(&EN9&EC97-;:2LK72`](&H[('T-" D)"71H:7,N;W!E;DEN9&EC M97,N86-Q=6ER92AI;F1I8V5S+"!I*3L-" D)?0T*"7T-" T*"7!U8FQI8R!V M;VED(&9R965.;V1E*&-O;G-T*$YO9&4A*%0I*2H ;F]D92D-" EI;B![('1H M;V1E+G-E;&9=.PT*"0D)=&AI<RYF<F5E3F]D92AT:&ES+F=E=$QE9G0H<$UY M3F]D92DI.PT*"0D)<$UY3F]D92YL969T(#T M;V1E*'1H:7,N9V5T4FEG:'0H<$UY3F]D92DI.PT*"0D)<$UY3F]D92YR:6=H M="`]("TQ.PT*"0D):68 *'!->4YO9&4N<&%R96YT(#X M=&5M<UMP37E.;V1E+G!A<F5N=%TN;&5F="`]/2!P37E.;V1E+G-E;&8I('L M9B`H<$UY3F]D92YP87)E;G0 /CT ,"`F)B!T:&ES+FET96US6W!->4YO9&4N M<&%R96YT72YR:6=H="`]/2!P37E.;V1E+G-E;&8I('L =&AI<RYI=&5M<UMP M37E.;V1E+G!A<F5N=%TN<FEG:'0 /2`M,3L ?0T*"0D)<$UY3F]D92YP87)E M;G0 /2`M,3L-" D)"71H:7,N;W!E;DEN9&EC97,N:6YS97)T*'!->4YO9&4N M;V]T(#T]('!->4YO9&4N<V5L9BD >R!T:&ES+FE2;V]T(#T +3$[('T-" D) M?0T*"7T-" T*"7!R:79A=&4 =F]I9"!S=V%P4VQO='-.;TYO=&EF>4AE87`H M<'1R9&EF9E]T(&DL('!T<F1I9F9?="!J*0T*"7L-" D)87-S97)T*&D /CT M,"`F)B!J(#X M;7-;:ETI.PT*"0ES=V%P*'1H:7,N:71E;7-;:5TN<V5L9BP =&AI<RYI=&5M M<UMJ72YS96QF*3L-" D):68 *'1H:7,N:71E;7-;:5TN;&5F="`^/2`P*2![ M('1H:7,N:71E;7-;=&AI<RYI=&5M<UMI72YL969T72YP87)E;G0 /2!J.R!] M:&ES+FET96US6VI=+FQE9G0 /CT ,"D >R!T:&ES+FET96US6W1H:7,N:71E M;7-;:ETN;&5F=%TN<&%R96YT(#T :3L ?0T*"0EI9B`H=&AI<RYI=&5M<UMJ M72YR:6=H="`^/2`P*2![('1H:7,N:71E;7-;=&AI<RYI=&5M<UMJ72YR:6=H M=%TN<&%R96YT(#T :3L ?0T*"0EI9B`H=&AI<RYI4F]O="`]/2!I*2![('1H M>R!T:&ES+FE2;V]T(#T :3L ?0T*"7T-" T*"7!U8FQI8R!V;VED('1R:6TH M*0T*"7L-" D)<VEZ95]T(&QE;E9A;&ED(#T =&AI<RYI=&5M<RYL96YG=& [ M" D)>PT*"0D):68 *'1H:7,N;W!E;DEN9&EC97,N96UP='DI('L 8G)E86L[ M;R!O<&5N26YD97 /2!T:&ES+F]P96Y);F1I8V5S+F9R;VYT.PT*"0D)"71H M:7,N;W!E;DEN9&EC97,N<F5M;W9E1G)O;G0H*3L-" D)"0ET:&ES+G-W87!3 M;&]T<TYO3F]T:69Y2&5A<"AI+"!O<&5N26YD97 I.PT*"0D)"71H:7,N;W!E M;&5N9W1H(#T M"0EI;G0 <F5S=6QT(#T ,#L-" D)875T;R!S=&%C:R`](&YE=R!.;V1E(2A4 M;F=T:"`M/2`Q.PT*"0D)"69O<B`H875T;R!T96UP(#T =&AI<RYG9712:6=H M="AN;V1E*3L =&5M<"`A/2!N=6QL.R!T96UP(#T =&AI<RYG971,969T*'1E M="`](&1G*&YO9&4I.PT*"0D)"6EF("AR97-U;'0I('L 8G)E86L[('T-" D) M"7T-" D)?0T*"0ER971U<FX <F5S=6QT.PT*"7T-"GT-" T*86QI87, 07)R M87E":6YA<GE4<F5E(2AI;G0I($EN=%1R964[("\O2G5S="!F;W( =&5S=&EN !9P`` ` end
Jan 13 2011
I haven't looked at your code, but I came across the idea of a vector map in C++ (based on a std::vector of std::pairs) with some performance advantages over std::map if there aren't a lot of insertions and deletions. The idea is a good one. Whether it's best as a custom store for RedBlackTree or as a separate container I don't know. The "unsorted binary tree" you mention doesn't sound right. Such a container would need to be kept sorted. On 14/01/11 15:55, %u wrote:Hi, I've noticed that, just as you can have a heap with an array-backed store, you can also have a binary search tree with the same store (although structured differently; see attachment for a bare-bones unsorted binary tree implementation -- which I have NOT yet tested, but which I can test if it will be used). The improvement will be in data locality, and while it may seem to use a bit more space than a link-based tree, I think it's worth it to let the RedBlackTree class use a custom store, such as any store that has getLeft/getRight/setLeft/setRight methods, and that uses opaque pointers. How does this idea sound? Thank you!
Jan 13 2011
The "unsorted binary tree" you mention doesn't sound right. Such acontainer would need to be kept sorted. It would, IF it was implemented the same way as a heap. But it's not. Take a look at my implementation if you get the chance; every node has four members in addition to the value, which are the indices of the (1) node (self-pointer), (2) parent, (3) left child, and (4) right child. There's no direct mapping between the place of a node in the tree and its place in the array, so there's no need to keep anything sorted. Hopefully that made sense... let me know if it doesn't. :)
Jan 13 2011
I see. It's not what I meant when I described the vector map. That has no pointers/indices stored in it. The position in the tree is implied by the index. On 14/01/11 18:21, %u wrote:The "unsorted binary tree" you mention doesn't sound right. Such acontainer would need to be kept sorted. It would, IF it was implemented the same way as a heap. But it's not. Take a look at my implementation if you get the chance; every node has four members in addition to the value, which are the indices of the (1) node (self-pointer), (2) parent, (3) left child, and (4) right child. There's no direct mapping between the place of a node in the tree and its place in the array, so there's no need to keep anything sorted. Hopefully that made sense... let me know if it doesn't. :)
Jan 14 2011
On Fri, 14 Jan 2011 00:25:17 -0500, %u <wfunction hotmail.com> wrote:Hi, I've noticed that, just as you can have a heap with an array-backed store, you can also have a binary search tree with the same store (although structured differently; see attachment for a bare-bones unsorted binary tree implementation -- which I have NOT yet tested, but which I can test if it will be used). The improvement will be in data locality, and while it may seem to use a bit more space than a link-based tree, I think it's worth it to let the RedBlackTree class use a custom store, such as any store that has getLeft/getRight/setLeft/setRight methods, and that uses opaque pointers. How does this idea sound? Thank you!Didn't look at your code exactly, but from reading this discussion, what you have implemented is basically a memory pool ;) Yes it's possible, and dcollections does this. in our discussions on bringing dcollections' red black tree to std.container, I asked if my custom allocator that uses an array for storage should be ported or not, and we decided to defer custom allocation until later. I fully expect that a custom allocation scheme will be introduced at some point in std.container. -Steve
Jan 14 2011
Didn't look at your code exactly, but from reading this discussion, what youhave implemented is basically a memory pool ;) Huh, interesting... I didn't think about it that way, but in a way, that's true. :) I just thought of it as some tree representation that did not use pointers.Yes it's possible, and dcollections does this. in our discussions on bringingdcollections' red black tree to std.container, I asked if my custom allocator that uses an array for storage should be ported or not, and we decided to defer custom allocation until later. I fully expect that a custom allocation scheme will be introduced at some point in std.container. Oh cool! So long as it's on the (probably very long!) to-do list, that's great. Thanks for letting me know. :] (By the way, if I happen to find enough time to modify the current version to allow for a custom allocator, would that be potentially of any use?)
Jan 14 2011
On Fri, 14 Jan 2011 20:57:18 -0500, %u <wfunction hotmail.com> wrote:Sure, in fact you could currently use dcollections to test it, since it allows for custom allocators ;) -SteveDidn't look at your code exactly, but from reading this discussion, what youhave implemented is basically a memory pool ;) Huh, interesting... I didn't think about it that way, but in a way, that's true. :) I just thought of it as some tree representation that did not use pointers.Yes it's possible, and dcollections does this. in our discussions on bringingdcollections' red black tree to std.container, I asked if my custom allocator that uses an array for storage should be ported or not, and we decided to defer custom allocation until later. I fully expect that a custom allocation scheme will be introduced at some point in std.container. Oh cool! So long as it's on the (probably very long!) to-do list, that's great. Thanks for letting me know. :] (By the way, if I happen to find enough time to modify the current version to allow for a custom allocator, would that be potentially of any use?)
Jan 15 2011