From 1239070d346d005782a96afe60b434472839addd Mon Sep 17 00:00:00 2001 From: Khara0 <2106107467@qq.com> Date: Mon, 21 Oct 2024 20:27:41 +0800 Subject: [PATCH] dd --- doc/MyTinySTL+泛读报告.docx | Bin 0 -> 12229 bytes .../MyTinySTL-master/.gitattributes | 63 + .../MyTinySTL-master/.gitignore | 253 ++ .../MyTinySTL-master/.travis.yml | 72 + .../MyTinySTL-master/CMakeLists.txt | 35 + .../MyTinySTL-master/License.txt | 11 + .../MSVC/MyTinySTL_VS2015.sln | 28 + .../MSVC/MyTinySTL_VS2015.vcxproj | 201 ++ .../MSVC/MyTinySTL_VS2015.vcxproj.filters | 162 + .../MyTinySTL-master/MyTinySTL/algo.h | 2744 +++++++++++++++++ .../MyTinySTL-master/MyTinySTL/algobase.h | 520 ++++ .../MyTinySTL-master/MyTinySTL/algorithm.h | 18 + .../MyTinySTL-master/MyTinySTL/alloc.h | 264 ++ .../MyTinySTL-master/MyTinySTL/allocator.h | 113 + .../MyTinySTL-master/MyTinySTL/astring.h | 18 + .../MyTinySTL-master/MyTinySTL/basic_string.h | 2075 +++++++++++++ .../MyTinySTL-master/MyTinySTL/construct.h | 85 + .../MyTinySTL-master/MyTinySTL/deque.h | 1426 +++++++++ .../MyTinySTL-master/MyTinySTL/exceptdef.h | 26 + .../MyTinySTL-master/MyTinySTL/functional.h | 285 ++ .../MyTinySTL-master/MyTinySTL/hashtable.h | 1609 ++++++++++ .../MyTinySTL-master/MyTinySTL/heap_algo.h | 227 ++ .../MyTinySTL-master/MyTinySTL/iterator.h | 366 +++ .../MyTinySTL-master/MyTinySTL/list.h | 1210 ++++++++ .../MyTinySTL-master/MyTinySTL/map.h | 549 ++++ .../MyTinySTL-master/MyTinySTL/memory.h | 208 ++ .../MyTinySTL-master/MyTinySTL/numeric.h | 155 + .../MyTinySTL-master/MyTinySTL/queue.h | 364 +++ .../MyTinySTL-master/MyTinySTL/rb_tree.h | 1738 +++++++++++ .../MyTinySTL-master/MyTinySTL/set.h | 477 +++ .../MyTinySTL-master/MyTinySTL/set_algo.h | 253 ++ .../MyTinySTL-master/MyTinySTL/stack.h | 173 ++ .../MyTinySTL-master/MyTinySTL/type_traits.h | 45 + .../MyTinySTL/uninitialized.h | 256 ++ .../MyTinySTL/unordered_map.h | 563 ++++ .../MyTinySTL/unordered_set.h | 534 ++++ .../MyTinySTL-master/MyTinySTL/util.h | 297 ++ .../MyTinySTL-master/MyTinySTL/vector.h | 936 ++++++ .../MyTinySTL-master/README.md | 101 + .../MyTinySTL-master/Test/CMakeLists.txt | 4 + .../Test/Lib/redbud/io/color.h | 351 +++ .../Test/Lib/redbud/platform.h | 108 + .../MyTinySTL-master/Test/README.md | 51 + .../Test/algorithm_performance_test.h | 108 + .../MyTinySTL-master/Test/algorithm_test.h | 1180 +++++++ .../MyTinySTL-master/Test/deque_test.h | 102 + .../MyTinySTL-master/Test/list_test.h | 118 + .../MyTinySTL-master/Test/map_test.h | 202 ++ .../MyTinySTL-master/Test/queue_test.h | 186 ++ .../MyTinySTL-master/Test/set_test.h | 166 + .../MyTinySTL-master/Test/stack_test.h | 103 + .../MyTinySTL-master/Test/string_test.h | 207 ++ .../MyTinySTL-master/Test/test.cpp | 52 + .../MyTinySTL-master/Test/test.h | 717 +++++ .../Test/unordered_map_test.h | 203 ++ .../Test/unordered_set_test.h | 191 ++ .../MyTinySTL-master/Test/vector_test.h | 114 + .../MyTinySTL-master/appveyor.yml | 21 + 58 files changed, 22644 insertions(+) create mode 100644 doc/MyTinySTL+泛读报告.docx create mode 100755 src/MyTinySTL-master/MyTinySTL-master/.gitattributes create mode 100755 src/MyTinySTL-master/MyTinySTL-master/.gitignore create mode 100755 src/MyTinySTL-master/MyTinySTL-master/.travis.yml create mode 100755 src/MyTinySTL-master/MyTinySTL-master/CMakeLists.txt create mode 100755 src/MyTinySTL-master/MyTinySTL-master/License.txt create mode 100755 src/MyTinySTL-master/MyTinySTL-master/MSVC/MyTinySTL_VS2015.sln create mode 100755 src/MyTinySTL-master/MyTinySTL-master/MSVC/MyTinySTL_VS2015.vcxproj create mode 100755 src/MyTinySTL-master/MyTinySTL-master/MSVC/MyTinySTL_VS2015.vcxproj.filters create mode 100755 src/MyTinySTL-master/MyTinySTL-master/MyTinySTL/algo.h create mode 100755 src/MyTinySTL-master/MyTinySTL-master/MyTinySTL/algobase.h create mode 100755 src/MyTinySTL-master/MyTinySTL-master/MyTinySTL/algorithm.h create mode 100755 src/MyTinySTL-master/MyTinySTL-master/MyTinySTL/alloc.h create mode 100755 src/MyTinySTL-master/MyTinySTL-master/MyTinySTL/allocator.h create mode 100755 src/MyTinySTL-master/MyTinySTL-master/MyTinySTL/astring.h create mode 100755 src/MyTinySTL-master/MyTinySTL-master/MyTinySTL/basic_string.h create mode 100755 src/MyTinySTL-master/MyTinySTL-master/MyTinySTL/construct.h create mode 100755 src/MyTinySTL-master/MyTinySTL-master/MyTinySTL/deque.h create mode 100755 src/MyTinySTL-master/MyTinySTL-master/MyTinySTL/exceptdef.h create mode 100755 src/MyTinySTL-master/MyTinySTL-master/MyTinySTL/functional.h create mode 100755 src/MyTinySTL-master/MyTinySTL-master/MyTinySTL/hashtable.h create mode 100755 src/MyTinySTL-master/MyTinySTL-master/MyTinySTL/heap_algo.h create mode 100755 src/MyTinySTL-master/MyTinySTL-master/MyTinySTL/iterator.h create mode 100755 src/MyTinySTL-master/MyTinySTL-master/MyTinySTL/list.h create mode 100755 src/MyTinySTL-master/MyTinySTL-master/MyTinySTL/map.h create mode 100755 src/MyTinySTL-master/MyTinySTL-master/MyTinySTL/memory.h create mode 100755 src/MyTinySTL-master/MyTinySTL-master/MyTinySTL/numeric.h create mode 100755 src/MyTinySTL-master/MyTinySTL-master/MyTinySTL/queue.h create mode 100755 src/MyTinySTL-master/MyTinySTL-master/MyTinySTL/rb_tree.h create mode 100755 src/MyTinySTL-master/MyTinySTL-master/MyTinySTL/set.h create mode 100755 src/MyTinySTL-master/MyTinySTL-master/MyTinySTL/set_algo.h create mode 100755 src/MyTinySTL-master/MyTinySTL-master/MyTinySTL/stack.h create mode 100755 src/MyTinySTL-master/MyTinySTL-master/MyTinySTL/type_traits.h create mode 100755 src/MyTinySTL-master/MyTinySTL-master/MyTinySTL/uninitialized.h create mode 100755 src/MyTinySTL-master/MyTinySTL-master/MyTinySTL/unordered_map.h create mode 100755 src/MyTinySTL-master/MyTinySTL-master/MyTinySTL/unordered_set.h create mode 100755 src/MyTinySTL-master/MyTinySTL-master/MyTinySTL/util.h create mode 100755 src/MyTinySTL-master/MyTinySTL-master/MyTinySTL/vector.h create mode 100755 src/MyTinySTL-master/MyTinySTL-master/README.md create mode 100755 src/MyTinySTL-master/MyTinySTL-master/Test/CMakeLists.txt create mode 100755 src/MyTinySTL-master/MyTinySTL-master/Test/Lib/redbud/io/color.h create mode 100755 src/MyTinySTL-master/MyTinySTL-master/Test/Lib/redbud/platform.h create mode 100755 src/MyTinySTL-master/MyTinySTL-master/Test/README.md create mode 100755 src/MyTinySTL-master/MyTinySTL-master/Test/algorithm_performance_test.h create mode 100755 src/MyTinySTL-master/MyTinySTL-master/Test/algorithm_test.h create mode 100755 src/MyTinySTL-master/MyTinySTL-master/Test/deque_test.h create mode 100755 src/MyTinySTL-master/MyTinySTL-master/Test/list_test.h create mode 100755 src/MyTinySTL-master/MyTinySTL-master/Test/map_test.h create mode 100755 src/MyTinySTL-master/MyTinySTL-master/Test/queue_test.h create mode 100755 src/MyTinySTL-master/MyTinySTL-master/Test/set_test.h create mode 100755 src/MyTinySTL-master/MyTinySTL-master/Test/stack_test.h create mode 100755 src/MyTinySTL-master/MyTinySTL-master/Test/string_test.h create mode 100755 src/MyTinySTL-master/MyTinySTL-master/Test/test.cpp create mode 100755 src/MyTinySTL-master/MyTinySTL-master/Test/test.h create mode 100755 src/MyTinySTL-master/MyTinySTL-master/Test/unordered_map_test.h create mode 100755 src/MyTinySTL-master/MyTinySTL-master/Test/unordered_set_test.h create mode 100755 src/MyTinySTL-master/MyTinySTL-master/Test/vector_test.h create mode 100755 src/MyTinySTL-master/MyTinySTL-master/appveyor.yml diff --git a/doc/MyTinySTL+泛读报告.docx b/doc/MyTinySTL+泛读报告.docx new file mode 100644 index 0000000000000000000000000000000000000000..480511d65c4833bd671640ba2b60351167aa7f31 GIT binary patch literal 12229 zcmb7q1yr0_vu)$0PZXGh=max{1*H){~EUSiNj=Zzi~fEwnP_MvM(IV}d(p zoUm z|8pku3T8@O}k2jt9EVr8M=&8$NeFV<5}2jqdqWM}DUXVA-^F*5LW$ciP8u=^NXH@m_KL z?N6LTUpbd68zhsdJN3o;_@g6%Zvp>f}%=pI5Y3_-h`WN{?C zDA~+nuKzm{a`li{qHmEfe2WCiKO+IOu{Zh^il{h+k3Ed&LF*8&!b2YEUyrz9te~hp z>=_pfw;}>}tZCTIB=S~Y+RWx>!}#t~G8{TQtgSD9D$I3JV1HsO5g-d!0EBboDL#UJ zu)*9UfGq<`RW&Qf=b)*xGT7MIS5Vo&mr3V$HNskMNDeDjz&YB=Dn-)q`x>%eBJTES z1IZj-OmEd$UdC^I<2lExzz4t`;9WZ9V?6H3 zj`GGi+P^q=a&WY<`o;Q}Sh+XWu|v-M*K>E)_T=W5qQ3zpIgpWH$F;u{9H^Sc#T85w zd%Ljgp(E)eWOSeH4qd${((3FY;|Er^sgif1fcnX6HMA`yZkW{~vLLI^7k$I2LnY^g zg~Ob^QMu5&ri?raLf{ozL_N;L`+=<4j#X0~8m&LtE&KS`*#W=JTE(+FMvy{#J!zv{R$ZHd5@v|ngjg&k*ezo{ zkWx5QzI*Pc{SBi31*^0`4(@?khezw(g7a3i?DM2`(8Yd0I?{H8(^nEoV&eC)XN=t% z;WeP%ArP&cPt)()7glOcVtxSYzK&!Vzx1-;v*4nkS7H-K7C0suPozA(2bZ(Te64u^ z{9^WhPCpQD%(~dv8~&DhT*9x_xZV)DCIA4^UnUNYZk9$4zld+s{-n0eiRzv0aLa#x zZ*~XLU9O)teZa+>7K<6@@v+6DeIQ;Sn8XeDF$PJEhyPJWr;5xlR{DOyXS?ZjWZvib+Q=>q z%LZlQ13=<(niKo+Do;XAJfAn^DrL8Yc^Br1GhSm9mUA>qjA%*$Vq_|2O!xMalAbo`NvG3Hqn5 zLl*BIZ(toemaHpng($Xt;^E%P_T8iOAUvwwvCoU8?AqW)YDhe2C`L(1B_$GrE?8Dc z0?5+qYzA(j7V%7Qfv>JDSqwxq2{hLS3i@f&SzY&=4O# zBdQ1wJ|f0M6=1*EvBuX(7s3k>?C@5CYsCVS({TkS5RM5VMwVwbZ1wdE*o>GYlj%3% z4ah~|;}xfIfYu<1wPm2%rV=eHJPt$5pvax0>mDwqGA*bcVpYX-n4QN&U&Lg=rp4pq zh8yBd54}+g#fwGb4M#7zD~}|Rh42JNnxM;BmeDa4@L)x$5+u0cJ{^9&6)MhK6-;JMVTRfn@rER>MlR7M@~$I* zLdk#0JDfQEjyy*(;466gO^#a25vDt^WXOAUwUAKW=KXG6PHYBD#IX6K{yl#1d>r^x zhx9s4tRPFGd7TLhl4$d4F%vn41ldvtEtFubD~#-oho`_Fcj}eV?h-3~TalScpc9GR8INFE?q9yQO0;tTniKAH2Yo_(Svd z?V&eyB};0?g#-<_;6LYp^T1(S%|JJYV`^h`U)y0Oa)oM z*5#w|e&%B|;mvwh-p+?>@FV2pxqBZS+1EV~!4TziMA+gL$&2x40zScyCvOj=h28uy z*wVFRsR`#SyB&X4bF5u=E3iF*4W1dA|xET>KG9^c09bDwua04>PIq}J+%DrJOIGCj) z9U+9QIhWwI50Ehu;bVoV&U-b#;w2tst}n@ho1LW))&w{nq*;4G9I1D%Cyr(F6&e?b zFQifY@)ieW8~5h?e09F-m+}dA+H4D!+74#ZC~Jwc zB7aTkPZx&wL`b4v`r>j4bCw0FZttH2o6bN@l4<-w!}7F9-LdM{u$s$AMdNWUJ)-w^ zcS+OY5!H&W*(>au>Uz7#rx9D-yz-kyiYe#rmE_*9uu-izL8l`|)4{4%5x9Kn+VoO)MMQh%p}Rt*G7ZP>!S#jn-@8`KDj-ik7+<}%f8 zt)^u^a}481f+KxnVvj5~-4!Uw_{M9EnQ(sb--I>1_b)$OZW%8vU%dH2sK=)W zQp!Hyt!a~!|CO?f@Y=lAtG2kc{k&z(S!cCSRlb{z0lpn)a_w-nENuQGF!@v8yxOTs z?WvxLXHYeAu2vCFXKJKs#XV1voHV(oKgdR>vjd*xQ|0OS%j>6S2H9-4ueU?L<+YVv+^~-oZN@JQf7s=jH@<9iF1#|Wb9E>cemz(5tDdOI97?6C zr>9TQ;n@I7W|QTfY<_?9t^mw=d z>0CH^qmWf2U^Rn8t~`=XJck%_J#v01uWQQZB%jGe17~K<{9_S*4!y@K6NRR)s{ZKhHLyHeEEuWhM=x34$Q4hB%pmLd2krdRXc0Uh zIR;Dp$|1vpMp3h`ySlF+|K8%q(zhA_!2tlRx1Hv%W7QuUQ3oSOM>A`aKlYjRs-KjW zInlk>Q=gG=IzoDhCo4iGL4=5;QB4V!G}a6s$yDaqf2X-wIw>= zy-ir6S(wu^ZQ6{f7#q0hs=CR@Ik4!N6z5V>1V}V!v8#%C6r7-DZu)F2?bJ2+;#an* zn8djp?k{#l&{Za60?q43yJi9ANfIJ zJ9SikBQL7d50R-T?ABhDv9PymJ;FR5NRKQ>e!_ANc@p7a?3H&pqVhg2?NkQ6&kp9F;;d{*Oq4t6CY`Lmg3^rR;v>W#;Vh1P zpZONuYakwwl0$?qJ}HT3o<0H(s+<^3xVK!pEq6D@-Kc=yUN#ovM|KOljBo=1tTj<* z)i-#6$0BLzp{0!bQhI*2zR?EfTlJ+$JWlr%E(Op)f|3SR2Lu3wj;w8F!Nfnz<8 z4SA#zYmuBEd`+X!{K0@EB*{LERevy-t*Rqlj>D2?RpOy8BbzqsYV3K8)f1Ot!N7q@ z-STwbUk)lF9imNFw$$h6>YmwEY6V}6*tf6PIBM$yJwG@~!Ipclc3}8Hp7$o|yUg46 z9C;6X_Fu1ZK`fA64YPBhoV@pBok_S?WTr7T!}1DP8jvt_{KUhSbQCvlV2F-7Kgwvm z*I7K_4%!Q>hOur`n<4AUhnF;fFU3t73)5_9j0$pBO6xj2^)+h3ok93+zL}>Ij$Sd% zr^SiS?y9_zX3sEhgzCZI7c&NjVSoKBtI?_RDT|u|ty19J*am~A?6;d3!w;s80h%ElWfd=iis`hP z98eY;(WbNbnv2!R1P#odotdjuiJ7j8k~BOw%ul@~dH5VEOw`{b#9vHzX@*kDh+1yC z70#u0!sQvZlncs60Z`zD>T;r%=U@}6jnA~auSoy<(HQQpjO1u)WM%Z*0eQ6^_YxKo z0BFGm05JY-_=h>uuVeCw##js*2YQFv;VWYr&oS8!P$O0}J;n&GrHTZkcWQ`}#rVVa zptJK(xj*oWl#1D`aIE`Lu6YEwBExm%Vp7Q$)K{VGlc8SOjEbBhq0kIt-j2H`KJT-i zq{;N_6Q;J2O+>UdL5Wui*c+a`25}VS=W}{@E5_K+VVBqnN!zNNJtVEI&llp!lS$Hc z!C;>!`Y_FdiWB0?qY#+<^~uI-Va7L?Q!d~oU3Z7XMyFu*$M(h8!g29%NZhb@D8cGo z5Fa;hwM=6Cx3pl{81q^yS+~gbJe3u)`=lKyk)lzof^v9_DZo5+gF!@vx(q{~6ctJPO0JQs-#K15qbHQR*@u!x3Etug%?$o){>0*LrSTS<^C2w*iMPyba8R;JE>5|GYZ6mz&V_{)l}6aSSs;=# zbx_sS$v+1fQ&acD>&5I#aConea@o(fN6Fqq%9Gt0Si1Z_w-@8F);(W-AjR;W6GR8IdkQeq`XAksH4ZV` zN{jc^<0Jh%l7v?ju?)-PMWGZo$BcQ&k|wym!O0s8umE!SH*h&3zdIkk&H~!@C={DyNUwwabT0(+&GM)5NAbEbb)WPgFf1!`B;+hZE$T4qaWQL-AiM=aVT z0yAC>Kf~c1SUu3v63A)yfrxY*9B*WU9%d=jRhXGbI79|6_d}eZjxiq?@w%)fqBWG2 zn3s;rMRi1AiNFl-37|v~sWz#cH(F@#%WMwi`EF>&#L%Z-oV|jA%#gb)0iq2XZZp2A zt4o*WU_Qt1e%f2WBsF3u4*#d)DQUl@VKRY}VuFn40^g7l-eVXiXn5YnXUTU@zD*c; zYs5&Dy6LCO;5-L>EqE*bYi8+nM4=DNyIEQ~U89>eK4JsVN2*|6s|O1>Llc(k#=#Bq zjkzlA_qWvpr!MtIXSQ4Ascm1x+7KI7vUnl~c2>{EwOPlIn9zFq{z!9?*k9DjQa37<`3E4 zQ{z_3O=cHcfpgqZ7k|0#8DopVIigC}}-7R%nJe-1BTD<@G6cn^_lT z?{&dw$rnKfbwSH$Zeq&<&r@WGWQ9(YkYzRyfn-fXN9pHA-9g7Bv1w%%)Ty(?q^MWE zab+0RY51wVlUhol=uyqH87m|zxO5SK7Dl`gTayjwQKuliU!5tMDY}HgMF=ji6>^oCig$;LXK$K&K`x|I`y$c51@mB%m>@@H|FCjpmp!+!!uxo4+zg1 z*Q+`BlnxIW`Sg`xWYK7vDD(+)`qMpHQ=dlB(G%$Ij3_J9i|y??DeA8;7eo6x zP%AsXC&D&@!ETK9G#l4&v%OM8wn!=ZGWj*P_B65Hc%jPKi}#a+8(6Z=cgp6X@0Q$o z0++sh#*KON<#~IDfGnMsPrO+@TU{{t^_o{(urwL?;(O>t(-T1&8&Y` z4;KMeI8#}_w$lOdhLsa}l51Sb*PDD-m@V{8dDmaezU{xFA3yrAw?b)ug}W{^KuSob%soRLFr#EKzq8h zNL#VL8Wjg%iSzW-aT1~s`aAk1E$XxP4#yKMFR7sQ+^Lh0{9wayS674f*&>HceKpq& zl__mB(YgGxF4CD&tz;;a12!QEEVFHiv`K{gh+kUFdhtb6I#9UYPN8ehGOeKC)JrT#G#y{sH+;xp5MC@A1W2eBV zZ=yUVO48Y=(C6a}dxbk+IKVKC^~OK0R)1FQ7}!2$35J#v1@?aC#W5%sOaOt!Atvdn8Nh2Xg1@0Fj?KOjy5K zJ@*u;ot6_~)~(WNN}5xcWLLOkN%H}lhH_2#^$(a+d+ssP<}Ja#9iI_8vQ{+R481~W zS}dk0YJ!%3Qux-fJUe@aXBklABu(W+Q@8_^dLiJZr0z2+dF=vAj}lt+vid2#?B+MF zXzCLNdd;srfrOK*1g|)eQU%!b%k?%05!K9ia%}SrXLt>jIZCub7G;;08JK(`OwyI5 z`APD0SgnCvoM@cTO~br5?Ic8{R#zVx$FIV%cfP)fcYPMe?f*Zs*78cx#j=3RM$ zP_arvwnDhw@Y+S|HrE%r(b5AX*SVEyGnU{bS8z&cKj~Kg{P;s@$gu&1Z@%AHi15b} zXPv5OQ@Ca86k(wbg+wO^slJeLuL_w>QWX2}hIGx?8lr!dml|;~7M*8u1bxgPLOV*- zX7$k0t}HqLD|gJLCsb+RD_Q)=E7@Mqk*P?n;g}GJfvjGwyseGe7r%eQr|J2{IwSX< zmJ+5m6;QD|(~Hi%G$k8%I6_ubl9^oh9mMpDw#|N%iaH{+U{H*dw~S0VB}Yq@YRLp1x+Vo%sz%LqM7H!IsDnh-J?7BTeo&3#2m3mu_MR8#ql}8gGFAc-Rl))QY^(@ zt0Ib+Y&Jv*Uog}d$n@gVlYCD?qmjck1n0n`6iqF&&q)HcO15xoh2y#h4rg`s>tQqe z26|4Ctgk5aowl>}ptrc^IWr}S?)hz?GN_bHrSx6`M|R{LV5lY4^>flAo3<_5h=pwk z>PtM7C;O1(;fJD<9chAn4ZcN^_y_Pep^2}kIFNJd%F}R$&^clsk_wIgm}i2wo`ChoD`5&jjE5hTIO|K9PI^&Au_3 zk;!!`GdDM2f=s!P?#JX24tYm`n(B3rh=uJUFBoFS@_{*+);MG%uIpl5*@Ue*_GbZ` z!s00?BtW)6=-$RKV@(w+3K75$C$Ddvh;mymUNdN45)@5S60o(Sk5Hzx)pR4VfNNgC z*I-pOGKFa10AfxipiPj!SjzLw$o>o> zM*FS^%VD2gq3Qw4N>6qOt*si(z6Whb^oQeD3!pX<71gP!JGmdC0EG}TP8bRW_D6;r zD_p>bv<&JyRNyQ_&gI80zW8ByOM@V0@}r=zeb-`d!AhQl3P z%q9>UAe%T$e$G+u3W|VlNxYb9Zi&lb*f|P+W`-S&!&4@G-R>ab zT7(JxiM>xap=7hzx7VKVAzb;NyBw0X_kzFj@AutBJ>{J0Yz%|-;zps4Qi~;iY!q7M zfm|VqxgTycb8@*u;9hxQ@0F>MZ_RP%A5+H}B9%^KU9#gO!nGi;gZoIa3i$F=^MI&^ zGuu?)jT)jYYGOp^VR~xyLf?jMXkf512|6vyQFjAmL8D4Lk2gSi(9}FYr$xY+AB=RZ zaFl-bYGxa^LqxoGdCVxVN9ky<%xqTSZcZxYZJUa+o?cN9!y_ zFvpDr1df#X^D6sQ@h;0?q5u&whARXjOs29r=7Ff7A0$}9cZ_iD9>(WO2-ZBlbra9X zu9$67c~h1M<{e^MzTQq481WF|#rpx$_87#-`25hN1rU1mcar1pB9roa!40o^fsXrX z*eF5UdY?G>B!hr(ji;9avlbcN(D`zvC|Sd;fQd|5pja#cK|nr2`hfWg;uSOg#!5RP z6Dfkt05NOh0*%o(858PXWe{TNY>*2|2@tyuf-z}L`X!||!a5{T?b zbCL;{&_7Hw8=+xH`X%H)Abh}h7U!4W;W)|d*pI8*=1hXelMw0(u3OUnoS(XQHDZ$o zdz!+oH3T0Ej0AlT$F^yomOIh#Qz0C5TAnL6F^*Ok&UkXSZ<*uANtJR96UfX*7Ie{I zV;Lo+o=J3;_eET)Z1Lwc%9@jqgg30{%08L%;z6ivR`)4ttr~$S{e`BBVrSE$iR26m zJSw9Q@lmBnY^6E*amM`?wTE-3)8#7eiWVx2z>U$o%V+T2%Up!823!~&QzPX?{2qOw zj{M1Q{`UT>nMLwM;hT@e%4yLwofYIv&FY|7b;6Pm;5JQq@9#U8Hu6!Gn*-CNjIjMO zcr=Zm#ceaU(0DtUo=6%a6ij(ASV|Bq2vMt%l9kWRtHaIb=Xd8@sfc_{Nqbm1^I-S6NGvzjL7_DenMQ^s!$-IBr7%Y(Fg4`jrl=eYp6DP1!oC; z3VnLMd7gNlAS8kY_<;awnz{WXb&DzLmZBHqyzWqh zxO=`cWC5l(oa_({@<6DoZUy_*fL~|@06rDa$-Mcm9Pil_6-X5(paqMYD3Uq?t4;! z0c<1pM6%Fq`kH)DR9lHQW%U=J1^0Exz*)LzkWpAr0CEO^iNsavsVPe~N;YCY9k*rm zyW#>*H;qScsH$g~8xpBK2YV(zfWuuo&%u-M6qV?Vf*u5nEj%7fyIXcsCbs*1LAduEeyPlrKw2gd-{+ytw0*d!GM z|5n8Q2idNxQ++!)5*GIW;q!tG5ghih-M)t~$Q|Yc54>7RdOn){)a}d!jk_I2HR3pi zOm?ymt>KxWQ1=*uAr%*nL7PB^RXX%e^C0Q0P#NJjV#N7 zFV)L8f20qV>t4ST{_cFo;&v02+K&ydED8e~5OIR-4t6$nw2DS)fTwu`6aZsEJw9Ac zKf!Y!xeNXBLYSoh&jMuYFr^AO}FwQ#8c z^0M6vFgq$4_j(tt&B5&%c52bxiACaw1;%mPlb^D*LW;+k1WOFzg|p=?1D&*)0iac6 zuyKmguYC_jTw9j%vS(YQC0wK`y0JLIM1Un2!Pk3K`&jaO2KF41^fq{t$)Ud~xqivy zJ_)~N-?uV?uCkl0k%RWHYC?U&h;=t3vglpn15#{*iot$f2{mX0UlJYM14so6NU8S_ zi~RkgET}#Rx|9M(Eb8(d{<=D0WYV}XoP?=AgJ{Qo7EOLtDMfIM=UXwE)^bc zf&m1jSkF;ummvlSi_S?kI!oR?5&0nwXOL*Cq;x@&8zeD?iRm!XBxJy=KLL~)u|-!1p!!%*DZr} zZq&i&nzrfSH?=4TC_3Qp0?+S3d5a4G1VHrmC{6u8hUm`=yp@FB#_tN@Uzz65@k<2U zNby%r`Q7R7ndcYgPp2#Yh56$?`M){)B}e{q{Brhd{6n1l??wJDPyS{6r@uFMf5ZMG zR{njqze{TWMpyq5+Ww`8{!3u{JN$Qb=-+U1uz$k;ODp<+Tl6mxv(*Kb} z{#x+=9F$*4>(B8E0!sC-%=G(Ye@|k+fPXSY^KamPOKHDf>G#Uv-&X?Q{$~pRyvFbF z-?wXj!-vWK1OM0N?RWg|4g0_G&~GZy|JJ_$9sawj^ly0HU!4D~G5r(#|H6LSTi*M_ q_g{^=e}7MZZ`J+nwddc!zZ-Y*A0hs@>yY1c_mgkmr*)cNp#KAM + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + {E88807F6-B07C-4371-BD38-FB1569F894E4} + Win32Proj + MyTinySTL + 8.1 + MyTinySTL + + + + Application + true + v140 + Unicode + + + Application + false + v140 + true + Unicode + + + Application + true + v140 + Unicode + + + Application + false + v140 + true + Unicode + + + + + + + + + + + + + + + + + + + + + true + + + true + + + false + + + false + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + + + + + + + Level4 + Disabled + _DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + true + true + + + + + Level4 + + + MaxSpeed + true + true + NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + true + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/MyTinySTL-master/MyTinySTL-master/MSVC/MyTinySTL_VS2015.vcxproj.filters b/src/MyTinySTL-master/MyTinySTL-master/MSVC/MyTinySTL_VS2015.vcxproj.filters new file mode 100755 index 0000000..aea4c50 --- /dev/null +++ b/src/MyTinySTL-master/MyTinySTL-master/MSVC/MyTinySTL_VS2015.vcxproj.filters @@ -0,0 +1,162 @@ + + + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {ec314ff3-dcde-4cac-a63a-4f6827750d0a} + + + {c6f24d77-e6f0-439e-954a-c0ca577689d5} + + + + + include + + + include + + + include + + + include + + + include + + + include + + + include + + + include + + + include + + + include + + + include + + + include + + + include + + + include + + + include + + + include + + + include + + + include + + + include + + + include + + + include + + + include + + + include + + + include + + + include + + + include + + + test + + + test + + + test + + + test + + + test + + + test + + + test + + + test + + + test + + + test + + + test + + + test + + + test + + + test\Lib + + + test\Lib + + + include + + + include + + + include + + + + + test + + + \ No newline at end of file diff --git a/src/MyTinySTL-master/MyTinySTL-master/MyTinySTL/algo.h b/src/MyTinySTL-master/MyTinySTL-master/MyTinySTL/algo.h new file mode 100755 index 0000000..b9d9660 --- /dev/null +++ b/src/MyTinySTL-master/MyTinySTL-master/MyTinySTL/algo.h @@ -0,0 +1,2744 @@ +#ifndef MYTINYSTL_ALGO_H_ +#define MYTINYSTL_ALGO_H_ + +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable : 4244) +#endif + +// 这个头文件包含了 mystl 的一系列算法 + +#include +#include + +#include "algobase.h" +#include "memory.h" +#include "heap_algo.h" +#include "functional.h" + +namespace mystl +{ + +/*****************************************************************************************/ +// all_of +// 检查[first, last)内是否全部元素都满足一元操作 unary_pred 为 true 的情况,满足则返回 true +/*****************************************************************************************/ +template +bool all_of(InputIter first, InputIter last, UnaryPredicate unary_pred) +{ + for (; first != last; ++first) + { + if (!unary_pred(*first)) + return false; + } + return true; +} + +/*****************************************************************************************/ +// any_of +// 检查[first, last)内是否存在某个元素满足一元操作 unary_pred 为 true 的情况,满足则返回 true +/*****************************************************************************************/ +template +bool any_of(InputIter first, InputIter last, UnaryPredicate unary_pred) +{ + for (; first != last; ++first) + { + if (unary_pred(*first)) + return true; + } + return false; +} + +/*****************************************************************************************/ +// none_of +// 检查[first, last)内是否全部元素都不满足一元操作 unary_pred 为 true 的情况,满足则返回 true +/*****************************************************************************************/ +template +bool none_of(InputIter first, InputIter last, UnaryPredicate unary_pred) +{ + for (; first != last; ++first) + { + if (unary_pred(*first)) + return false; + } + return true; +} + +/*****************************************************************************************/ +// count +// 对[first, last)区间内的元素与给定值进行比较,缺省使用 operator==,返回元素相等的个数 +/*****************************************************************************************/ +template +size_t count(InputIter first, InputIter last, const T& value) +{ + size_t n = 0; + for (; first != last; ++first) + { + if (*first == value) + ++n; + } + return n; +} + +/*****************************************************************************************/ +// count_if +// 对[first, last)区间内的每个元素都进行一元 unary_pred 操作,返回结果为 true 的个数 +/*****************************************************************************************/ +template +size_t count_if(InputIter first, InputIter last, UnaryPredicate unary_pred) +{ + size_t n = 0; + for (; first != last; ++first) + { + if (unary_pred(*first)) + ++n; + } + return n; +} + +/*****************************************************************************************/ +// find +// 在[first, last)区间内找到等于 value 的元素,返回指向该元素的迭代器 +/*****************************************************************************************/ +template +InputIter +find(InputIter first, InputIter last, const T& value) +{ + while (first != last && *first != value) + ++first; + return first; +} + +/*****************************************************************************************/ +// find_if +// 在[first, last)区间内找到第一个令一元操作 unary_pred 为 true 的元素并返回指向该元素的迭代器 +/*****************************************************************************************/ +template +InputIter +find_if(InputIter first, InputIter last, UnaryPredicate unary_pred) +{ + while (first != last && !unary_pred(*first)) + ++first; + return first; +} + +/*****************************************************************************************/ +// find_if_not +// 在[first, last)区间内找到第一个令一元操作 unary_pred 为 false 的元素并返回指向该元素的迭代器 +/*****************************************************************************************/ +template +InputIter +find_if_not(InputIter first, InputIter last, UnaryPredicate unary_pred) +{ + while (first != last && unary_pred(*first)) + ++first; + return first; +} + +/*****************************************************************************************/ +// search +// 在[first1, last1)中查找[first2, last2)的首次出现点 +/*****************************************************************************************/ +template +ForwardIter1 +search(ForwardIter1 first1, ForwardIter1 last1, + ForwardIter2 first2, ForwardIter2 last2) +{ + auto d1 = mystl::distance(first1, last1); + auto d2 = mystl::distance(first2, last2); + if (d1 < d2) + return last1; + auto current1 = first1; + auto current2 = first2; + while (current2 != last2) + { + if (*current1 == *current2) + { + ++current1; + ++current2; + } + else + { + if (d1 == d2) + { + return last1; + } + else + { + current1 = ++first1; + current2 = first2; + --d1; + } + } + } + return first1; +} + +// 重载版本使用函数对象 comp 代替比较操作 +template +ForwardIter1 +search(ForwardIter1 first1, ForwardIter1 last1, + ForwardIter2 first2, ForwardIter2 last2, Compared comp) +{ + auto d1 = mystl::distance(first1, last1); + auto d2 = mystl::distance(first2, last2); + if (d1 < d2) + return last1; + auto current1 = first1; + auto current2 = first2; + while (current2 != last2) + { + if (comp(*current1, *current2)) + { + ++current1; + ++current2; + } + else + { + if (d1 == d2) + { + return last1; + } + else + { + current1 = ++first1; + current2 = first2; + --d1; + } + } + } + return first1; +} + +/*****************************************************************************************/ +// search_n +// 在[first, last)中查找连续 n 个 value 所形成的子序列,返回一个迭代器指向该子序列的起始处 +/*****************************************************************************************/ +template +ForwardIter +search_n(ForwardIter first, ForwardIter last, Size n, const T& value) +{ + if (n <= 0) + { + return first; + } + else + { + first = mystl::find(first, last, value); + while (first != last) + { + auto m = n - 1; + auto i = first; + ++i; + while (i != last && m != 0 && *i == value) + { + ++i; + --m; + } + if (m == 0) + { + return first; + } + else + { + first = mystl::find(i, last, value); + } + } + return last; + } +} + +// 重载版本使用函数对象 comp 代替比较操作 +template +ForwardIter +search_n(ForwardIter first, ForwardIter last, + Size n, const T& value, Compared comp) +{ + if (n <= 0) + { + return first; + } + else + { + while (first != last) + { + if (comp(*first, value)) + break; + ++first; + } + while (first != last) + { + auto m = n - 1; + auto i = first; + ++i; + while (i != last && m != 0 && comp(*i, value)) + { + ++i; + --m; + } + if (m == 0) + { + return first; + } + else + { + while (i != last) + { + if (comp(*i, value)) + break; + ++i; + } + first = i; + } + } + return last; + } +} + +/*****************************************************************************************/ +// find_end +// 在[first1, last1)区间中查找[first2, last2)最后一次出现的地方,若不存在返回 last1 +/*****************************************************************************************/ +// find_end_dispatch 的 forward_iterator_tag 版本 +template +ForwardIter1 +find_end_dispatch(ForwardIter1 first1, ForwardIter1 last1, + ForwardIter2 first2, ForwardIter2 last2, + forward_iterator_tag, forward_iterator_tag) +{ + if (first2 == last2) + { + return last1; + } + else + { + auto result = last1; + while (true) + { + // 利用 search 查找某个子序列的首次出现点,找不到则返回 last1 + auto new_result = mystl::search(first1, last1, first2, last2); + if (new_result == last1) + { + return result; + } + else + { + result = new_result; + first1 = new_result; + ++first1; + } + } + } +} + +// find_end_dispatch 的 bidirectional_iterator_tag 版本 +template +BidirectionalIter1 +find_end_dispatch(BidirectionalIter1 first1, BidirectionalIter1 last1, + BidirectionalIter2 first2, BidirectionalIter2 last2, + bidirectional_iterator_tag, bidirectional_iterator_tag) +{ + typedef reverse_iterator reviter1; + typedef reverse_iterator reviter2; + reviter1 rlast1(first1); + reviter2 rlast2(first2); + reviter1 rresult = mystl::search(reviter1(last1), rlast1, reviter2(last2), rlast2); + if (rresult == rlast1) + { + return last1; + } + else + { + auto result = rresult.base(); + mystl::advance(result, -mystl::distance(first2, last2)); + return result; + } +} + +template +ForwardIter1 +find_end(ForwardIter1 first1, ForwardIter1 last1, + ForwardIter2 first2, ForwardIter2 last2) +{ + typedef typename iterator_traits::iterator_category Category1; + typedef typename iterator_traits::iterator_category Category2; + return mystl::find_end_dispatch(first1, last1, first2, last2, Category1(), Category2()); +} + +// 重载版本使用函数对象 comp 代替比较操作 +// find_end_dispatch 的 forward_iterator_tag 版本 +template +ForwardIter1 +find_end_dispatch(ForwardIter1 first1, ForwardIter1 last1, + ForwardIter2 first2, ForwardIter2 last2, + forward_iterator_tag, forward_iterator_tag, Compared comp) +{ + if (first2 == last2) + { + return last1; + } + else + { + auto result = last1; + while (true) + { + // 利用 search 查找某个子序列的首次出现点,找不到则返回 last1 + auto new_result = mystl::search(first1, last1, first2, last2, comp); + if (new_result == last1) + { + return result; + } + else + { + result = new_result; + first1 = new_result; + ++first1; + } + } + } +} + +// find_end_dispatch 的 bidirectional_iterator_tag 版本 +template +BidirectionalIter1 +find_end_dispatch(BidirectionalIter1 first1, BidirectionalIter1 last1, + BidirectionalIter2 first2, BidirectionalIter2 last2, + bidirectional_iterator_tag, bidirectional_iterator_tag, Compared comp) +{ + typedef reverse_iterator reviter1; + typedef reverse_iterator reviter2; + reviter1 rlast1(first1); + reviter2 rlast2(first2); + reviter1 rresult = mystl::search(reviter1(last1), rlast1, reviter2(last2), rlast2, comp); + if (rresult == rlast1) + { + return last1; + } + else + { + auto result = rresult.base(); + mystl::advance(result, -mystl::distance(first2, last2)); + return result; + } +} + +template +ForwardIter1 +find_end(ForwardIter1 first1, ForwardIter1 last1, + ForwardIter2 first2, ForwardIter2 last2, Compared comp) +{ + typedef typename iterator_traits::iterator_category Category1; + typedef typename iterator_traits::iterator_category Category2; + return mystl::find_end_dispatch(first1, last1, first2, last2, Category1(), Category2(), comp); +} + +/*****************************************************************************************/ +// find_first_of +// 在[first1, last1)中查找[first2, last2)中的某些元素,返回指向第一次出现的元素的迭代器 +/*****************************************************************************************/ +template +InputIter +find_first_of(InputIter first1, InputIter last1, + ForwardIter first2, ForwardIter last2) +{ + for (; first1 != last1; ++first1) + { + for (auto iter = first2; iter != last2; ++iter) + { + if (*first1 == *iter) + return first1; + } + } + return last1; +} + +// 重载版本使用函数对象 comp 代替比较操作 +template +InputIter +find_first_of(InputIter first1, InputIter last1, + ForwardIter first2, ForwardIter last2, Compared comp) +{ + for (; first1 != last1; ++first1) + { + for (auto iter = first2; iter != last2; ++iter) + { + if (comp(*first1, *iter)) + return first1; + } + } + return last1; +} + +/*****************************************************************************************/ +// for_each +// 使用一个函数对象 f 对[first, last)区间内的每个元素执行一个 operator() 操作,但不能改变元素内容 +// f() 可返回一个值,但该值会被忽略 +/*****************************************************************************************/ +template +Function for_each(InputIter first, InputIter last, Function f) +{ + for (; first != last; ++first) + { + f(*first); + } + return f; +} + +/*****************************************************************************************/ +// adjacent_find +// 找出第一对匹配的相邻元素,缺省使用 operator== 比较,如果找到返回一个迭代器,指向这对元素的第一个元素 +/*****************************************************************************************/ +template +ForwardIter adjacent_find(ForwardIter first, ForwardIter last) +{ + if (first == last) return last; + auto next = first; + while (++next != last) + { + if (*first == *next) return first; + first = next; + } + return last; +} + +// 重载版本使用函数对象 comp 代替比较操作 +template +ForwardIter adjacent_find(ForwardIter first, ForwardIter last, Compared comp) +{ + if (first == last) return last; + auto next = first; + while (++next != last) + { + if (comp(*first, *next)) return first; + first = next; + } + return last; +} + +/*****************************************************************************************/ +// lower_bound +// 在[first, last)中查找第一个不小于 value 的元素,并返回指向它的迭代器,若没有则返回 last +/*****************************************************************************************/ +// lbound_dispatch 的 forward_iterator_tag 版本 +template +ForwardIter +lbound_dispatch(ForwardIter first, ForwardIter last, + const T& value, forward_iterator_tag) +{ + auto len = mystl::distance(first, last); + auto half = len; + ForwardIter middle; + while (len > 0) + { + half = len >> 1; + middle = first; + mystl::advance(middle, half); + if (*middle < value) + { + first = middle; + ++first; + len = len - half - 1; + } + else + { + len = half; + } + } + return first; +} + +// lbound_dispatch 的 random_access_iterator_tag 版本 +template +RandomIter +lbound_dispatch(RandomIter first, RandomIter last, + const T& value, random_access_iterator_tag) +{ + auto len = last - first; + auto half = len; + RandomIter middle; + while (len > 0) + { + half = len >> 1; + middle = first + half; + if (*middle < value) + { + first = middle + 1; + len = len - half - 1; + } + else + { + len = half; + } + } + return first; +} + +template +ForwardIter +lower_bound(ForwardIter first, ForwardIter last, const T& value) +{ + return mystl::lbound_dispatch(first, last, value, iterator_category(first)); +} + +// 重载版本使用函数对象 comp 代替比较操作 +// lbound_dispatch 的 forward_iterator_tag 版本 +template +ForwardIter +lbound_dispatch(ForwardIter first, ForwardIter last, + const T& value, forward_iterator_tag, Compared comp) +{ + auto len = mystl::distance(first, last); + auto half = len; + ForwardIter middle; + while (len > 0) + { + half = len >> 1; + middle = first; + mystl::advance(middle, half); + if (comp(*middle, value)) + { + first = middle; + ++first; + len = len - half - 1; + } + else + { + len = half; + } + } + return first; +} + +// lbound_dispatch 的 random_access_iterator_tag 版本 +template +RandomIter +lbound_dispatch(RandomIter first, RandomIter last, + const T& value, random_access_iterator_tag, Compared comp) +{ + auto len = last - first; + auto half = len; + RandomIter middle; + while (len > 0) + { + half = len >> 1; + middle = first + half; + if (comp(*middle, value)) + { + first = middle + 1; + len = len - half - 1; + } + else + { + len = half; + } + } + return first; +} + +template +ForwardIter +lower_bound(ForwardIter first, ForwardIter last, const T& value, Compared comp) +{ + return mystl::lbound_dispatch(first, last, value, iterator_category(first), comp); +} + +/*****************************************************************************************/ +// upper_bound +// 在[first, last)中查找第一个大于value 的元素,并返回指向它的迭代器,若没有则返回 last +/*****************************************************************************************/ +// ubound_dispatch 的 forward_iterator_tag 版本 +template +ForwardIter +ubound_dispatch(ForwardIter first, ForwardIter last, + const T& value, forward_iterator_tag) +{ + auto len = mystl::distance(first, last); + auto half = len; + ForwardIter middle; + while (len > 0) + { + half = len >> 1; + middle = first; + mystl::advance(middle, half); + if (value < *middle) + { + len = half; + } + else + { + first = middle; + ++first; + len = len - half - 1; + } + } + return first; +} + +// ubound_dispatch 的 random_access_iterator_tag 版本 +template +RandomIter +ubound_dispatch(RandomIter first, RandomIter last, + const T& value, random_access_iterator_tag) +{ + auto len = last - first; + auto half = len; + RandomIter middle; + while (len > 0) + { + half = len >> 1; + middle = first + half; + if (value < *middle) + { + len = half; + } + else + { + first = middle + 1; + len = len - half - 1; + } + } + return first; +} + +template +ForwardIter +upper_bound(ForwardIter first, ForwardIter last, const T& value) +{ + return mystl::ubound_dispatch(first, last, value, iterator_category(first)); +} + +// 重载版本使用函数对象 comp 代替比较操作 +// ubound_dispatch 的 forward_iterator_tag 版本 +template +ForwardIter +ubound_dispatch(ForwardIter first, ForwardIter last, + const T& value, forward_iterator_tag, Compared comp) +{ + auto len = mystl::distance(first, last); + auto half = len; + ForwardIter middle; + while (len > 0) + { + half = len >> 1; + middle = first; + mystl::advance(middle, half); + if (comp(value, *middle)) + { + len = half; + } + else + { + first = middle; + ++first; + len = len - half - 1; + } + } + return first; +} + +// ubound_dispatch 的 random_access_iterator_tag 版本 +template +RandomIter +ubound_dispatch(RandomIter first, RandomIter last, + const T& value, random_access_iterator_tag, Compared comp) +{ + auto len = last - first; + auto half = len; + RandomIter middle; + while (len > 0) + { + half = len >> 1; + middle = first + half; + if (comp(value, *middle)) + { + len = half; + } + else + { + first = middle + 1; + len = len - half - 1; + } + } + return first; +} + +template +ForwardIter +upper_bound(ForwardIter first, ForwardIter last, const T& value, Compared comp) +{ + return mystl::ubound_dispatch(first, last, value, iterator_category(first), comp); +} + +/*****************************************************************************************/ +// binary_search +// 二分查找,如果在[first, last)内有等同于 value 的元素,返回 true,否则返回 false +/*****************************************************************************************/ +template +bool binary_search(ForwardIter first, ForwardIter last, const T& value) +{ + auto i = mystl::lower_bound(first, last, value); + return i != last && !(value < *i); +} + +// 重载版本使用函数对象 comp 代替比较操作 +template +bool binary_search(ForwardIter first, ForwardIter last, const T& value, Compared comp) +{ + auto i = mystl::lower_bound(first, last, value); + return i != last && !comp(value, *i); +} + +/*****************************************************************************************/ +// equal_range +// 查找[first,last)区间中与 value 相等的元素所形成的区间,返回一对迭代器指向区间首尾 +// 第一个迭代器指向第一个不小于 value 的元素,第二个迭代器指向第一个大于 value 的元素 +/*****************************************************************************************/ +// erange_dispatch 的 forward_iterator_tag 版本 +template +mystl::pair +erange_dispatch(ForwardIter first, ForwardIter last, + const T& value, forward_iterator_tag) +{ + auto len = mystl::distance(first, last); + auto half = len; + ForwardIter middle, left, right; + while (len > 0) + { + half = len >> 1; + middle = first; + mystl::advance(middle, half); + if (*middle < value) + { + first = middle; + ++first; + len = len - half - 1; + } + else if (value < *middle) + { + len = half; + } + else + { + left = mystl::lower_bound(first, last, value); + mystl::advance(first, len); + right = mystl::upper_bound(++middle, first, value); + return mystl::pair(left, right); + } + } + return mystl::pair(last, last); +} + +// erange_dispatch 的 random_access_iterator_tag 版本 +template +mystl::pair +erange_dispatch(RandomIter first, RandomIter last, + const T& value, random_access_iterator_tag) +{ + auto len = last - first; + auto half = len; + RandomIter middle, left, right; + while (len > 0) + { + half = len >> 1; + middle = first + half; + if (*middle < value) + { + first = middle + 1; + len = len - half - 1; + } + else if (value < *middle) + { + len = half; + } + else + { + left = mystl::lower_bound(first, middle, value); + right = mystl::upper_bound(++middle, first + len, value); + return mystl::pair(left, right); + } + } + return mystl::pair(last, last); +} + +template +mystl::pair +equal_range(ForwardIter first, ForwardIter last, const T& value) +{ + return mystl::erange_dispatch(first, last, value, iterator_category(first)); +} + +// 重载版本使用函数对象 comp 代替比较操作 +// erange_dispatch 的 forward iterator 版本 +template +mystl::pair +erange_dispatch(ForwardIter first, ForwardIter last, + const T& value, forward_iterator_tag, Compared comp) +{ + auto len = mystl::distance(first, last); + auto half = len; + ForwardIter middle, left, right; + while (len > 0) + { + half = len >> 1; + middle = first; + mystl::advance(middle, half); + if (comp(*middle, value)) + { + first = middle; + ++first; + len = len - half - 1; + } + else if (comp(value, *middle)) + { + len = half; + } + else + { + left = mystl::lower_bound(first, last, value, comp); + mystl::advance(first, len); + right = mystl::upper_bound(++middle, first, value, comp); + return mystl::pair(left, right); + } + } + return mystl::pair(last, last); +} + +// erange_dispatch 的 random access iterator 版本 +template +mystl::pair +erange_dispatch(RandomIter first, RandomIter last, + const T& value, random_access_iterator_tag, Compared comp) +{ + auto len = last - first; + auto half = len; + RandomIter middle, left, right; + while (len > 0) + { + half = len >> 1; + middle = first + half; + if (comp(*middle, value)) + { + first = middle + 1; + len = len - half - 1; + } + else if (comp(value, *middle)) + { + len = half; + } + else + { + left = mystl::lower_bound(first, middle, value, comp); + right = mystl::upper_bound(++middle, first + len, value, comp); + return mystl::pair(left, right); + } + } + return mystl::pair(last, last); +} + +template +mystl::pair +equal_range(ForwardIter first, ForwardIter last, const T& value, Compared comp) +{ + return mystl::erange_dispatch(first, last, value, iterator_category(first), comp); +} + +/*****************************************************************************************/ +// generate +// 将函数对象 gen 的运算结果对[first, last)内的每个元素赋值 +/*****************************************************************************************/ +template +void generate(ForwardIter first, ForwardIter last, Generator gen) +{ + for (; first != last; ++first) + { + *first = gen(); + } +} + +/*****************************************************************************************/ +// generate_n +// 用函数对象 gen 连续对 n 个元素赋值 +/*****************************************************************************************/ +template +void generate_n(ForwardIter first, Size n, Generator gen) +{ + for (; n > 0; --n, ++first) + { + *first = gen(); + } +} + +/*****************************************************************************************/ +// includes +// 判断序列一S1 是否包含序列二S2 +/*****************************************************************************************/ +template +bool includes(InputIter1 first1, InputIter1 last1, + InputIter2 first2, InputIter2 last2) +{ + while (first1 != last1 && first2 != last2) + { + if (*first2 < *first1) + { + return false; + } + else if (*first1 < *first2) + { + ++first1; + } + else + { + ++first1, ++first2; + } + } + return first2 == last2; +} + +// 重载版本使用函数对象 comp 代替比较操作 +template +bool includes(InputIter1 first1, InputIter1 last1, + InputIter2 first2, InputIter2 last2, Compared comp) +{ + while (first1 != last1 && first2 != last2) + { + if (comp(*first2, *first1)) + { + return false; + } + else if (comp(*first1, *first2)) + { + ++first1; + } + else + { + ++first1, ++first2; + } + } + return first2 == last2; +} + +/*****************************************************************************************/ +// is_heap +// 检查[first, last)内的元素是否为一个堆,如果是,则返回 true +/*****************************************************************************************/ +template +bool is_heap(RandomIter first, RandomIter last) +{ + auto n = mystl::distance(first, last); + auto parent = 0; + for (auto child = 1; child < n; ++child) + { + if (first[parent] < first[child]) + return false; + if ((child & 1) == 0) + ++parent; + } + return true; +} + +// 重载版本使用函数对象 comp 代替比较操作 +template +bool is_heap(RandomIter first, RandomIter last, Compared comp) +{ + auto n = mystl::distance(first, last); + auto parent = 0; + for (auto child = 1; child < n; ++child) + { + if (comp(first[parent], first[child])) + return false; + if ((child & 1) == 0) + ++parent; + } + return true; +} + +/*****************************************************************************************/ +// is_sorted +// 检查[first, last)内的元素是否升序,如果是升序,则返回 true +/*****************************************************************************************/ +template +bool is_sorted(ForwardIter first, ForwardIter last) +{ + if (first == last) + return true; + auto next = first; + ++next; + for (; next != last; first = next, ++next) + { + if (*next < *first) + return false; + } + return true; +} + +// 重载版本使用函数对象 comp 代替比较操作 +template +bool is_sorted(ForwardIter first, ForwardIter last, Compared comp) +{ + if (first == last) + return true; + auto next = first; + ++next; + for (; next != last; first = next, ++next) + { + if (comp(*next, *first)) + return false; + } + return true; +} + +/*****************************************************************************************/ +// median +// 找出三个值的中间值 +/*****************************************************************************************/ +template +const T& median(const T& left, const T& mid, const T& right) +{ + if (left < mid) + if (mid < right) // left < mid < right + return mid; + else if (left < right) // left < right <= mid + return right; + else // right <= left < mid + return left; + else if (left < right) // mid <= left < right + return left; + else if (mid < right) // mid < right <= left + return right; + else // right <= mid <= left + return mid; +} + +// 重载版本使用函数对象 comp 代替比较操作 +template +const T& median(const T& left, const T& mid, const T& right, Compared comp) +{ + if (comp(left, mid)) + if (comp(mid, right)) + return mid; + else if (comp(left, right)) + return right; + else + return left; + else if (comp(left, right)) + return left; + else if (comp(mid, right)) + return right; + else + return mid; +} + +/*****************************************************************************************/ +// max_element +// 返回一个迭代器,指向序列中最大的元素 +/*****************************************************************************************/ +template +ForwardIter max_element(ForwardIter first, ForwardIter last) +{ + if (first == last) + return first; + auto result = first; + while (++first != last) + { + if (*result < *first) + result = first; + } + return result; +} + +// 重载版本使用函数对象 comp 代替比较操作 +template +ForwardIter max_element(ForwardIter first, ForwardIter last, Compared comp) +{ + if (first == last) + return first; + auto result = first; + while (++first != last) + { + if (comp(*result, *first)) + result = first; + } + return result; +} + +/*****************************************************************************************/ +// min_element +// 返回一个迭代器,指向序列中最小的元素 +/*****************************************************************************************/ +template +ForwardIter min_elememt(ForwardIter first, ForwardIter last) +{ + if (first == last) + return first; + auto result = first; + while (++first != last) + { + if (*first < *result) + result = first; + } + return result; +} + +// 重载版本使用函数对象 comp 代替比较操作 +template +ForwardIter min_elememt(ForwardIter first, ForwardIter last, Compared comp) +{ + if (first == last) + return first; + auto result = first; + while (++first != last) + { + if (comp(*first, *result)) + result = first; + } + return result; +} + +/*****************************************************************************************/ +// swap_ranges +// 将[first1, last1)从 first2 开始,交换相同个数元素 +// 交换的区间长度必须相同,两个序列不能互相重叠,返回一个迭代器指向序列二最后一个被交换元素的下一位置 +/*****************************************************************************************/ +template +ForwardIter2 +swap_ranges(ForwardIter1 first1, ForwardIter1 last1, + ForwardIter2 first2) +{ + for (; first1 != last1; ++first1, ++first2) + { + mystl::iter_swap(first1, first2); + } + return first2; +} + +/*****************************************************************************************/ +// transform +// 第一个版本以函数对象 unary_op 作用于[first, last)中的每个元素并将结果保存至 result 中 +// 第二个版本以函数对象 binary_op 作用于两个序列[first1, last1)、[first2, last2)的相同位置 +/*****************************************************************************************/ +template +OutputIter +transform(InputIter first, InputIter last, + OutputIter result, UnaryOperation unary_op) +{ + for (; first != last; ++first, ++result) + { + *result = unary_op(*first); + } + return result; +} + +template +OutputIter +transform(InputIter1 first1, InputIter1 last1, + InputIter2 first2, OutputIter result, BinaryOperation binary_op) +{ + for (; first1 != last1; ++first1, ++first2, ++result) + { + *result = binary_op(*first1, *first2); + } + return result; +} + +/*****************************************************************************************/ +// remove_copy +// 移除区间内与指定 value 相等的元素,并将结果复制到以 result 标示起始位置的容器上 +/*****************************************************************************************/ +template +OutputIter +remove_copy(InputIter first, InputIter last, OutputIter result, const T& value) +{ + for (; first != last; ++first) + { + if (*first != value) + { + *result++ = *first; + } + } + return result; +} + +/*****************************************************************************************/ +// remove +// 移除所有与指定 value 相等的元素 +// 并不从容器中删除这些元素,所以 remove 和 remove_if 不适用于 array +/*****************************************************************************************/ +template +ForwardIter remove(ForwardIter first, ForwardIter last, const T& value) +{ + first = mystl::find(first, last, value); // 利用 find 找出第一个匹配的地方 + auto next = first; + return first == last ? first : mystl::remove_copy(++next, last, first, value); +} + +/*****************************************************************************************/ +// remove_copy_if +// 移除区间内所有令一元操作 unary_pred 为 true 的元素,并将结果复制到以 result 为起始位置的容器上 +/*****************************************************************************************/ +template +OutputIter +remove_copy_if(InputIter first, InputIter last, + OutputIter result, UnaryPredicate unary_pred) +{ + for (; first != last; ++first) + { + if (!unary_pred(*first)) + { + *result = *first; + ++result; + } + } + return result; +} + +/*****************************************************************************************/ +// remove_if +// 移除区间内所有令一元操作 unary_pred 为 true 的元素 +/*****************************************************************************************/ +template +ForwardIter +remove_if(ForwardIter first, ForwardIter last, UnaryPredicate unary_pred) +{ + first = mystl::find_if(first, last, unary_pred); // 利用 find_if 找出第一个匹配的地方 + auto next = first; + return first == last ? first : mystl::remove_copy_if(++next, last, first, unary_pred); +} + +/*****************************************************************************************/ +// replace +// 将区间内所有的 old_value 都以 new_value 替代 +/*****************************************************************************************/ +template +void replace(ForwardIter first, ForwardIter last, + const T& old_value, const T& new_value) +{ + for (; first != last; ++first) + { + if (*first == old_value) + *first = new_value; + } +} + +/*****************************************************************************************/ +// replace_copy +// 行为与 replace 类似,不同的是将结果复制到 result 所指的容器中,原序列没有改变 +/*****************************************************************************************/ +template +OutputIter +replace_copy(InputIter first, InputIter last, + OutputIter result, const T& old_value, const T& new_value) +{ + for (; first != last; ++first, ++result) + { + *result = *first == old_value ? new_value : *first; + } + return result; +} + +/*****************************************************************************************/ +// replace_copy_if +// 行为与 replace_if 类似,不同的是将结果复制到 result 所指的容器中,原序列没有改变 +/*****************************************************************************************/ +template +OutputIter +replace_copy_if(InputIter first, InputIter last, + OutputIter result, UnaryPredicate unary_pred, const T& new_value) +{ + for (; first != last; ++first, ++result) + { + *result = unary_pred(*first) ? new_value : *first; + } + return result; +} + +/*****************************************************************************************/ +// replace_if +// 将区间内所有令一元操作 unary_pred 为 true 的元素都用 new_value 替代 +/*****************************************************************************************/ +template +void replace_if(ForwardIter first, ForwardIter last, + UnaryPredicate unary_pred, const T& new_value) +{ + for (; first != last; ++first) + { + if (unary_pred(*first)) + *first = new_value; + } +} + +/*****************************************************************************************/ +// reverse +// 将[first, last)区间内的元素反转 +/*****************************************************************************************/ +// reverse_dispatch 的 bidirectional_iterator_tag 版本 +template +void reverse_dispatch(BidirectionalIter first, BidirectionalIter last, + bidirectional_iterator_tag) +{ + while (true) + { + if (first == last || first == --last) + return; + mystl::iter_swap(first++, last); + } +} + +// reverse_dispatch 的 random_access_iterator_tag 版本 +template +void reverse_dispatch(RandomIter first, RandomIter last, + random_access_iterator_tag) +{ + while (first < last) + mystl::iter_swap(first++, --last); +} + +template +void reverse(BidirectionalIter first, BidirectionalIter last) +{ + mystl::reverse_dispatch(first, last, iterator_category(first)); +} + +/*****************************************************************************************/ +// reverse_copy +// 行为与 reverse 类似,不同的是将结果复制到 result 所指容器中 +/*****************************************************************************************/ +template +OutputIter +reverse_copy(BidirectionalIter first, BidirectionalIter last, + OutputIter result) +{ + while (first != last) + { + --last; + *result = *last; + ++result; + } + return result; +} + +/*****************************************************************************************/ +// random_shuffle +// 将[first, last)内的元素次序随机重排 +// 重载版本使用一个产生随机数的函数对象 rand +/*****************************************************************************************/ +template +void random_shuffle(RandomIter first, RandomIter last) +{ + if (first == last) + return; + srand((unsigned)time(0)); + for (auto i = first + 1; i != last; ++i) + { + mystl::iter_swap(i, first + (rand() % (i - first + 1))); + } +} + +// 重载版本使用一个产生随机数的函数对象 rand +template +void random_shuffle(RandomIter first, RandomIter last, + RandomNumberGenerator& rand) +{ + if (first == last) + return; + auto len = mystl::distance(first, last); + for (auto i = first + 1; i != last; ++i) + { + mystl::iter_swap(i, first + (rand(i - first + 1) % len)); + } +} + +/*****************************************************************************************/ +// rotate +// 将[first, middle)内的元素和 [middle, last)内的元素互换,可以交换两个长度不同的区间 +// 返回交换后 middle 的位置 +/*****************************************************************************************/ +// rotate_dispatch 的 forward_iterator_tag 版本 +template +ForwardIter +rotate_dispatch(ForwardIter first, ForwardIter middle, + ForwardIter last, forward_iterator_tag) +{ + auto first2 = middle; + do + { + mystl::swap(*first++, *first2++); + if (first == middle) + middle = first2; + } while (first2 != last); // 后半段移到前面 + + auto new_middle = first; // 迭代器返回的位置 + first2 = middle; + while (first2 != last) + { // 调整剩余元素 + mystl::swap(*first++, *first2++); + if (first == middle) + { + middle = first2; + } + else if (first2 == last) + { + first2 = middle; + } + } + return new_middle; +} + +// rotate_dispatch 的 bidirectional_iterator_tag 版本 +template +BidirectionalIter +rotate_dispatch(BidirectionalIter first, BidirectionalIter middle, + BidirectionalIter last, bidirectional_iterator_tag) +{ + mystl::reverse_dispatch(first, middle, bidirectional_iterator_tag()); + mystl::reverse_dispatch(middle, last, bidirectional_iterator_tag()); + while (first != middle && middle != last) + mystl::swap(*first++, *--last); + if (first == middle) + { + mystl::reverse_dispatch(middle, last, bidirectional_iterator_tag()); + return last; + } + else + { + mystl::reverse_dispatch(first, middle, bidirectional_iterator_tag()); + return first; + } +} + +// 求最大公因子 +template +EuclideanRingElement rgcd(EuclideanRingElement m, EuclideanRingElement n) +{ + while (n != 0) + { + auto t = m % n; + m = n; + n = t; + } + return m; +} + +// rotate_dispatch 的 random_access_iterator_tag 版本 +template +RandomIter +rotate_dispatch(RandomIter first, RandomIter middle, + RandomIter last, random_access_iterator_tag) +{ + // 因为是 random access iterator,我们可以确定每个元素的位置 + auto n = last - first; + auto l = middle - first; + auto r = n - l; + auto result = first + (last - middle); + if (l == r) + { + mystl::swap_ranges(first, middle, middle); + return result; + } + auto cycle_times = rgcd(n, l); + for (auto i = 0; i < cycle_times; ++i) + { + auto tmp = *first; + auto p = first; + if (l < r) + { + for (auto j = 0; j < r / cycle_times; ++j) + { + if (p > first + r) + { + *p = *(p - r); + p -= r; + } + *p = *(p + l); + p += l; + } + } + else + { + for (auto j = 0; j < l / cycle_times - 1; ++j) + { + if (p < last - l) + { + *p = *(p + l); + p += l; + } + *p = *(p - r); + p -= r; + } + } + *p = tmp; + ++first; + } + return result; +} + +template +ForwardIter +rotate(ForwardIter first, ForwardIter middle, ForwardIter last) +{ + if (first == middle) + return last; + if (middle == last) + return first; + return mystl::rotate_dispatch(first, middle, last, iterator_category(first)); +} + +/*****************************************************************************************/ +// rotate_copy +// 行为与 rotate 类似,不同的是将结果复制到 result 所指的容器中 +/*****************************************************************************************/ +template +ForwardIter +rotate_copy(ForwardIter first, ForwardIter middle, + ForwardIter last, OutputIter result) +{ + return mystl::copy(first, middle, mystl::copy(middle, last, result)); +} + +/*****************************************************************************************/ +// is_permutation +// 判断[first1,last1)是否为[first2, last2)的排列组合 +/*****************************************************************************************/ +template +bool is_permutation_aux(ForwardIter1 first1, ForwardIter1 last1, + ForwardIter2 first2, ForwardIter2 last2, + BinaryPred pred) +{ + constexpr bool is_ra_it = mystl::is_random_access_iterator::value + && mystl::is_random_access_iterator::value; + if (is_ra_it) + { + auto len1 = last1 - first1; + auto len2 = last2 - first2; + if (len1 != len2) + return false; + } + + // 先找出相同的前缀段 + for (; first1 != last1 && first2 != last2; ++first1, (void) ++first2) + { + if (!pred(*first1, *first2)) + break; + } + if (is_ra_it) + { + if (first1 == last1) + return true; + } + else + { + auto len1 = mystl::distance(first1, last1); + auto len2 = mystl::distance(first2, last2); + if (len1 == 0 && len2 == 0) + return true; + if (len1 != len2) + return false; + } + + // 判断剩余部分 + for (auto i = first1; i != last1; ++i) + { + bool is_repeated = false; + for (auto j = first1; j != i; ++j) + { + if (pred(*j, *i)) + { + is_repeated = true; + break; + } + } + + if (!is_repeated) + { + // 计算 *i 在 [first2, last2) 的数目 + auto c2 = 0; + for (auto j = first2; j != last2; ++j) + { + if (pred(*i, *j)) + ++c2; + } + if (c2 == 0) + return false; + + // 计算 *i 在 [first1, last1) 的数目 + auto c1 = 1; + auto j = i; + for (++j; j != last1; ++j) + { + if (pred(*i, *j)) + ++c1; + } + if (c1 != c2) + return false; + } + } + return true; +} + +template +bool is_permutation(ForwardIter1 first1, ForwardIter1 last1, + ForwardIter2 first2, ForwardIter2 last2, + BinaryPred pred) +{ + return is_permutation_aux(first1, last1, first2, last2, pred); +} + +template +bool is_permutation(ForwardIter1 first1, ForwardIter1 last1, + ForwardIter2 first2, ForwardIter2 last2) +{ + typedef typename iterator_traits::value_type v1; + typedef typename iterator_traits::value_type v2; + static_assert(std::is_same::value, + "the type should be same in mystl::is_permutation"); + return is_permutation_aux(first1, last1, first2, last2, + mystl::equal_to()); +} + +/*****************************************************************************************/ +// next_permutation +// 取得[first, last)所标示序列的下一个排列组合,如果没有下一个排序组合,返回 false,否则返回 true +/*****************************************************************************************/ +template +bool next_permutation(BidirectionalIter first, BidirectionalIter last) +{ + auto i = last; + if (first == last || first == --i) + return false; + for (;;) + { + auto ii = i; + if (*--i < *ii) + { // 找到第一对小于关系的元素 + auto j = last; + while (!(*i < *--j)) {} + mystl::iter_swap(i, j); // 交换 i,j 所指元素 + mystl::reverse(ii, last); // 将 ii 之后的所有元素反转 + return true; + } + if (i == first) + { + mystl::reverse(first, last); + return false; + } + } +} + +// 重载版本使用函数对象 comp 代替比较操作 +template +bool next_permutation(BidirectionalIter first, BidirectionalIter last, Compared comp) +{ + auto i = last; + if (first == last || first == --i) + return false; + for (;;) + { + auto ii = i; + if (comp(*--i, *ii)) + { + auto j = last; + while (!comp(*i, *--j)) {} + mystl::iter_swap(i, j); // 交换 i,j 所指元素 + mystl::reverse(ii, last); // 将 ii 之后的所有元素反转 + return true; + } + if (i == first) + { + mystl::reverse(first, last); + return false; + } + } +} + +/*****************************************************************************************/ +// prev_permutation +// 取得[first, last)所标示序列的上一个排列组合,如果没有上一个排序组合,返回 false,否则返回 true +/*****************************************************************************************/ +template +bool prev_permutation(BidirectionalIter first, BidirectionalIter last) +{ + auto i = last; + if (first == last || first == --i) + return false; + for (;;) + { + auto ii = i; + if (*ii < *--i) + { // 找到第一对大于关系的元素 + auto j = last; + while (!(*--j < *i)) {} + mystl::iter_swap(i, j); // 交换i,j + mystl::reverse(ii, last); // 将 ii 之后的所有元素反转 + return true; + } + if (i == first) + { + mystl::reverse(first, last); + return false; + } + } +} + +// 重载版本使用函数对象 comp 代替比较操作 +template +bool prev_permutation(BidirectionalIter first, BidirectionalIter last, Compared comp) +{ + auto i = last; + if (first == last || first == --i) + return false; + for (;;) + { + auto ii = i; + if (comp(*ii, *--i)) + { + auto j = last; + while (!comp(*--j, *i)) {} + mystl::iter_swap(i, j); // 交换i,j + mystl::reverse(ii, last); // 将 ii 之后的所有元素反转 + return true; + } + if (i == first) + { + mystl::reverse(first, last); + return false; + } + } +} + +/*****************************************************************************************/ +// merge +// 将两个经过排序的集合 S1 和 S2 合并起来置于另一段空间,返回一个迭代器指向最后一个元素的下一位置 +/*****************************************************************************************/ +template +OutputIter +merge(InputIter1 first1, InputIter1 last1, + InputIter2 first2, InputIter2 last2, + OutputIter result) +{ + while (first1 != last1 && first2 != last2) + { + if (*first2 < *first1) + { + *result = *first2; + ++first2; + } + else + { + *result = *first1; + ++first1; + } + ++result; + } + return mystl::copy(first2, last2, mystl::copy(first1, last1, result)); +} + +// 重载版本使用函数对象 comp 代替比较操作 +template +OutputIter +merge(InputIter1 first1, InputIter1 last1, + InputIter2 first2, InputIter2 last2, + OutputIter result, Compared comp) +{ + while (first1 != last1 && first2 != last2) + { + if (comp(*first2, *first1)) + { + *result = *first2; + ++first2; + } + else + { + *result = *first1; + ++first1; + } + ++result; + } + return mystl::copy(first2, last2, mystl::copy(first1, last1, result)); +} + +/*****************************************************************************************/ +// inplace_merge +// 把连接在一起的两个有序序列结合成单一序列并保持有序 +/*****************************************************************************************/ +// 没有缓冲区的情况下合并 +template +void merge_without_buffer(BidirectionalIter first, BidirectionalIter middle, + BidirectionalIter last, Distance len1, Distance len2) +{ + if (len1 == 0 || len2 == 0) + return; + if (len1 + len2 == 2) + { + if (*middle < *first) + mystl::iter_swap(first, middle); + return; + } + auto first_cut = first; + auto second_cut = middle; + Distance len11 = 0; + Distance len22 = 0; + if (len1 > len2) + { // 序列一较长,找到序列一的中点 + len11 = len1 >> 1; + mystl::advance(first_cut, len11); + second_cut = mystl::lower_bound(middle, last, *first_cut); + len22 = mystl::distance(middle, second_cut); + } + else + { // 序列二较长,找到序列二的中点 + len22 = len2 >> 1; + mystl::advance(second_cut, len22); + first_cut = mystl::upper_bound(first, middle, *second_cut); + len11 = mystl::distance(first, first_cut); + } + auto new_middle = mystl::rotate(first_cut, middle, second_cut); + mystl::merge_without_buffer(first, first_cut, new_middle, len11, len22); + mystl::merge_without_buffer(new_middle, second_cut, last, len1 - len11, len2 - len22); +} + +template +BidirectionalIter1 +merge_backward(BidirectionalIter1 first1, BidirectionalIter1 last1, + BidirectionalIter2 first2, BidirectionalIter2 last2, + BidirectionalIter1 result) +{ + if (first1 == last1) + return mystl::copy_backward(first2, last2, result); + if (first2 == last2) + return mystl::copy_backward(first1, last1, result); + --last1; + --last2; + while (true) + { + if (*last2 < *last1) + { + *--result = *last1; + if (first1 == last1) + return mystl::copy_backward(first2, ++last2, result); + --last1; + } + else + { + *--result = *last2; + if (first2 == last2) + return mystl::copy_backward(first1, ++last1, result); + --last2; + } + } +} + +template +BidirectionalIter1 +rotate_adaptive(BidirectionalIter1 first, BidirectionalIter1 middle, + BidirectionalIter1 last, Distance len1, Distance len2, + BidirectionalIter2 buffer, Distance buffer_size) +{ + BidirectionalIter2 buffer_end; + if (len1 > len2 && len2 <= buffer_size) + { + buffer_end = mystl::copy(middle, last, buffer); + mystl::copy_backward(first, middle, last); + return mystl::copy(buffer, buffer_end, first); + } + else if (len1 <= buffer_size) + { + buffer_end = mystl::copy(first, middle, buffer); + mystl::copy(middle, last, first); + return mystl::copy_backward(buffer, buffer_end, last); + } + else + { + return mystl::rotate(first, middle, last); + } +} + +// 有缓冲区的情况下合并 +template +void merge_adaptive(BidirectionalIter first, BidirectionalIter middle, + BidirectionalIter last, Distance len1, Distance len2, + Pointer buffer, Distance buffer_size) +{ + // 区间长度足够放进缓冲区 + if (len1 <= len2 && len1 <= buffer_size) + { + Pointer buffer_end = mystl::copy(first, middle, buffer); + mystl::merge(buffer, buffer_end, middle, last, first); + } + else if (len2 <= buffer_size) + { + Pointer buffer_end = mystl::copy(middle, last, buffer); + mystl::merge_backward(first, middle, buffer, buffer_end, last); + } + else + { // 区间长度太长,分割递归处理 + auto first_cut = first; + auto second_cut = middle; + Distance len11 = 0; + Distance len22 = 0; + if (len1 > len2) + { + len11 = len1 >> 1; + mystl::advance(first_cut, len11); + second_cut = mystl::lower_bound(middle, last, *first_cut); + len22 = mystl::distance(middle, second_cut); + } + else + { + len22 = len2 >> 1; + mystl::advance(second_cut, len22); + first_cut = mystl::upper_bound(first, middle, *second_cut); + len11 = mystl::distance(first, first_cut); + } + auto new_middle = mystl::rotate_adaptive(first_cut, middle, second_cut, + len1 - len11, len22, buffer, buffer_size); + mystl::merge_adaptive(first, first_cut, new_middle, len11, len22, buffer, buffer_size); + mystl::merge_adaptive(new_middle, second_cut, last, len1 - len11, + len2 - len22, buffer, buffer_size); + } +} + +template +void +inplace_merge_aux(BidirectionalIter first, BidirectionalIter middle, + BidirectionalIter last, T*) +{ + auto len1 = mystl::distance(first, middle); + auto len2 = mystl::distance(middle, last); + temporary_buffer buf(first, last); + if (!buf.begin()) + { + mystl::merge_without_buffer(first, middle, last, len1, len2); + } + else + { + mystl::merge_adaptive(first, middle, last, len1, len2, buf.begin(), buf.size()); + } +} + +template +void +inplace_merge(BidirectionalIter first, BidirectionalIter middle, + BidirectionalIter last) +{ + if (first == middle || middle == last) + return; + mystl::inplace_merge_aux(first, middle, last, value_type(first)); +} + +// 重载版本使用函数对象 comp 代替比较操作 +// 没有缓冲区的情况下合并 +template +void merge_without_buffer(BidirectionalIter first, BidirectionalIter middle, + BidirectionalIter last, Distance len1, Distance len2, + Compared comp) +{ + if (len1 == 0 || len2 == 0) + return; + if (len1 + len2 == 2) + { + if (comp(*middle, *first)) + mystl::iter_swap(first, middle); + return; + } + auto first_cut = first; + auto second_cut = middle; + Distance len11 = 0; + Distance len22 = 0; + if (len1 > len2) + { + len11 = len1 >> 1; + mystl::advance(first_cut, len11); + second_cut = mystl::lower_bound(middle, last, *first_cut, comp); + len22 = mystl::distance(middle, second_cut); + } + else + { + len22 = len2 >> 1; + mystl::advance(second_cut, len22); + first_cut = mystl::upper_bound(first, middle, *second_cut, comp); + len11 = mystl::distance(first, first_cut); + } + auto new_middle = mystl::rotate(first_cut, middle, second_cut); + mystl::merge_without_buffer(first, first_cut, new_middle, len11, len22, comp); + mystl::merge_without_buffer(new_middle, second_cut, last, len1 - len11, len2 - len22, comp); +} + +template +BidirectionalIter1 +merge_backward(BidirectionalIter1 first1, BidirectionalIter1 last1, + BidirectionalIter2 first2, BidirectionalIter2 last2, + BidirectionalIter1 result, Compared comp) +{ + if (first1 == last1) + return mystl::copy_backward(first2, last2, result); + if (first2 == last2) + return mystl::copy_backward(first1, last1, result); + --last1; + --last2; + while (true) + { + if (comp(*last2, *last1)) + { + *--result = *last1; + if (first1 == last1) + return mystl::copy_backward(first2, ++last2, result); + --last1; + } + else + { + *--result = *last2; + if (first2 == last2) + return mystl::copy_backward(first1, ++last1, result); + --last2; + } + } +} + +// 有缓冲区的情况下合并 +template +void merge_adaptive(BidirectionalIter first, BidirectionalIter middle, + BidirectionalIter last, Distance len1, Distance len2, + Pointer buffer, Distance buffer_size, Compared comp) +{ + // 区间长度足够放进缓冲区 + if (len1 <= len2 && len1 <= buffer_size) + { + Pointer buffer_end = mystl::copy(first, middle, buffer); + mystl::merge(buffer, buffer_end, middle, last, first, comp); + } + else if (len2 <= buffer_size) + { + Pointer buffer_end = mystl::copy(middle, last, buffer); + mystl::merge_backward(first, middle, buffer, buffer_end, last, comp); + } + else + { // 区间长度太长,分割递归处理 + auto first_cut = first; + auto second_cut = middle; + Distance len11 = 0; + Distance len22 = 0; + if (len1 > len2) + { + len11 = len1 >> 1; + mystl::advance(first_cut, len11); + second_cut = mystl::lower_bound(middle, last, *first_cut, comp); + len22 = mystl::distance(middle, second_cut); + } + else + { + len22 = len2 >> 1; + mystl::advance(second_cut, len22); + first_cut = mystl::upper_bound(first, middle, *second_cut, comp); + len11 = mystl::distance(first, first_cut); + } + auto new_middle = mystl::rotate_adaptive(first_cut, middle, second_cut, len1 - len11, + len22, buffer, buffer_size); + mystl::merge_adaptive(first, first_cut, new_middle, len11, + len22, buffer, buffer_size, comp); + mystl::merge_adaptive(new_middle, second_cut, last, len1 - len11, + len2 - len22, buffer, buffer_size, comp); + } +} + +template +void +inplace_merge_aux(BidirectionalIter first, BidirectionalIter middle, + BidirectionalIter last, T*, Compared comp) +{ + auto len1 = mystl::distance(first, middle); + auto len2 = mystl::distance(middle, last); + temporary_buffer buf(first, last); + if (!buf.begin()) + { + mystl::merge_without_buffer(first, middle, last, len1, len2, comp); + } + else + { + mystl::merge_adaptive(first, middle, last, len1, len2, buf.begin(), buf.size(), comp); + } +} + +template +void +inplace_merge(BidirectionalIter first, BidirectionalIter middle, + BidirectionalIter last, Compared comp) +{ + if (first == middle || middle == last) + return; + mystl::inplace_merge_aux(first, middle, last, value_type(first), comp); +} + +/*****************************************************************************************/ +// partial_sort +// 对整个序列做部分排序,保证较小的 N 个元素以递增顺序置于[first, first + N)中 +/*****************************************************************************************/ +template +void partial_sort(RandomIter first, RandomIter middle, + RandomIter last) +{ + mystl::make_heap(first, middle); + for (auto i = middle; i < last; ++i) + { + if (*i < *first) + { + mystl::pop_heap_aux(first, middle, i, *i, distance_type(first)); + } + } + mystl::sort_heap(first, middle); +} + +// 重载版本使用函数对象 comp 代替比较操作 +template +void partial_sort(RandomIter first, RandomIter middle, + RandomIter last, Compared comp) +{ + mystl::make_heap(first, middle, comp); + for (auto i = middle; i < last; ++i) + { + if (comp(*i, *first)) + { + mystl::pop_heap_aux(first, middle, i, *i, distance_type(first), comp); + } + } + mystl::sort_heap(first, middle, comp); +} + +/*****************************************************************************************/ +// partial_sort_copy +// 行为与 partial_sort 类似,不同的是把排序结果复制到 result 容器中 +/*****************************************************************************************/ +template +RandomIter +psort_copy_aux(InputIter first, InputIter last, + RandomIter result_first, RandomIter result_last, + Distance*) +{ + if (result_first == result_last) + return result_last; + auto result_iter = result_first; + while (first != last && result_iter != result_last) + { + *result_iter = *first; + ++result_iter; + ++first; + } + mystl::make_heap(result_first, result_iter); + while (first != last) + { + if (*first < *result_first) + { + mystl::adjust_heap(result_first, static_cast(0), + result_iter - result_first, *first); + } + ++first; + } + mystl::sort_heap(result_first, result_iter); + return result_iter; +} + +template +RandomIter +partial_sort_copy(InputIter first, InputIter last, + RandomIter result_first, RandomIter result_last) +{ + return mystl::psort_copy_aux(first, last, result_first, result_last, + distance_type(result_first)); +} + +// 重载版本使用函数对象 comp 代替比较操作 +template +RandomIter +psort_copy_aux(InputIter first, InputIter last, + RandomIter result_first, RandomIter result_last, + Distance*, Compared comp) +{ + if (result_first == result_last) + return result_last; + auto result_iter = result_first; + while (first != last && result_iter != result_last) + { + *result_iter = *first; + ++result_iter; + ++first; + } + mystl::make_heap(result_first, result_iter, comp); + while (first != last) + { + if (comp(*first, *result_first)) + { + mystl::adjust_heap(result_first, static_cast(0), + result_iter - result_first, *first, comp); + } + ++first; + } + mystl::sort_heap(result_first, result_iter, comp); + return result_iter; +} + +template +RandomIter +partial_sort_copy(InputIter first, InputIter last, + RandomIter result_first, RandomIter result_last, + Compared comp) +{ + return mystl::psort_copy_aux(first, last, result_first, result_last, + distance_type(result_first), comp); +} +/*****************************************************************************************/ +// partition +// 对区间内的元素重排,被一元条件运算判定为 true 的元素会放到区间的前段 +// 该函数不保证元素的原始相对位置 +/*****************************************************************************************/ +template +BidirectionalIter +partition(BidirectionalIter first, BidirectionalIter last, + UnaryPredicate unary_pred) +{ + while (true) + { + while (first != last && unary_pred(*first)) + { + ++first; + } + if (first == last) + break; + --last; + while (first != last && !unary_pred(*last)) + { + --last; + } + if (first == last) + break; + mystl::iter_swap(first, last); + ++first; + } + return first; +} + +/*****************************************************************************************/ +// partition_copy +// 行为与 partition 类似,不同的是,将被一元操作符判定为 true 的放到 result_true 的输出区间 +// 其余放到 result_false 的输出区间,并返回一个 mystl::pair 指向这两个区间的尾部 +/*****************************************************************************************/ +template +mystl::pair +partition_copy(InputIter first, InputIter last, + OutputIter1 result_true, OutputIter2 result_false, + UnaryPredicate unary_pred) +{ + for (; first != last; ++first) + { + if (unary_pred(*first)) + { + *result_true++ = *first; + } + else + { + *result_false++ = *first; + } + } + return mystl::pair(result_true, result_false); +} + +/*****************************************************************************************/ +// sort +// 将[first, last)内的元素以递增的方式排序 +/*****************************************************************************************/ +constexpr static size_t kSmallSectionSize = 128; // 小型区间的大小,在这个大小内采用插入排序 + + // 用于控制分割恶化的情况 +template +Size slg2(Size n) +{ // 找出 lgk <= n 的 k 的最大值 + Size k = 0; + for (; n > 1; n >>= 1) + ++k; + return k; +} + +// 分割函数 unchecked_partition +template +RandomIter +unchecked_partition(RandomIter first, RandomIter last, const T& pivot) +{ + while (true) + { + while (*first < pivot) + ++first; + --last; + while (pivot < *last) + --last; + if (!(first < last)) + return first; + mystl::iter_swap(first, last); + ++first; + } +} + +// 内省式排序,先进行 quick sort,当分割行为有恶化倾向时,改用 heap sort +template +void intro_sort(RandomIter first, RandomIter last, Size depth_limit) +{ + while (static_cast(last - first) > kSmallSectionSize) + { + if (depth_limit == 0) + { // 到达最大分割深度限制 + mystl::partial_sort(first, last, last); // 改用 heap_sort + return; + } + --depth_limit; + auto mid = mystl::median(*(first), *(first + (last - first) / 2), *(last - 1)); + auto cut = mystl::unchecked_partition(first, last, mid); + mystl::intro_sort(cut, last, depth_limit); + last = cut; + } +} + +// 插入排序辅助函数 unchecked_linear_insert +template +void unchecked_linear_insert(RandomIter last, const T& value) +{ + auto next = last; + --next; + while (value < *next) + { + *last = *next; + last = next; + --next; + } + *last = value; +} + +// 插入排序函数 unchecked_insertion_sort +template +void unchecked_insertion_sort(RandomIter first, RandomIter last) +{ + for (auto i = first; i != last; ++i) + { + mystl::unchecked_linear_insert(i, *i); + } +} + +// 插入排序函数 insertion_sort +template +void insertion_sort(RandomIter first, RandomIter last) +{ + if (first == last) + return; + for (auto i = first + 1; i != last; ++i) + { + auto value = *i; + if (value < *first) + { + mystl::copy_backward(first, i, i + 1); + *first = value; + } + else + { + mystl::unchecked_linear_insert(i, value); + } + } +} + +// 最终插入排序函数 final_insertion_sort +template +void final_insertion_sort(RandomIter first, RandomIter last) +{ + if (static_cast(last - first) > kSmallSectionSize) + { + mystl::insertion_sort(first, first + kSmallSectionSize); + mystl::unchecked_insertion_sort(first + kSmallSectionSize, last); + } + else + { + mystl::insertion_sort(first, last); + } +} + +template +void sort(RandomIter first, RandomIter last) +{ + if (first != last) + { + // 内省式排序,将区间分为一个个小区间,然后对整体进行插入排序 + mystl::intro_sort(first, last, slg2(last - first) * 2); + mystl::final_insertion_sort(first, last); + } +} + +// 重载版本使用函数对象 comp 代替比较操作 +// 分割函数 unchecked_partition +template +RandomIter +unchecked_partition(RandomIter first, RandomIter last, + const T& pivot, Compared comp) +{ + while (true) + { + while (comp(*first, pivot)) + ++first; + --last; + while (comp(pivot, *last)) + --last; + if (!(first < last)) + return first; + mystl::iter_swap(first, last); + ++first; + } +} + +// 内省式排序,先进行 quick sort,当分割行为有恶化倾向时,改用 heap sort +template +void intro_sort(RandomIter first, RandomIter last, + Size depth_limit, Compared comp) +{ + while (static_cast(last - first) > kSmallSectionSize) + { + if (depth_limit == 0) + { // 到达最大分割深度限制 + mystl::partial_sort(first, last, last, comp); // 改用 heap_sort + return; + } + --depth_limit; + auto mid = mystl::median(*(first), *(first + (last - first) / 2), *(last - 1)); + auto cut = mystl::unchecked_partition(first, last, mid, comp); + mystl::intro_sort(cut, last, depth_limit, comp); + last = cut; + } +} + +// 插入排序辅助函数 unchecked_linear_insert +template +void unchecked_linear_insert(RandomIter last, const T& value, Compared comp) +{ + auto next = last; + --next; + while (comp(value, *next)) + { // 从尾部开始寻找第一个可插入位置 + *last = *next; + last = next; + --next; + } + *last = value; +} + +// 插入排序函数 unchecked_insertion_sort +template +void unchecked_insertion_sort(RandomIter first, RandomIter last, + Compared comp) +{ + for (auto i = first; i != last; ++i) + { + mystl::unchecked_linear_insert(i, *i, comp); + } +} + +// 插入排序函数 insertion_sort +template +void insertion_sort(RandomIter first, RandomIter last, Compared comp) +{ + if (first == last) + return; + for (auto i = first + 1; i != last; ++i) + { + auto value = *i; + if (comp(value, *first)) + { + mystl::copy_backward(first, i, i + 1); + *first = value; + } + else + { + mystl::unchecked_linear_insert(i, value, comp); + } + } +} + +// 最终插入排序函数 final_insertion_sort +template +void final_insertion_sort(RandomIter first, RandomIter last, Compared comp) +{ + if (static_cast(last - first) > kSmallSectionSize) + { + mystl::insertion_sort(first, first + kSmallSectionSize, comp); + mystl::unchecked_insertion_sort(first + kSmallSectionSize, last, comp); + } + else + { + mystl::insertion_sort(first, last, comp); + } +} + +template +void sort(RandomIter first, RandomIter last, Compared comp) +{ + if (first != last) + { + // 内省式排序,将区间分为一个个小区间,然后对整体进行插入排序 + mystl::intro_sort(first, last, slg2(last - first) * 2, comp); + mystl::final_insertion_sort(first, last, comp); + } +} + +/*****************************************************************************************/ +// nth_element +// 对序列重排,使得所有小于第 n 个元素的元素出现在它的前面,大于它的出现在它的后面 +/*****************************************************************************************/ +template +void nth_element(RandomIter first, RandomIter nth, + RandomIter last) +{ + if (nth == last) + return; + while (last - first > 3) + { + auto cut = mystl::unchecked_partition(first, last, mystl::median(*first, + *(first + (last - first) / 2), + *(last - 1))); + if (cut <= nth) // 如果 nth 位于右段 + first = cut; // 对右段进行分割 + else + last = cut; // 对左段进行分割 + } + mystl::insertion_sort(first, last); +} + +// 重载版本使用函数对象 comp 代替比较操作 +template +void nth_element(RandomIter first, RandomIter nth, + RandomIter last, Compared comp) +{ + if (nth == last) + return; + while (last - first > 3) + { + auto cut = mystl::unchecked_partition(first, last, mystl::median(*first, + *(first + (last - first) / 2), + *(last - 1)), comp); + if (cut <= nth) // 如果 nth 位于右段 + first = cut; // 对右段进行分割 + else + last = cut; // 对左段进行分割 + } + mystl::insertion_sort(first, last, comp); +} + +/*****************************************************************************************/ +// unique_copy +// 从[first, last)中将元素复制到 result 上,序列必须有序,如果有重复的元素,只会复制一次 +/*****************************************************************************************/ +// unique_copy_dispatch 的 forward_iterator_tag 版本 +template +ForwardIter +unique_copy_dispatch(InputIter first, InputIter last, + ForwardIter result, forward_iterator_tag) +{ + *result = *first; + while (++first != last) + { + if (*result != *first) + *++result = *first; + } + return ++result; +} + +// unique_copy_dispatch 的 output_iterator_tag 版本 +// 由于 output iterator 只能进行只读操作,所以不能有 *result != *first 这样的判断 +template +OutputIter +unique_copy_dispatch(InputIter first, InputIter last, + OutputIter result, output_iterator_tag) +{ + auto value = *first; + *result = value; + while (++first != last) + { + if (value != *first) + { + value = *first; + *++result = value; + } + } + return ++result; +} + +template +OutputIter +unique_copy(InputIter first, InputIter last, OutputIter result) +{ + if (first == last) + return result; + return mystl::unique_copy_dispatch(first, last, result, iterator_category(result)); +} + +// 重载版本使用函数对象 comp 代替比较操作 +// unique_copy_dispatch 的 forward_iterator_tag 版本 +template +ForwardIter +unique_copy_dispatch(InputIter first, InputIter last, + ForwardIter result, forward_iterator_tag, Compared comp) +{ + *result = *first; + while (++first != last) + { + if (!comp(*result, *first)) + *++result = *first; + } + return ++result; +} + +// unique_copy_dispatch 的 output_iterator_tag 版本 +// 由于 output iterator 只能进行只读操作,所以不能有 *result != *first 这样的判断 +template +OutputIter +unique_copy_dispatch(InputIter first, InputIter last, + OutputIter result, output_iterator_tag, Compared comp) +{ + auto value = *first; + *result = value; + while (++first != last) + { + if (!comp(value, *first)) + { + value = *first; + *++result = value; + } + } + return ++result; +} + +template +OutputIter +unique_copy(InputIter first, InputIter last, OutputIter result, Compared comp) +{ + if (first == last) + return result; + return mystl::unique_copy_dispatch(first, last, result, iterator_category(result), comp); +} + +/*****************************************************************************************/ +// unique +// 移除[first, last)内重复的元素,序列必须有序,和 remove 类似,它也不能真正的删除重复元素 +/*****************************************************************************************/ +template +ForwardIter unique(ForwardIter first, ForwardIter last) +{ + first = mystl::adjacent_find(first, last); + return mystl::unique_copy(first, last, first); +} + +// 重载版本使用函数对象 comp 代替比较操作 +template +ForwardIter unique(ForwardIter first, ForwardIter last, Compared comp) +{ + first = mystl::adjacent_find(first, last, comp); + return mystl::unique_copy(first, last, first, comp); +} + +} // namespace mystl + +#ifdef _MSC_VER +#pragma warning(pop) +#endif + +#endif // !MYTINYSTL_ALGO_H_ + diff --git a/src/MyTinySTL-master/MyTinySTL-master/MyTinySTL/algobase.h b/src/MyTinySTL-master/MyTinySTL-master/MyTinySTL/algobase.h new file mode 100755 index 0000000..f7342b5 --- /dev/null +++ b/src/MyTinySTL-master/MyTinySTL-master/MyTinySTL/algobase.h @@ -0,0 +1,520 @@ +#ifndef MYTINYSTL_ALGOBASE_H_ +#define MYTINYSTL_ALGOBASE_H_ + +// 这个头文件包含了 mystl 的基本算法 + +#include + +#include "iterator.h" +#include "util.h" + +namespace mystl +{ + +#ifdef max +#pragma message("#undefing marco max") +#undef max +#endif // max + +#ifdef min +#pragma message("#undefing marco min") +#undef min +#endif // min + +/*****************************************************************************************/ +// max +// 取二者中的较大值,语义相等时保证返回第一个参数 +/*****************************************************************************************/ +template +const T& max(const T& lhs, const T& rhs) +{ + return lhs < rhs ? rhs : lhs; +} + +// 重载版本使用函数对象 comp 代替比较操作 +template +const T& max(const T& lhs, const T& rhs, Compare comp) +{ + return comp(lhs, rhs) ? rhs : lhs; +} + +/*****************************************************************************************/ +// min +// 取二者中的较小值,语义相等时保证返回第一个参数 +/*****************************************************************************************/ +template +const T& min(const T& lhs, const T& rhs) +{ + return rhs < lhs ? rhs : lhs; +} + +// 重载版本使用函数对象 comp 代替比较操作 +template +const T& min(const T& lhs, const T& rhs, Compare comp) +{ + return comp(rhs, lhs) ? rhs : lhs; +} + +/*****************************************************************************************/ +// iter_swap +// 将两个迭代器所指对象对调 +/*****************************************************************************************/ +template +void iter_swap(FIter1 lhs, FIter2 rhs) +{ + mystl::swap(*lhs, *rhs); +} + +/*****************************************************************************************/ +// copy +// 把 [first, last)区间内的元素拷贝到 [result, result + (last - first))内 +/*****************************************************************************************/ +// input_iterator_tag 版本 +template +OutputIter +unchecked_copy_cat(InputIter first, InputIter last, OutputIter result, + mystl::input_iterator_tag) +{ + for (; first != last; ++first, ++result) + { + *result = *first; + } + return result; +} + +// ramdom_access_iterator_tag 版本 +template +OutputIter +unchecked_copy_cat(RandomIter first, RandomIter last, OutputIter result, + mystl::random_access_iterator_tag) +{ + for (auto n = last - first; n > 0; --n, ++first, ++result) + { + *result = *first; + } + return result; +} + +template +OutputIter +unchecked_copy(InputIter first, InputIter last, OutputIter result) +{ + return unchecked_copy_cat(first, last, result, iterator_category(first)); +} + +// 为 trivially_copy_assignable 类型提供特化版本 +template +typename std::enable_if< + std::is_same::type, Up>::value && + std::is_trivially_copy_assignable::value, + Up*>::type +unchecked_copy(Tp* first, Tp* last, Up* result) +{ + const auto n = static_cast(last - first); + if (n != 0) + std::memmove(result, first, n * sizeof(Up)); + return result + n; +} + +template +OutputIter copy(InputIter first, InputIter last, OutputIter result) +{ + return unchecked_copy(first, last, result); +} + +/*****************************************************************************************/ +// copy_backward +// 将 [first, last)区间内的元素拷贝到 [result - (last - first), result)内 +/*****************************************************************************************/ +// unchecked_copy_backward_cat 的 bidirectional_iterator_tag 版本 +template +BidirectionalIter2 +unchecked_copy_backward_cat(BidirectionalIter1 first, BidirectionalIter1 last, + BidirectionalIter2 result, mystl::bidirectional_iterator_tag) +{ + while (first != last) + *--result = *--last; + return result; +} + +// unchecked_copy_backward_cat 的 random_access_iterator_tag 版本 +template +BidirectionalIter2 +unchecked_copy_backward_cat(RandomIter1 first, RandomIter1 last, + BidirectionalIter2 result, mystl::random_access_iterator_tag) +{ + for (auto n = last - first; n > 0; --n) + *--result = *--last; + return result; +} + +template +BidirectionalIter2 +unchecked_copy_backward(BidirectionalIter1 first, BidirectionalIter1 last, + BidirectionalIter2 result) +{ + return unchecked_copy_backward_cat(first, last, result, + iterator_category(first)); +} + +// 为 trivially_copy_assignable 类型提供特化版本 +template +typename std::enable_if< + std::is_same::type, Up>::value && + std::is_trivially_copy_assignable::value, + Up*>::type +unchecked_copy_backward(Tp* first, Tp* last, Up* result) +{ + const auto n = static_cast(last - first); + if (n != 0) + { + result -= n; + std::memmove(result, first, n * sizeof(Up)); + } + return result; +} + +template +BidirectionalIter2 +copy_backward(BidirectionalIter1 first, BidirectionalIter1 last, BidirectionalIter2 result) +{ + return unchecked_copy_backward(first, last, result); +} + +/*****************************************************************************************/ +// copy_if +// 把[first, last)内满足一元操作 unary_pred 的元素拷贝到以 result 为起始的位置上 +/*****************************************************************************************/ +template +OutputIter +copy_if(InputIter first, InputIter last, OutputIter result, UnaryPredicate unary_pred) +{ + for (; first != last; ++first) + { + if (unary_pred(*first)) + *result++ = *first; + } + return result; +} + +/*****************************************************************************************/ +// copy_n +// 把 [first, first + n)区间上的元素拷贝到 [result, result + n)上 +// 返回一个 pair 分别指向拷贝结束的尾部 +/*****************************************************************************************/ +template +mystl::pair +unchecked_copy_n(InputIter first, Size n, OutputIter result, mystl::input_iterator_tag) +{ + for (; n > 0; --n, ++first, ++result) + { + *result = *first; + } + return mystl::pair(first, result); +} + +template +mystl::pair +unchecked_copy_n(RandomIter first, Size n, OutputIter result, + mystl::random_access_iterator_tag) +{ + auto last = first + n; + return mystl::pair(last, mystl::copy(first, last, result)); +} + +template +mystl::pair +copy_n(InputIter first, Size n, OutputIter result) +{ + return unchecked_copy_n(first, n, result, iterator_category(first)); +} + +/*****************************************************************************************/ +// move +// 把 [first, last)区间内的元素移动到 [result, result + (last - first))内 +/*****************************************************************************************/ +// input_iterator_tag 版本 +template +OutputIter +unchecked_move_cat(InputIter first, InputIter last, OutputIter result, + mystl::input_iterator_tag) +{ + for (; first != last; ++first, ++result) + { + *result = mystl::move(*first); + } + return result; +} + +// ramdom_access_iterator_tag 版本 +template +OutputIter +unchecked_move_cat(RandomIter first, RandomIter last, OutputIter result, + mystl::random_access_iterator_tag) +{ + for (auto n = last - first; n > 0; --n, ++first, ++result) + { + *result = mystl::move(*first); + } + return result; +} + +template +OutputIter +unchecked_move(InputIter first, InputIter last, OutputIter result) +{ + return unchecked_move_cat(first, last, result, iterator_category(first)); +} + +// 为 trivially_copy_assignable 类型提供特化版本 +template +typename std::enable_if< + std::is_same::type, Up>::value && + std::is_trivially_move_assignable::value, + Up*>::type +unchecked_move(Tp* first, Tp* last, Up* result) +{ + const size_t n = static_cast(last - first); + if (n != 0) + std::memmove(result, first, n * sizeof(Up)); + return result + n; +} + +template +OutputIter move(InputIter first, InputIter last, OutputIter result) +{ + return unchecked_move(first, last, result); +} + +/*****************************************************************************************/ +// move_backward +// 将 [first, last)区间内的元素移动到 [result - (last - first), result)内 +/*****************************************************************************************/ +// bidirectional_iterator_tag 版本 +template +BidirectionalIter2 +unchecked_move_backward_cat(BidirectionalIter1 first, BidirectionalIter1 last, + BidirectionalIter2 result, mystl::bidirectional_iterator_tag) +{ + while (first != last) + *--result = mystl::move(*--last); + return result; +} + +// random_access_iterator_tag 版本 +template +RandomIter2 +unchecked_move_backward_cat(RandomIter1 first, RandomIter1 last, + RandomIter2 result, mystl::random_access_iterator_tag) +{ + for (auto n = last - first; n > 0; --n) + *--result = mystl::move(*--last); + return result; +} + +template +BidirectionalIter2 +unchecked_move_backward(BidirectionalIter1 first, BidirectionalIter1 last, + BidirectionalIter2 result) +{ + return unchecked_move_backward_cat(first, last, result, + iterator_category(first)); +} + +// 为 trivially_copy_assignable 类型提供特化版本 +template +typename std::enable_if< + std::is_same::type, Up>::value && + std::is_trivially_move_assignable::value, + Up*>::type +unchecked_move_backward(Tp* first, Tp* last, Up* result) +{ + const size_t n = static_cast(last - first); + if (n != 0) + { + result -= n; + std::memmove(result, first, n * sizeof(Up)); + } + return result; +} + +template +BidirectionalIter2 +move_backward(BidirectionalIter1 first, BidirectionalIter1 last, BidirectionalIter2 result) +{ + return unchecked_move_backward(first, last, result); +} + +/*****************************************************************************************/ +// equal +// 比较第一序列在 [first, last)区间上的元素值是否和第二序列相等 +/*****************************************************************************************/ +template +bool equal(InputIter1 first1, InputIter1 last1, InputIter2 first2) +{ + for (; first1 != last1; ++first1, ++first2) + { + if (*first1 != *first2) + return false; + } + return true; +} + +// 重载版本使用函数对象 comp 代替比较操作 +template +bool equal(InputIter1 first1, InputIter1 last1, InputIter2 first2, Compared comp) +{ + for (; first1 != last1; ++first1, ++first2) + { + if (!comp(*first1, *first2)) + return false; + } + return true; +} + +/*****************************************************************************************/ +// fill_n +// 从 first 位置开始填充 n 个值 +/*****************************************************************************************/ +template +OutputIter unchecked_fill_n(OutputIter first, Size n, const T& value) +{ + for (; n > 0; --n, ++first) + { + *first = value; + } + return first; +} + +// 为 one-byte 类型提供特化版本 +template +typename std::enable_if< + std::is_integral::value && sizeof(Tp) == 1 && + !std::is_same::value && + std::is_integral::value && sizeof(Up) == 1, + Tp*>::type +unchecked_fill_n(Tp* first, Size n, Up value) +{ + if (n > 0) + { + std::memset(first, (unsigned char)value, (size_t)(n)); + } + return first + n; +} + +template +OutputIter fill_n(OutputIter first, Size n, const T& value) +{ + return unchecked_fill_n(first, n, value); +} + +/*****************************************************************************************/ +// fill +// 为 [first, last)区间内的所有元素填充新值 +/*****************************************************************************************/ +template +void fill_cat(ForwardIter first, ForwardIter last, const T& value, + mystl::forward_iterator_tag) +{ + for (; first != last; ++first) + { + *first = value; + } +} + +template +void fill_cat(RandomIter first, RandomIter last, const T& value, + mystl::random_access_iterator_tag) +{ + fill_n(first, last - first, value); +} + +template +void fill(ForwardIter first, ForwardIter last, const T& value) +{ + fill_cat(first, last, value, iterator_category(first)); +} + +/*****************************************************************************************/ +// lexicographical_compare +// 以字典序排列对两个序列进行比较,当在某个位置发现第一组不相等元素时,有下列几种情况: +// (1)如果第一序列的元素较小,返回 true ,否则返回 false +// (2)如果到达 last1 而尚未到达 last2 返回 true +// (3)如果到达 last2 而尚未到达 last1 返回 false +// (4)如果同时到达 last1 和 last2 返回 false +/*****************************************************************************************/ +template +bool lexicographical_compare(InputIter1 first1, InputIter1 last1, + InputIter2 first2, InputIter2 last2) +{ + for (; first1 != last1 && first2 != last2; ++first1, ++first2) + { + if (*first1 < *first2) + return true; + if (*first2 < *first1) + return false; + } + return first1 == last1 && first2 != last2; +} + +// 重载版本使用函数对象 comp 代替比较操作 +template +bool lexicographical_compare(InputIter1 first1, InputIter1 last1, + InputIter2 first2, InputIter2 last2, Compred comp) +{ + for (; first1 != last1 && first2 != last2; ++first1, ++first2) + { + if (comp(*first1, *first2)) + return true; + if (comp(*first2, *first1)) + return false; + } + return first1 == last1 && first2 != last2; +} + +// 针对 const unsigned char* 的特化版本 +bool lexicographical_compare(const unsigned char* first1, + const unsigned char* last1, + const unsigned char* first2, + const unsigned char* last2) +{ + const auto len1 = last1 - first1; + const auto len2 = last2 - first2; + // 先比较相同长度的部分 + const auto result = std::memcmp(first1, first2, mystl::min(len1, len2)); + // 若相等,长度较长的比较大 + return result != 0 ? result < 0 : len1 < len2; +} + +/*****************************************************************************************/ +// mismatch +// 平行比较两个序列,找到第一处失配的元素,返回一对迭代器,分别指向两个序列中失配的元素 +/*****************************************************************************************/ +template +mystl::pair +mismatch(InputIter1 first1, InputIter1 last1, InputIter2 first2) +{ + while (first1 != last1 && *first1 == *first2) + { + ++first1; + ++first2; + } + return mystl::pair(first1, first2); +} + +// 重载版本使用函数对象 comp 代替比较操作 +template +mystl::pair +mismatch(InputIter1 first1, InputIter1 last1, InputIter2 first2, Compred comp) +{ + while (first1 != last1 && comp(*first1, *first2)) + { + ++first1; + ++first2; + } + return mystl::pair(first1, first2); +} + +} // namespace mystl +#endif // !MYTINYSTL_ALGOBASE_H_ + diff --git a/src/MyTinySTL-master/MyTinySTL-master/MyTinySTL/algorithm.h b/src/MyTinySTL-master/MyTinySTL-master/MyTinySTL/algorithm.h new file mode 100755 index 0000000..ee99e4f --- /dev/null +++ b/src/MyTinySTL-master/MyTinySTL-master/MyTinySTL/algorithm.h @@ -0,0 +1,18 @@ +#ifndef MYTINYSTL_ALGORITHM_H_ +#define MYTINYSTL_ALGORITHM_H_ + +// 这个头文件包含了 mystl 的所有算法,包括基本算法,数值算法,heap 算法,set 算法和其他算法 + +#include "algobase.h" +#include "algo.h" +#include "set_algo.h" +#include "heap_algo.h" +#include "numeric.h" + +namespace mystl +{ + +} // namespace mystl + +#endif // !MYTINYSTL_ALGORITHM_H_ + diff --git a/src/MyTinySTL-master/MyTinySTL-master/MyTinySTL/alloc.h b/src/MyTinySTL-master/MyTinySTL-master/MyTinySTL/alloc.h new file mode 100755 index 0000000..93d3bcf --- /dev/null +++ b/src/MyTinySTL-master/MyTinySTL-master/MyTinySTL/alloc.h @@ -0,0 +1,264 @@ +#ifndef MYTINYSTL_ALLOC_H_ +#define MYTINYSTL_ALLOC_H_ + +// 这个头文件包含一个类 alloc,用于分配和回收内存,以内存池的方式实现 +// +// 从 v2.0.0 版本开始,将不再使用内存池,这个文件将被弃用,但暂时保留 +// +// 注意!!! +// 我知道这个文件里很多实现是错的,这是很久很久前写的了,后面已经不用这个东西了, +// 所以我也没再维护,有诸多问题,已经有人在issue中都提了,free_list的修改, +// 指针作为参数时没实际修改到原指针,等等。相信会看这么仔细的,大部分都是 +// 初学C++的朋友,大佬都不会看这些玩具了,所以其中的错误,就留给对内存池实现 +// 感兴趣的朋友去修改啦! + +#include + +#include +#include + +namespace mystl +{ + +// 共用体: FreeList +// 采用链表的方式管理内存碎片,分配与回收小内存(<=4K)区块 +union FreeList +{ + union FreeList* next; // 指向下一个区块 + char data[1]; // 储存本块内存的首地址 +}; + +// 不同内存范围的上调大小 +enum +{ + EAlign128 = 8, + EAlign256 = 16, + EAlign512 = 32, + EAlign1024 = 64, + EAlign2048 = 128, + EAlign4096 = 256 +}; + +// 小对象的内存大小 +enum { ESmallObjectBytes = 4096 }; + +// free lists 个数 +enum { EFreeListsNumber = 56 }; + +// 空间配置类 alloc +// 如果内存较大,超过 4096 bytes,直接调用 std::malloc, std::free +// 当内存较小时,以内存池管理,每次配置一大块内存,并维护对应的自由链表 +class alloc +{ +private: + static char* start_free; // 内存池起始位置 + static char* end_free; // 内存池结束位置 + static size_t heap_size; // 申请 heap 空间附加值大小 + + static FreeList* free_list[EFreeListsNumber]; // 自由链表 + +public: + static void* allocate(size_t n); + static void deallocate(void* p, size_t n); + static void* reallocate(void* p, size_t old_size, size_t new_size); + +private: + static size_t M_align(size_t bytes); + static size_t M_round_up(size_t bytes); + static size_t M_freelist_index(size_t bytes); + static void* M_refill(size_t n); + static char* M_chunk_alloc(size_t size, size_t &nobj); +}; + +// 静态成员变量初始化 + +char* alloc::start_free = nullptr; +char* alloc::end_free = nullptr; +size_t alloc::heap_size = 0; + +FreeList* alloc::free_list[EFreeListsNumber] = { + nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr, + nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr, + nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr, + nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr, + nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr, + nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr, + nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr + }; + +// 分配大小为 n 的空间, n > 0 +inline void* alloc::allocate(size_t n) +{ + FreeList* my_free_list; + FreeList* result; + if (n > static_cast(ESmallObjectBytes)) + return std::malloc(n); + my_free_list = free_list[M_freelist_index(n)]; + result = my_free_list; + if (result == nullptr) + { + void* r = M_refill(M_round_up(n)); + return r; + } + my_free_list = result->next; + return result; +} + +// 释放 p 指向的大小为 n 的空间, p 不能为 0 +inline void alloc::deallocate(void* p, size_t n) +{ + if (n > static_cast(ESmallObjectBytes)) + { + std::free(p); + return; + } + FreeList* q = reinterpret_cast(p); + FreeList* my_free_list; + my_free_list = free_list[M_freelist_index(n)]; + q->next = my_free_list; + my_free_list = q; +} + +// 重新分配空间,接受三个参数,参数一为指向新空间的指针,参数二为原来空间的大小,参数三为申请空间的大小 +inline void* alloc::reallocate(void* p, size_t old_size, size_t new_size) +{ + deallocate(p, old_size); + p = allocate(new_size); + return p; +} + +// bytes 对应上调大小 +inline size_t alloc::M_align(size_t bytes) +{ + if (bytes <= 512) + { + return bytes <= 256 + ? bytes <= 128 ? EAlign128 : EAlign256 + : EAlign512; + } + return bytes <= 2048 + ? bytes <= 1024 ? EAlign1024 : EAlign2048 + : EAlign4096; +} + +// 将 bytes 上调至对应区间大小 +inline size_t alloc::M_round_up(size_t bytes) +{ + return ((bytes + M_align(bytes) - 1) & ~(M_align(bytes) - 1)); +} + +// 根据区块大小,选择第 n 个 free lists +inline size_t alloc::M_freelist_index(size_t bytes) +{ + if (bytes <= 512) + { + return bytes <= 256 + ? bytes <= 128 + ? ((bytes + EAlign128 - 1) / EAlign128 - 1) + : (15 + (bytes + EAlign256 - 129) / EAlign256) + : (23 + (bytes + EAlign512 - 257) / EAlign512); + } + return bytes <= 2048 + ? bytes <= 1024 + ? (31 + (bytes + EAlign1024 - 513) / EAlign1024) + : (39 + (bytes + EAlign2048 - 1025) / EAlign2048) + : (47 + (bytes + EAlign4096 - 2049) / EAlign4096); +} + +// 重新填充 free list +void* alloc::M_refill(size_t n) +{ + size_t nblock = 10; + char* c = M_chunk_alloc(n, nblock); + FreeList* my_free_list; + FreeList* result, *cur, *next; + // 如果只有一个区块,就把这个区块返回给调用者,free list 没有增加新节点 + if (nblock == 1) + return c; + // 否则把一个区块给调用者,剩下的纳入 free list 作为新节点 + my_free_list = free_list[M_freelist_index(n)]; + result = (FreeList*)c; + my_free_list = next = (FreeList*)(c + n); + for (size_t i = 1; ; ++i) + { + cur = next; + next = (FreeList*)((char*)next + n); + if (nblock - 1 == i) + { + cur->next = nullptr; + break; + } + else + { + cur->next = next; + } + } + return result; +} + +// 从内存池中取空间给 free list 使用,条件不允许时,会调整 nblock +char* alloc::M_chunk_alloc(size_t size, size_t& nblock) +{ + char* result; + size_t need_bytes = size * nblock; + size_t pool_bytes = end_free - start_free; + + // 如果内存池剩余大小完全满足需求量,返回它 + if (pool_bytes >= need_bytes) + { + result = start_free; + start_free += need_bytes; + return result; + } + + // 如果内存池剩余大小不能完全满足需求量,但至少可以分配一个或一个以上的区块,就返回它 + else if (pool_bytes >= size) + { + nblock = pool_bytes / size; + need_bytes = size * nblock; + result = start_free; + start_free += need_bytes; + return result; + } + + // 如果内存池剩余大小连一个区块都无法满足 + else + { + if (pool_bytes > 0) + { // 如果内存池还有剩余,把剩余的空间加入到 free list 中 + FreeList* my_free_list = free_list[M_freelist_index(pool_bytes)]; + ((FreeList*)start_free)->next = my_free_list; + my_free_list = (FreeList*)start_free; + } + // 申请 heap 空间 + size_t bytes_to_get = (need_bytes << 1) + M_round_up(heap_size >> 4); + start_free = (char*)std::malloc(bytes_to_get); + if (!start_free) + { // heap 空间也不够 + FreeList* my_free_list, *p; + // 试着查找有无未用区块,且区块足够大的 free list + for (size_t i = size; i <= ESmallObjectBytes; i += M_align(i)) + { + my_free_list = free_list[M_freelist_index(i)]; + p = my_free_list; + if (p) + { + my_free_list = p->next; + start_free = (char*)p; + end_free = start_free + i; + return M_chunk_alloc(size, nblock); + } + } + std::printf("out of memory"); + end_free = nullptr; + throw std::bad_alloc(); + } + end_free = start_free + bytes_to_get; + heap_size += bytes_to_get; + return M_chunk_alloc(size, nblock); + } +} + +} // namespace mystl +#endif // !MYTINYSTL_ALLOC_H_ + diff --git a/src/MyTinySTL-master/MyTinySTL-master/MyTinySTL/allocator.h b/src/MyTinySTL-master/MyTinySTL-master/MyTinySTL/allocator.h new file mode 100755 index 0000000..a3a5d4e --- /dev/null +++ b/src/MyTinySTL-master/MyTinySTL-master/MyTinySTL/allocator.h @@ -0,0 +1,113 @@ +#ifndef MYTINYSTL_ALLOCATOR_H_ +#define MYTINYSTL_ALLOCATOR_H_ + +// 这个头文件包含一个模板类 allocator,用于管理内存的分配、释放,对象的构造、析构 + +#include "construct.h" +#include "util.h" + +namespace mystl +{ + +// 模板类:allocator +// 模板函数代表数据类型 +template +class allocator +{ +public: + typedef T value_type; + typedef T* pointer; + typedef const T* const_pointer; + typedef T& reference; + typedef const T& const_reference; + typedef size_t size_type; + typedef ptrdiff_t difference_type; + +public: + static T* allocate(); + static T* allocate(size_type n); + + static void deallocate(T* ptr); + static void deallocate(T* ptr, size_type n); + + static void construct(T* ptr); + static void construct(T* ptr, const T& value); + static void construct(T* ptr, T&& value); + + template + static void construct(T* ptr, Args&& ...args); + + static void destroy(T* ptr); + static void destroy(T* first, T* last); +}; + +template +T* allocator::allocate() +{ + return static_cast(::operator new(sizeof(T))); +} + +template +T* allocator::allocate(size_type n) +{ + if (n == 0) + return nullptr; + return static_cast(::operator new(n * sizeof(T))); +} + +template +void allocator::deallocate(T* ptr) +{ + if (ptr == nullptr) + return; + ::operator delete(ptr); +} + +template +void allocator::deallocate(T* ptr, size_type /*size*/) +{ + if (ptr == nullptr) + return; + ::operator delete(ptr); +} + +template +void allocator::construct(T* ptr) +{ + mystl::construct(ptr); +} + +template +void allocator::construct(T* ptr, const T& value) +{ + mystl::construct(ptr, value); +} + +template + void allocator::construct(T* ptr, T&& value) +{ + mystl::construct(ptr, mystl::move(value)); +} + +template +template + void allocator::construct(T* ptr, Args&& ...args) +{ + mystl::construct(ptr, mystl::forward(args)...); +} + +template +void allocator::destroy(T* ptr) +{ + mystl::destroy(ptr); +} + +template +void allocator::destroy(T* first, T* last) +{ + mystl::destroy(first, last); +} + +} // namespace mystl +#endif // !MYTINYSTL_ALLOCATOR_H_ + diff --git a/src/MyTinySTL-master/MyTinySTL-master/MyTinySTL/astring.h b/src/MyTinySTL-master/MyTinySTL-master/MyTinySTL/astring.h new file mode 100755 index 0000000..0bf7adc --- /dev/null +++ b/src/MyTinySTL-master/MyTinySTL-master/MyTinySTL/astring.h @@ -0,0 +1,18 @@ +#ifndef MYTINYSTL_ASTRING_H_ +#define MYTINYSTL_ASTRING_H_ + +// 定义了 string, wstring, u16string, u32string 类型 + +#include "basic_string.h" + +namespace mystl +{ + +using string = mystl::basic_string; +using wstring = mystl::basic_string; +using u16string = mystl::basic_string; +using u32string = mystl::basic_string; + +} +#endif // !MYTINYSTL_ASTRING_H_ + diff --git a/src/MyTinySTL-master/MyTinySTL-master/MyTinySTL/basic_string.h b/src/MyTinySTL-master/MyTinySTL-master/MyTinySTL/basic_string.h new file mode 100755 index 0000000..668ca5c --- /dev/null +++ b/src/MyTinySTL-master/MyTinySTL-master/MyTinySTL/basic_string.h @@ -0,0 +1,2075 @@ +#ifndef MYTINYSTL_BASIC_STRING_H_ +#define MYTINYSTL_BASIC_STRING_H_ + +// 这个头文件包含一个模板类 basic_string +// 用于表示字符串类型 + +#include + +#include "iterator.h" +#include "memory.h" +#include "functional.h" +#include "exceptdef.h" + +namespace mystl +{ + +// char_traits + +template +struct char_traits +{ + typedef CharType char_type; + + static size_t length(const char_type* str) + { + size_t len = 0; + for (; *str != char_type(0); ++str) + ++len; + return len; + } + + static int compare(const char_type* s1, const char_type* s2, size_t n) + { + for (; n != 0; --n, ++s1, ++s2) + { + if (*s1 < *s2) + return -1; + if (*s2 < *s1) + return 1; + } + return 0; + } + + static char_type* copy(char_type* dst, const char_type* src, size_t n) + { + MYSTL_DEBUG(src + n <= dst || dst + n <= src); + char_type* r = dst; + for (; n != 0; --n, ++dst, ++src) + *dst = *src; + return r; + } + + static char_type* move(char_type* dst, const char_type* src, size_t n) + { + char_type* r = dst; + if (dst < src) + { + for (; n != 0; --n, ++dst, ++src) + *dst = *src; + } + else if (src < dst) + { + dst += n; + src += n; + for (; n != 0; --n) + *--dst = *--src; + } + return r; + } + + static char_type* fill(char_type* dst, char_type ch, size_t count) + { + char_type* r = dst; + for (; count > 0; --count, ++dst) + *dst = ch; + return r; + } +}; + +// Partialized. char_traits +template <> +struct char_traits +{ + typedef char char_type; + + static size_t length(const char_type* str) noexcept + { return std::strlen(str); } + + static int compare(const char_type* s1, const char_type* s2, size_t n) noexcept + { return std::memcmp(s1, s2, n); } + + static char_type* copy(char_type* dst, const char_type* src, size_t n) noexcept + { + MYSTL_DEBUG(src + n <= dst || dst + n <= src); + return static_cast(std::memcpy(dst, src, n)); + } + + static char_type* move(char_type* dst, const char_type* src, size_t n) noexcept + { + return static_cast(std::memmove(dst, src, n)); + } + + static char_type* fill(char_type* dst, char_type ch, size_t count) noexcept + { + return static_cast(std::memset(dst, ch, count)); + } +}; + +// Partialized. char_traits +template <> +struct char_traits +{ + typedef wchar_t char_type; + + static size_t length(const char_type* str) noexcept + { + return std::wcslen(str); + } + + static int compare(const char_type* s1, const char_type* s2, size_t n) noexcept + { + return std::wmemcmp(s1, s2, n); + } + + static char_type* copy(char_type* dst, const char_type* src, size_t n) noexcept + { + MYSTL_DEBUG(src + n <= dst || dst + n <= src); + return static_cast(std::wmemcpy(dst, src, n)); + } + + static char_type* move(char_type* dst, const char_type* src, size_t n) noexcept + { + return static_cast(std::wmemmove(dst, src, n)); + } + + static char_type* fill(char_type* dst, char_type ch, size_t count) noexcept + { + return static_cast(std::wmemset(dst, ch, count)); + } +}; + +// Partialized. char_traits +template <> +struct char_traits +{ + typedef char16_t char_type; + + static size_t length(const char_type* str) noexcept + { + size_t len = 0; + for (; *str != char_type(0); ++str) + ++len; + return len; + } + + static int compare(const char_type* s1, const char_type* s2, size_t n) noexcept + { + for (; n != 0; --n, ++s1, ++s2) + { + if (*s1 < *s2) + return -1; + if (*s2 < *s1) + return 1; + } + return 0; + } + + static char_type* copy(char_type* dst, const char_type* src, size_t n) noexcept + { + MYSTL_DEBUG(src + n <= dst || dst + n <= src); + char_type* r = dst; + for (; n != 0; --n, ++dst, ++src) + *dst = *src; + return r; + } + + static char_type* move(char_type* dst, const char_type* src, size_t n) noexcept + { + char_type* r = dst; + if (dst < src) + { + for (; n != 0; --n, ++dst, ++src) + *dst = *src; + } + else if (src < dst) + { + dst += n; + src += n; + for (; n != 0; --n) + *--dst = *--src; + } + return r; + } + + static char_type* fill(char_type* dst, char_type ch, size_t count) noexcept + { + char_type* r = dst; + for (; count > 0; --count, ++dst) + *dst = ch; + return r; + } +}; + +// Partialized. char_traits +template <> +struct char_traits +{ + typedef char32_t char_type; + + static size_t length(const char_type* str) noexcept + { + size_t len = 0; + for (; *str != char_type(0); ++str) + ++len; + return len; + } + + static int compare(const char_type* s1, const char_type* s2, size_t n) noexcept + { + for (; n != 0; --n, ++s1, ++s2) + { + if (*s1 < *s2) + return -1; + if (*s2 < *s1) + return 1; + } + return 0; + } + + static char_type* copy(char_type* dst, const char_type* src, size_t n) noexcept + { + MYSTL_DEBUG(src + n <= dst || dst + n <= src); + char_type* r = dst; + for (; n != 0; --n, ++dst, ++src) + *dst = *src; + return r; + } + + static char_type* move(char_type* dst, const char_type* src, size_t n) noexcept + { + char_type* r = dst; + if (dst < src) + { + for (; n != 0; --n, ++dst, ++src) + *dst = *src; + } + else if (src < dst) + { + dst += n; + src += n; + for (; n != 0; --n) + *--dst = *--src; + } + return r; + } + + static char_type* fill(char_type* dst, char_type ch, size_t count) noexcept + { + char_type* r = dst; + for (; count > 0; --count, ++dst) + *dst = ch; + return r; + } +}; + +// 初始化 basic_string 尝试分配的最小 buffer 大小,可能被忽略 +#define STRING_INIT_SIZE 32 + +// 模板类 basic_string +// 参数一代表字符类型,参数二代表萃取字符类型的方式,缺省使用 mystl::char_traits +template > +class basic_string +{ +public: + typedef CharTraits traits_type; + typedef CharTraits char_traits; + + typedef mystl::allocator allocator_type; + typedef mystl::allocator data_allocator; + + typedef typename allocator_type::value_type value_type; + typedef typename allocator_type::pointer pointer; + typedef typename allocator_type::const_pointer const_pointer; + typedef typename allocator_type::reference reference; + typedef typename allocator_type::const_reference const_reference; + typedef typename allocator_type::size_type size_type; + typedef typename allocator_type::difference_type difference_type; + + typedef value_type* iterator; + typedef const value_type* const_iterator; + typedef mystl::reverse_iterator reverse_iterator; + typedef mystl::reverse_iterator const_reverse_iterator; + + allocator_type get_allocator() { return allocator_type(); } + + static_assert(std::is_pod::value, "Character type of basic_string must be a POD"); + static_assert(std::is_same::value, + "CharType must be same as traits_type::char_type"); + +public: + // 末尾位置的值,例: + // if (str.find('a') != string::npos) { /* do something */ } + static constexpr size_type npos = static_cast(-1); + +private: + iterator buffer_; // 储存字符串的起始位置 + size_type size_; // 大小 + size_type cap_; // 容量 + +public: + // 构造、复制、移动、析构函数 + + basic_string() noexcept + { try_init(); } + + basic_string(size_type n, value_type ch) + :buffer_(nullptr), size_(0), cap_(0) + { + fill_init(n, ch); + } + + basic_string(const basic_string& other, size_type pos) + :buffer_(nullptr), size_(0), cap_(0) + { + init_from(other.buffer_, pos, other.size_ - pos); + } + basic_string(const basic_string& other, size_type pos, size_type count) + :buffer_(nullptr), size_(0), cap_(0) + { + init_from(other.buffer_, pos, count); + } + + basic_string(const_pointer str) + :buffer_(nullptr), size_(0), cap_(0) + { + init_from(str, 0, char_traits::length(str)); + } + basic_string(const_pointer str, size_type count) + :buffer_(nullptr), size_(0), cap_(0) + { + init_from(str, 0, count); + } + + template ::value, int>::type = 0> + basic_string(Iter first, Iter last) + { copy_init(first, last, iterator_category(first)); } + + basic_string(const basic_string& rhs) + :buffer_(nullptr), size_(0), cap_(0) + { + init_from(rhs.buffer_, 0, rhs.size_); + } + basic_string(basic_string&& rhs) noexcept + :buffer_(rhs.buffer_), size_(rhs.size_), cap_(rhs.cap_) + { + rhs.buffer_ = nullptr; + rhs.size_ = 0; + rhs.cap_ = 0; + } + + basic_string& operator=(const basic_string& rhs); + basic_string& operator=(basic_string&& rhs) noexcept; + + basic_string& operator=(const_pointer str); + basic_string& operator=(value_type ch); + + ~basic_string() { destroy_buffer(); } + +public: + // 迭代器相关操作 + iterator begin() noexcept + { return buffer_; } + const_iterator begin() const noexcept + { return buffer_; } + iterator end() noexcept + { return buffer_ + size_; } + const_iterator end() const noexcept + { return buffer_ + size_; } + + reverse_iterator rbegin() noexcept + { return reverse_iterator(end()); } + const_reverse_iterator rbegin() const noexcept + { return const_reverse_iterator(end()); } + reverse_iterator rend() noexcept + { return reverse_iterator(begin()); } + const_reverse_iterator rend() const noexcept + { return const_reverse_iterator(begin()); } + + const_iterator cbegin() const noexcept + { return begin(); } + const_iterator cend() const noexcept + { return end(); } + const_reverse_iterator crbegin() const noexcept + { return rbegin(); } + const_reverse_iterator crend() const noexcept + { return rend(); } + + // 容量相关操作 + bool empty() const noexcept + { return size_ == 0; } + + size_type size() const noexcept + { return size_; } + size_type length() const noexcept + { return size_; } + size_type capacity() const noexcept + { return cap_; } + size_type max_size() const noexcept + { return static_cast(-1); } + + void reserve(size_type n); + void shrink_to_fit(); + + // 访问元素相关操作 + reference operator[](size_type n) + { + MYSTL_DEBUG(n <= size_); + if (n == size_) + *(buffer_ + n) = value_type(); + return *(buffer_ + n); + } + const_reference operator[](size_type n) const + { + MYSTL_DEBUG(n <= size_); + if (n == size_) + *(buffer_ + n) = value_type(); + return *(buffer_ + n); + } + + reference at(size_type n) + { + THROW_OUT_OF_RANGE_IF(n >= size_, "basic_string::at()" + "subscript out of range"); + return (*this)[n]; + } + const_reference at(size_type n) const + { + THROW_OUT_OF_RANGE_IF(n >= size_, "basic_string::at()" + "subscript out of range"); + return (*this)[n]; + } + + reference front() + { + MYSTL_DEBUG(!empty()); + return *begin(); + } + const_reference front() const + { + MYSTL_DEBUG(!empty()); + return *begin(); + } + + reference back() + { + MYSTL_DEBUG(!empty()); + return *(end() - 1); + } + const_reference back() const + { + MYSTL_DEBUG(!empty()); + return *(end() - 1); + } + + const_pointer data() const noexcept + { return to_raw_pointer(); } + const_pointer c_str() const noexcept + { return to_raw_pointer(); } + + // 添加删除相关操作 + + // insert + iterator insert(const_iterator pos, value_type ch); + iterator insert(const_iterator pos, size_type count, value_type ch); + + template + iterator insert(const_iterator pos, Iter first, Iter last); + + + // push_back / pop_back + void push_back(value_type ch) + { append(1, ch); } + void pop_back() + { + MYSTL_DEBUG(!empty()); + --size_; + } + + // append + basic_string& append(size_type count, value_type ch); + + basic_string& append(const basic_string& str) + { return append(str, 0, str.size_); } + basic_string& append(const basic_string& str, size_type pos) + { return append(str, pos, str.size_ - pos); } + basic_string& append(const basic_string& str, size_type pos, size_type count); + + basic_string& append(const_pointer s) + { return append(s, char_traits::length(s)); } + basic_string& append(const_pointer s, size_type count); + + template ::value, int>::type = 0> + basic_string& append(Iter first, Iter last) + { return append_range(first, last); } + + // erase /clear + iterator erase(const_iterator pos); + iterator erase(const_iterator first, const_iterator last); + + // resize + void resize(size_type count) + { resize(count, value_type()); } + void resize(size_type count, value_type ch); + + void clear() noexcept + { size_ = 0; } + + // basic_string 相关操作 + + // compare + int compare(const basic_string& other) const; + int compare(size_type pos1, size_type count1, const basic_string& other) const; + int compare(size_type pos1, size_type count1, const basic_string& other, + size_type pos2, size_type count2 = npos) const; + int compare(const_pointer s) const; + int compare(size_type pos1, size_type count1, const_pointer s) const; + int compare(size_type pos1, size_type count1, const_pointer s, size_type count2) const; + + // substr + basic_string substr(size_type index, size_type count = npos) + { + count = mystl::min(count, size_ - index); + return basic_string(buffer_ + index, buffer_ + index + count); + } + + // replace + basic_string& replace(size_type pos, size_type count, const basic_string& str) + { + THROW_OUT_OF_RANGE_IF(pos > size_, "basic_string::replace's pos out of range"); + return replace_cstr(buffer_ + pos, count, str.buffer_, str.size_); + } + basic_string& replace(const_iterator first, const_iterator last, const basic_string& str) + { + MYSTL_DEBUG(begin() <= first && last <= end() && first <= last); + return replace_cstr(first, static_cast(last - first), str.buffer_, str.size_); + } + + basic_string& replace(size_type pos, size_type count, const_pointer str) + { + THROW_OUT_OF_RANGE_IF(pos > size_, "basic_string::replace's pos out of range"); + return replace_cstr(buffer_ + pos, count, str, char_traits::length(str)); + } + basic_string& replace(const_iterator first, const_iterator last, const_pointer str) + { + MYSTL_DEBUG(begin() <= first && last <= end() && first <= last); + return replace_cstr(first, static_cast(last - first), str, char_traits::length(str)); + } + + basic_string& replace(size_type pos, size_type count, const_pointer str, size_type count2) + { + THROW_OUT_OF_RANGE_IF(pos > size_, "basic_string::replace's pos out of range"); + return replace_cstr(buffer_ + pos, count, str, count2); + } + basic_string& replace(const_iterator first, const_iterator last, const_pointer str, size_type count) + { + MYSTL_DEBUG(begin() <= first && last <= end() && first <= last); + return replace_cstr(first, static_cast(last - first), str, count); + + } + + basic_string& replace(size_type pos, size_type count, size_type count2, value_type ch) + { + THROW_OUT_OF_RANGE_IF(pos > size_, "basic_string::replace's pos out of range"); + return replace_fill(buffer_ + pos, count, count2, ch); + } + basic_string& replace(const_iterator first, const_iterator last, size_type count, value_type ch) + { + MYSTL_DEBUG(begin() <= first && last <= end() && first <= last); + return replace_fill(first, static_cast(last - first), count, ch); + } + + basic_string& replace(size_type pos1, size_type count1, const basic_string& str, + size_type pos2, size_type count2 = npos) + { + THROW_OUT_OF_RANGE_IF(pos1 > size_ || pos2 > str.size_, + "basic_string::replace's pos out of range"); + return replace_cstr(buffer_ + pos1, count1, str.buffer_ + pos2, count2); + } + + template ::value, int>::type = 0> + basic_string& replace(const_iterator first, const_iterator last, Iter first2, Iter last2) + { + MYSTL_DEBUG(begin() <= first && last <= end() && first <= last); + return replace_copy(first, last, first2, last2); + } + + // reverse + void reverse() noexcept; + + // swap + void swap(basic_string& rhs) noexcept; + + // 查找相关操作 + + // find + size_type find(value_type ch, size_type pos = 0) const noexcept; + size_type find(const_pointer str, size_type pos = 0) const noexcept; + size_type find(const_pointer str, size_type pos, size_type count) const noexcept; + size_type find(const basic_string& str, size_type pos = 0) const noexcept; + + // rfind + size_type rfind(value_type ch, size_type pos = npos) const noexcept; + size_type rfind(const_pointer str, size_type pos = npos) const noexcept; + size_type rfind(const_pointer str, size_type pos, size_type count) const noexcept; + size_type rfind(const basic_string& str, size_type pos = npos) const noexcept; + + // find_first_of + size_type find_first_of(value_type ch, size_type pos = 0) const noexcept; + size_type find_first_of(const_pointer s, size_type pos = 0) const noexcept; + size_type find_first_of(const_pointer s, size_type pos, size_type count) const noexcept; + size_type find_first_of(const basic_string& str, size_type pos = 0) const noexcept; + + // find_first_not_of + size_type find_first_not_of(value_type ch, size_type pos = 0) const noexcept; + size_type find_first_not_of(const_pointer s, size_type pos = 0) const noexcept; + size_type find_first_not_of(const_pointer s, size_type pos, size_type count) const noexcept; + size_type find_first_not_of(const basic_string& str, size_type pos = 0) const noexcept; + + // find_last_of + size_type find_last_of(value_type ch, size_type pos = 0) const noexcept; + size_type find_last_of(const_pointer s, size_type pos = 0) const noexcept; + size_type find_last_of(const_pointer s, size_type pos, size_type count) const noexcept; + size_type find_last_of(const basic_string& str, size_type pos = 0) const noexcept; + + // find_last_not_of + size_type find_last_not_of(value_type ch, size_type pos = 0) const noexcept; + size_type find_last_not_of(const_pointer s, size_type pos = 0) const noexcept; + size_type find_last_not_of(const_pointer s, size_type pos, size_type count) const noexcept; + size_type find_last_not_of(const basic_string& str, size_type pos = 0) const noexcept; + + // count + size_type count(value_type ch, size_type pos = 0) const noexcept; + +public: + // 重载 operator+= + basic_string& operator+=(const basic_string& str) + { return append(str); } + basic_string& operator+=(value_type ch) + { return append(1, ch); } + basic_string& operator+=(const_pointer str) + { return append(str, str + char_traits::length(str)); } + + // 重载 operator >> / operatror << + + friend std::istream& operator >> (std::istream& is, basic_string& str) + { + value_type* buf = new value_type[4096]; + is >> buf; + basic_string tmp(buf); + str = std::move(tmp); + delete[]buf; + return is; + } + + friend std::ostream& operator << (std::ostream& os, const basic_string& str) + { + for (size_type i = 0; i < str.size_; ++i) + os << *(str.buffer_ + i); + return os; + } + +private: + // helper functions + + // init / destroy + void try_init() noexcept; + + void fill_init(size_type n, value_type ch); + + template + void copy_init(Iter first, Iter last, mystl::input_iterator_tag); + template + void copy_init(Iter first, Iter last, mystl::forward_iterator_tag); + + void init_from(const_pointer src, size_type pos, size_type n); + + void destroy_buffer(); + + // get raw pointer + const_pointer to_raw_pointer() const; + + // shrink_to_fit + void reinsert(size_type size); + + // append + template + basic_string& append_range(Iter first, Iter last); + + // compare + int compare_cstr(const_pointer s1, size_type n1, const_pointer s2, size_type n2) const; + + // replace + basic_string& replace_cstr(const_iterator first, size_type count1, const_pointer str, size_type count2); + basic_string& replace_fill(const_iterator first, size_type count1, size_type count2, value_type ch); + template + basic_string& replace_copy(const_iterator first, const_iterator last, Iter first2, Iter last2); + + // reallocate + void reallocate(size_type need); + iterator reallocate_and_fill(iterator pos, size_type n, value_type ch); + iterator reallocate_and_copy(iterator pos, const_iterator first, const_iterator last); +}; + +/*****************************************************************************************/ + +// 复制赋值操作符 +template +basic_string& +basic_string:: +operator=(const basic_string& rhs) +{ + if (this != &rhs) + { + basic_string tmp(rhs); + swap(tmp); + } + return *this; +} + +// 移动赋值操作符 +template +basic_string& +basic_string:: +operator=(basic_string&& rhs) noexcept +{ + destroy_buffer(); + buffer_ = rhs.buffer_; + size_ = rhs.size_; + cap_ = rhs.cap_; + rhs.buffer_ = nullptr; + rhs.size_ = 0; + rhs.cap_ = 0; + return *this; +} + +// 用一个字符串赋值 +template +basic_string& +basic_string:: +operator=(const_pointer str) +{ + const size_type len = char_traits::length(str); + if (cap_ < len) + { + auto new_buffer = data_allocator::allocate(len + 1); + data_allocator::deallocate(buffer_); + buffer_ = new_buffer; + cap_ = len + 1; + } + char_traits::copy(buffer_, str, len); + size_ = len; + return *this; +} + +// 用一个字符赋值 +template +basic_string& +basic_string:: +operator=(value_type ch) +{ + if (cap_ < 1) + { + auto new_buffer = data_allocator::allocate(2); + data_allocator::deallocate(buffer_); + buffer_ = new_buffer; + cap_ = 2; + } + *buffer_ = ch; + size_ = 1; + return *this; +} + +// 预留储存空间 +template +void basic_string:: +reserve(size_type n) +{ + if (cap_ < n) + { + THROW_LENGTH_ERROR_IF(n > max_size(), "n can not larger than max_size()" + "in basic_string::reserve(n)"); + auto new_buffer = data_allocator::allocate(n); + char_traits::move(new_buffer, buffer_, size_); + buffer_ = new_buffer; + cap_ = n; + } +} + +// 减少不用的空间 +template +void basic_string:: +shrink_to_fit() +{ + if (size_ != cap_) + { + reinsert(size_); + } +} + +// 在 pos 处插入一个元素 +template +typename basic_string::iterator +basic_string:: +insert(const_iterator pos, value_type ch) +{ + iterator r = const_cast(pos); + if (size_ == cap_) + { + return reallocate_and_fill(r, 1, ch); + } + char_traits::move(r + 1, r, end() - r); + ++size_; + *r = ch; + return r; +} + +// 在 pos 处插入 n 个元素 +template +typename basic_string::iterator +basic_string:: +insert(const_iterator pos, size_type count, value_type ch) +{ + iterator r = const_cast(pos); + if (count == 0) + return r; + if (cap_ - size_ < count) + { + return reallocate_and_fill(r, count, ch); + } + if (pos == end()) + { + char_traits::fill(end(), ch, count); + size_ += count; + return r; + } + char_traits::move(r + count, r, count); + char_traits::fill(r, ch, count); + size_ += count; + return r; +} + +// 在 pos 处插入 [first, last) 内的元素 +template +template +typename basic_string::iterator +basic_string:: +insert(const_iterator pos, Iter first, Iter last) +{ + iterator r = const_cast(pos); + const size_type len = mystl::distance(first, last); + if (len == 0) + return r; + if (cap_ - size_ < len) + { + return reallocate_and_copy(r, first, last); + } + if (pos == end()) + { + mystl::uninitialized_copy(first, last, end()); + size_ += len; + return r; + } + char_traits::move(r + len, r, len); + mystl::uninitialized_copy(first, last, r); + size_ += len; + return r; +} + +// 在末尾添加 count 个 ch +template +basic_string& +basic_string:: +append(size_type count, value_type ch) +{ + THROW_LENGTH_ERROR_IF(size_ > max_size() - count, + "basic_string's size too big"); + if (cap_ - size_ < count) + { + reallocate(count); + } + char_traits::fill(buffer_ + size_, ch, count); + size_ += count; + return *this; +} + +// 在末尾添加 [str[pos] str[pos+count]) 一段 +template +basic_string& +basic_string:: +append(const basic_string& str, size_type pos, size_type count) +{ + THROW_LENGTH_ERROR_IF(size_ > max_size() - count, + "basic_string's size too big"); + if (count == 0) + return *this; + if (cap_ - size_ < count) + { + reallocate(count); + } + char_traits::copy(buffer_ + size_, str.buffer_ + pos, count); + size_ += count; + return *this; +} + +// 在末尾添加 [s, s+count) 一段 +template +basic_string& +basic_string:: +append(const_pointer s, size_type count) +{ + THROW_LENGTH_ERROR_IF(size_ > max_size() - count, + "basic_string's size too big"); + if (cap_ - size_ < count) + { + reallocate(count); + } + char_traits::copy(buffer_ + size_, s, count); + size_ += count; + return *this; +} + +// 删除 pos 处的元素 +template +typename basic_string::iterator +basic_string:: +erase(const_iterator pos) +{ + MYSTL_DEBUG(pos != end()); + iterator r = const_cast(pos); + char_traits::move(r, pos + 1, end() - pos - 1); + --size_; + return r; +} + +// 删除 [first, last) 的元素 +template +typename basic_string::iterator +basic_string:: +erase(const_iterator first, const_iterator last) +{ + if (first == begin() && last == end()) + { + clear(); + return end(); + } + const size_type n = end() - last; + iterator r = const_cast(first); + char_traits::move(r, last, n); + size_ -= (last - first); + return r; +} + +// 重置容器大小 +template +void basic_string:: +resize(size_type count, value_type ch) +{ + if (count < size_) + { + erase(buffer_ + count, buffer_ + size_); + } + else + { + append(count - size_, ch); + } +} + +// 比较两个 basic_string,小于返回 -1,大于返回 1,等于返回 0 +template +int basic_string:: +compare(const basic_string& other) const +{ + return compare_cstr(buffer_, size_, other.buffer_, other.size_); +} + +// 从 pos1 下标开始的 count1 个字符跟另一个 basic_string 比较 +template +int basic_string:: +compare(size_type pos1, size_type count1, const basic_string& other) const +{ + auto n1 = mystl::min(count1, size_ - pos1); + return compare_cstr(buffer_ + pos1, n1, other.buffer_, other.size_); +} + +// 从 pos1 下标开始的 count1 个字符跟另一个 basic_string 下标 pos2 开始的 count2 个字符比较 +template +int basic_string:: +compare(size_type pos1, size_type count1, const basic_string& other, + size_type pos2, size_type count2) const +{ + auto n1 = mystl::min(count1, size_ - pos1); + auto n2 = mystl::min(count2, other.size_ - pos2); + return compare_cstr(buffer_, n1, other.buffer_, n2); +} + +// 跟一个字符串比较 +template +int basic_string:: +compare(const_pointer s) const +{ + auto n2 = char_traits::length(s); + return compare_cstr(buffer_, size_, s, n2); +} + +// 从下标 pos1 开始的 count1 个字符跟另一个字符串比较 +template +int basic_string:: +compare(size_type pos1, size_type count1, const_pointer s) const +{ + auto n1 = mystl::min(count1, size_ - pos1); + auto n2 = char_traits::length(s); + return compare_cstr(buffer_, n1, s, n2); +} + +// 从下标 pos1 开始的 count1 个字符跟另一个字符串的前 count2 个字符比较 +template +int basic_string:: +compare(size_type pos1, size_type count1, const_pointer s, size_type count2) const +{ + auto n1 = mystl::min(count1, size_ - pos1); + return compare_cstr(buffer_, n1, s, count2); +} + +// 反转 basic_string +template +void basic_string:: +reverse() noexcept +{ + for (auto i = begin(), j = end(); i < j;) + { + mystl::iter_swap(i++, --j); + } +} + +// 交换两个 basic_string +template +void basic_string:: +swap(basic_string& rhs) noexcept +{ + if (this != &rhs) + { + mystl::swap(buffer_, rhs.buffer_); + mystl::swap(size_, rhs.size_); + mystl::swap(cap_, rhs.cap_); + } +} + +// 从下标 pos 开始查找字符为 ch 的元素,若找到返回其下标,否则返回 npos +template +typename basic_string::size_type +basic_string:: +find(value_type ch, size_type pos) const noexcept +{ + for (auto i = pos; i < size_; ++i) + { + if (*(buffer_ + i) == ch) + return i; + } + return npos; +} + +// 从下标 pos 开始查找字符串 str,若找到返回起始位置的下标,否则返回 npos +template +typename basic_string::size_type +basic_string:: +find(const_pointer str, size_type pos) const noexcept +{ + const auto len = char_traits::length(str); + if (len == 0) + return pos; + if (size_ - pos < len) + return npos; + const auto left = size_ - len; + for (auto i = pos; i <= left; ++i) + { + if (*(buffer_ + i) == *str) + { + size_type j = 1; + for (; j < len; ++j) + { + if (*(buffer_ + i + j) != *(str + j)) + break; + } + if (j == len) + return i; + } + } + return npos; +} + +// 从下标 pos 开始查找字符串 str 的前 count 个字符,若找到返回起始位置的下标,否则返回 npos +template +typename basic_string::size_type +basic_string:: +find(const_pointer str, size_type pos, size_type count) const noexcept +{ + if (count == 0) + return pos; + if (size_ - pos < count) + return npos; + const auto left = size_ - count; + for (auto i = pos; i <= left; ++i) + { + if (*(buffer_ + i) == *str) + { + size_type j = 1; + for (; j < count; ++j) + { + if (*(buffer_ + i + j) != *(str + j)) + break; + } + if (j == count) + return i; + } + } + return npos; +} + +// 从下标 pos 开始查找字符串 str,若找到返回起始位置的下标,否则返回 npos +template +typename basic_string::size_type +basic_string:: +find(const basic_string& str, size_type pos) const noexcept +{ + const size_type count = str.size_; + if (count == 0) + return pos; + if (size_ - pos < count) + return npos; + const auto left = size_ - count; + for (auto i = pos; i <= left; ++i) + { + if (*(buffer_ + i) == str.front()) + { + size_type j = 1; + for (; j < count; ++j) + { + if (*(buffer_ + i + j) != str[j]) + break; + } + if (j == count) + return i; + } + } + return npos; +} + +// 从下标 pos 开始反向查找值为 ch 的元素,与 find 类似 +template +typename basic_string::size_type +basic_string:: +rfind(value_type ch, size_type pos) const noexcept +{ + if (pos >= size_) + pos = size_ - 1; + for (auto i = pos; i != 0; --i) + { + if (*(buffer_ + i) == ch) + return i; + } + return front() == ch ? 0 : npos; +} + +// 从下标 pos 开始反向查找字符串 str,与 find 类似 +template +typename basic_string::size_type +basic_string:: +rfind(const_pointer str, size_type pos) const noexcept +{ + if (pos >= size_) + pos = size_ - 1; + const size_type len = char_traits::length(str); + switch (len) + { + case 0: + return pos; + case 1: + { + for (auto i = pos; i != 0; --i) + { + if (*(buffer_ + i) == *str) + return i; + } + return front() == *str ? 0 : npos; + } + default: + { // len >= 2 + for (auto i = pos; i >= len - 1; --i) + { + if (*(buffer_ + i) == *(str + len - 1)) + { + size_type j = 1; + for (; j < len; ++j) + { + if (*(buffer_ + i - j) != *(str + len - j - 1)) + break; + } + if (j == len) + return i - len + 1; + } + } + break; + } + } + return npos; +} + +// 从下标 pos 开始反向查找字符串 str 前 count 个字符,与 find 类似 +template +typename basic_string::size_type +basic_string:: +rfind(const_pointer str, size_type pos, size_type count) const noexcept +{ + if (count == 0) + return pos; + if (pos >= size_) + pos = size_ - 1; + if (pos < count - 1) + return npos; + for (auto i = pos; i >= count - 1; --i) + { + if (*(buffer_ + i) == *(str + count - 1)) + { + size_type j = 1; + for (; j < count; ++j) + { + if (*(buffer_ + i - j) != *(str + count - j - 1)) + break; + } + if (j == count) + return i - count + 1; + } + } + return npos; +} + +// 从下标 pos 开始反向查找字符串 str,与 find 类似 +template +typename basic_string::size_type +basic_string:: +rfind(const basic_string& str, size_type pos) const noexcept +{ + const size_type count = str.size_; + if (pos >= size_) + pos = size_ - 1; + if (count == 0) + return pos; + if (pos < count - 1) + return npos; + for (auto i = pos; i >= count - 1; --i) + { + if (*(buffer_ + i) == str[count - 1]) + { + size_type j = 1; + for (; j < count; ++j) + { + if (*(buffer_ + i - j) != str[count - j - 1]) + break; + } + if (j == count) + return i - count + 1; + } + } + return npos; +} + +// 从下标 pos 开始查找 ch 出现的第一个位置 +template +typename basic_string::size_type +basic_string:: +find_first_of(value_type ch, size_type pos) const noexcept +{ + for (auto i = pos; i < size_; ++i) + { + if (*(buffer_ + i) == ch) + return i; + } + return npos; +} + +// 从下标 pos 开始查找字符串 s 其中的一个字符出现的第一个位置 +template +typename basic_string::size_type +basic_string:: +find_first_of(const_pointer s, size_type pos) const noexcept +{ + const size_type len = char_traits::length(s); + for (auto i = pos; i < size_; ++i) + { + value_type ch = *(buffer_ + i); + for (size_type j = 0; j < len; ++j) + { + if (ch == *(s + j)) + return i; + } + } + return npos; +} + +// 从下标 pos 开始查找字符串 s +template +typename basic_string::size_type +basic_string:: +find_first_of(const_pointer s, size_type pos, size_type count) const noexcept +{ + for (auto i = pos; i < size_; ++i) + { + value_type ch = *(buffer_ + i); + for (size_type j = 0; j < count; ++j) + { + if (ch == *(s + j)) + return i; + } + } + return npos; +} + +// 从下标 pos 开始查找字符串 str 其中一个字符出现的第一个位置 +template +typename basic_string::size_type +basic_string:: +find_first_of(const basic_string& str, size_type pos) const noexcept +{ + for (auto i = pos; i < size_; ++i) + { + value_type ch = *(buffer_ + i); + for (size_type j = 0; j < str.size_; ++j) + { + if (ch == str[j]) + return i; + } + } + return npos; +} + +// 从下标 pos 开始查找与 ch 不相等的第一个位置 +template +typename basic_string::size_type +basic_string:: +find_first_not_of(value_type ch, size_type pos) const noexcept +{ + for (auto i = pos; i < size_; ++i) + { + if (*(buffer_ + i) != ch) + return i; + } + return npos; +} + +// 从下标 pos 开始查找与字符串 s 其中一个字符不相等的第一个位置 +template +typename basic_string::size_type +basic_string:: +find_first_not_of(const_pointer s, size_type pos) const noexcept +{ + const size_type len = char_traits::length(s); + for (auto i = pos; i < size_; ++i) + { + value_type ch = *(buffer_ + i); + for (size_type j = 0; j < len; ++j) + { + if (ch != *(s + j)) + return i; + } + } + return npos; +} + +// 从下标 pos 开始查找与字符串 s 前 count 个字符中不相等的第一个位置 +template +typename basic_string::size_type +basic_string:: +find_first_not_of(const_pointer s, size_type pos, size_type count) const noexcept +{ + for (auto i = pos; i < size_; ++i) + { + value_type ch = *(buffer_ + i); + for (size_type j = 0; j < count; ++j) + { + if (ch != *(s + j)) + return i; + } + } + return npos; +} + +// 从下标 pos 开始查找与字符串 str 的字符中不相等的第一个位置 +template +typename basic_string::size_type +basic_string:: +find_first_not_of(const basic_string& str, size_type pos) const noexcept +{ + for (auto i = pos; i < size_; ++i) + { + value_type ch = *(buffer_ + i); + for (size_type j = 0; j < str.size_; ++j) + { + if (ch != str[j]) + return i; + } + } + return npos; +} + +// 从下标 pos 开始查找与 ch 相等的最后一个位置 +template +typename basic_string::size_type +basic_string:: +find_last_of(value_type ch, size_type pos) const noexcept +{ + for (auto i = size_ - 1; i >= pos; --i) + { + if (*(buffer_ + i) == ch) + return i; + } + return npos; +} + +// 从下标 pos 开始查找与字符串 s 其中一个字符相等的最后一个位置 +template +typename basic_string::size_type +basic_string:: +find_last_of(const_pointer s, size_type pos) const noexcept +{ + const size_type len = char_traits::length(s); + for (auto i = size_ - 1; i >= pos; --i) + { + value_type ch = *(buffer_ + i); + for (size_type j = 0; j < len; ++j) + { + if (ch == *(s + j)) + return i; + } + } + return npos; +} + +// 从下标 pos 开始查找与字符串 s 前 count 个字符中相等的最后一个位置 +template +typename basic_string::size_type +basic_string:: +find_last_of(const_pointer s, size_type pos, size_type count) const noexcept +{ + for (auto i = size_ - 1; i >= pos; --i) + { + value_type ch = *(buffer_ + i); + for (size_type j = 0; j < count; ++j) + { + if (ch == *(s + j)) + return i; + } + } + return npos; +} + +// 从下标 pos 开始查找与字符串 str 字符中相等的最后一个位置 +template +typename basic_string::size_type +basic_string:: +find_last_of(const basic_string& str, size_type pos) const noexcept +{ + for (auto i = size_ - 1; i >= pos; --i) + { + value_type ch = *(buffer_ + i); + for (size_type j = 0; j < str.size_; ++j) + { + if (ch == str[j]) + return i; + } + } + return npos; +} + +// 从下标 pos 开始查找与 ch 字符不相等的最后一个位置 +template +typename basic_string::size_type +basic_string:: +find_last_not_of(value_type ch, size_type pos) const noexcept +{ + for (auto i = size_ - 1; i >= pos; --i) + { + if (*(buffer_ + i) != ch) + return i; + } + return npos; +} + +// 从下标 pos 开始查找与字符串 s 的字符中不相等的最后一个位置 +template +typename basic_string::size_type +basic_string:: +find_last_not_of(const_pointer s, size_type pos) const noexcept +{ + const size_type len = char_traits::length(s); + for (auto i = size_ - 1; i >= pos; --i) + { + value_type ch = *(buffer_ + i); + for (size_type j = 0; j < len; ++j) + { + if (ch != *(s + j)) + return i; + } + } + return npos; +} + +// 从下标 pos 开始查找与字符串 s 前 count 个字符中不相等的最后一个位置 +template +typename basic_string::size_type +basic_string:: +find_last_not_of(const_pointer s, size_type pos, size_type count) const noexcept +{ + for (auto i = size_ - 1; i >= pos; --i) + { + value_type ch = *(buffer_ + i); + for (size_type j = 0; j < count; ++j) + { + if (ch != *(s + j)) + return i; + } + } + return npos; +} + +// 从下标 pos 开始查找与字符串 str 字符中不相等的最后一个位置 +template +typename basic_string::size_type +basic_string:: +find_last_not_of(const basic_string& str, size_type pos) const noexcept +{ + for (auto i = size_ - 1; i >= pos; --i) + { + value_type ch = *(buffer_ + i); + for (size_type j = 0; j < str.size_; ++j) + { + if (ch != str[j]) + return i; + } + } + return npos; +} + +// 返回从下标 pos 开始字符为 ch 的元素出现的次数 +template +typename basic_string::size_type +basic_string:: +count(value_type ch, size_type pos) const noexcept +{ + size_type n = 0; + for (auto i = pos; i < size_; ++i) + { + if (*(buffer_ + i) == ch) + ++n; + } + return n; +} + +/*****************************************************************************************/ +// helper function + +// 尝试初始化一段 buffer,若分配失败则忽略,不会抛出异常 +template +void basic_string:: +try_init() noexcept +{ + try + { + buffer_ = data_allocator::allocate(static_cast(STRING_INIT_SIZE)); + size_ = 0; + cap_ = 0; + } + catch (...) + { + buffer_ = nullptr; + size_ = 0; + cap_ = 0; + // no throw + } +} + +// fill_init 函数 +template +void basic_string:: +fill_init(size_type n, value_type ch) +{ + const auto init_size = mystl::max(static_cast(STRING_INIT_SIZE), n + 1); + buffer_ = data_allocator::allocate(init_size); + char_traits::fill(buffer_, ch, n); + size_ = n; + cap_ = init_size; +} + +// copy_init 函数 +template +template +void basic_string:: +copy_init(Iter first, Iter last, mystl::input_iterator_tag) +{ + size_type n = mystl::distance(first, last); + const auto init_size = mystl::max(static_cast(STRING_INIT_SIZE), n + 1); + try + { + buffer_ = data_allocator::allocate(init_size); + size_ = n; + cap_ = init_size; + } + catch (...) + { + buffer_ = nullptr; + size_ = 0; + cap_ = 0; + throw; + } + for (; n > 0; --n, ++first) + append(*first); +} + +template +template +void basic_string:: +copy_init(Iter first, Iter last, mystl::forward_iterator_tag) +{ + const size_type n = mystl::distance(first, last); + const auto init_size = mystl::max(static_cast(STRING_INIT_SIZE), n + 1); + try + { + buffer_ = data_allocator::allocate(init_size); + size_ = n; + cap_ = init_size; + mystl::uninitialized_copy(first, last, buffer_); + } + catch (...) + { + buffer_ = nullptr; + size_ = 0; + cap_ = 0; + throw; + } +} + +// init_from 函数 +template +void basic_string:: +init_from(const_pointer src, size_type pos, size_type count) +{ + const auto init_size = mystl::max(static_cast(STRING_INIT_SIZE), count + 1); + buffer_ = data_allocator::allocate(init_size); + char_traits::copy(buffer_, src + pos, count); + size_ = count; + cap_ = init_size; +} + +// destroy_buffer 函数 +template +void basic_string:: +destroy_buffer() +{ + if (buffer_ != nullptr) + { + data_allocator::deallocate(buffer_, cap_); + buffer_ = nullptr; + size_ = 0; + cap_ = 0; + } +} + +// to_raw_pointer 函数 +template +typename basic_string::const_pointer +basic_string:: +to_raw_pointer() const +{ + *(buffer_ + size_) = value_type(); + return buffer_; +} + +// reinsert 函数 +template +void basic_string:: +reinsert(size_type size) +{ + auto new_buffer = data_allocator::allocate(size); + try + { + char_traits::move(new_buffer, buffer_, size); + } + catch (...) + { + data_allocator::deallocate(new_buffer); + } + buffer_ = new_buffer; + size_ = size; + cap_ = size; +} + +// append_range,末尾追加一段 [first, last) 内的字符 +template +template +basic_string& +basic_string:: +append_range(Iter first, Iter last) +{ + const size_type n = mystl::distance(first, last); + THROW_LENGTH_ERROR_IF(size_ > max_size() - n, + "basic_string's size too big"); + if (cap_ - size_ < n) + { + reallocate(n); + } + mystl::uninitialized_copy_n(first, n, buffer_ + size_); + size_ += n; + return *this; +} + +template +int basic_string:: +compare_cstr(const_pointer s1, size_type n1, const_pointer s2, size_type n2) const +{ + auto rlen = mystl::min(n1, n2); + auto res = char_traits::compare(s1, s2, rlen); + if (res != 0) return res; + if (n1 < n2) return -1; + if (n1 > n2) return 1; + return 0; +} + +// 把 first 开始的 count1 个字符替换成 str 开始的 count2 个字符 +template +basic_string& +basic_string:: +replace_cstr(const_iterator first, size_type count1, const_pointer str, size_type count2) +{ + if (static_cast(cend() - first) < count1) + { + count1 = cend() - first; + } + if (count1 < count2) + { + const size_type add = count2 - count1; + THROW_LENGTH_ERROR_IF(size_ > max_size() - add, + "basic_string's size too big"); + if (size_ > cap_ - add) + { + reallocate(add); + } + pointer r = const_cast(first); + char_traits::move(r + count2, first + count1, end() - (first + count1)); + char_traits::copy(r, str, count2); + size_ += add; + } + else + { + pointer r = const_cast(first); + char_traits::move(r + count2, first + count1, end() - (first + count1)); + char_traits::copy(r, str, count2); + size_ -= (count1 - count2); + } + return *this; +} + +// 把 first 开始的 count1 个字符替换成 count2 个 ch 字符 +template +basic_string& +basic_string:: +replace_fill(const_iterator first, size_type count1, size_type count2, value_type ch) +{ + if (static_cast(cend() - first) < count1) + { + count1 = cend() - first; + } + if (count1 < count2) + { + const size_type add = count2 - count1; + THROW_LENGTH_ERROR_IF(size_ > max_size() - add, + "basic_string's size too big"); + if (size_ > cap_ - add) + { + reallocate(add); + } + pointer r = const_cast(first); + char_traits::move(r + count2, first + count1, end() - (first + count1)); + char_traits::fill(r, ch, count2); + size_ += add; + } + else + { + pointer r = const_cast(first); + char_traits::move(r + count2, first + count1, end() - (first + count1)); + char_traits::fill(r, ch, count2); + size_ -= (count1 - count2); + } + return *this; +} + +// 把 [first, last) 的字符替换成 [first2, last2) +template +template +basic_string& +basic_string:: +replace_copy(const_iterator first, const_iterator last, Iter first2, Iter last2) +{ + size_type len1 = last - first; + size_type len2 = last2 - first2; + if (len1 < len2) + { + const size_type add = len2 - len1; + THROW_LENGTH_ERROR_IF(size_ > max_size() - add, + "basic_string's size too big"); + if (size_ > cap_ - add) + { + reallocate(add); + } + pointer r = const_cast(first); + char_traits::move(r + len2, first + len1, end() - (first + len1)); + char_traits::copy(r, first2, len2); + size_ += add; + } + else + { + pointer r = const_cast(first); + char_traits::move(r + len2, first + len1, end() - (first + len1)); + char_traits::copy(r, first2, len2); + size_ -= (len1 - len2); + } + return *this; +} + +// reallocate 函数 +template +void basic_string:: +reallocate(size_type need) +{ + const auto new_cap = mystl::max(cap_ + need, cap_ + (cap_ >> 1)); + auto new_buffer = data_allocator::allocate(new_cap); + char_traits::move(new_buffer, buffer_, size_); + data_allocator::deallocate(buffer_); + buffer_ = new_buffer; + cap_ = new_cap; +} + +// reallocate_and_fill 函数 +template +typename basic_string::iterator +basic_string:: +reallocate_and_fill(iterator pos, size_type n, value_type ch) +{ + const auto r = pos - buffer_; + const auto old_cap = cap_; + const auto new_cap = mystl::max(old_cap + n, old_cap + (old_cap >> 1)); + auto new_buffer = data_allocator::allocate(new_cap); + auto e1 = char_traits::move(new_buffer, buffer_, r) + r; + auto e2 = char_traits::fill(e1, ch, n) + n; + char_traits::move(e2, buffer_ + r, size_ - r); + data_allocator::deallocate(buffer_, old_cap); + buffer_ = new_buffer; + size_ += n; + cap_ = new_cap; + return buffer_ + r; +} + +// reallocate_and_copy 函数 +template +typename basic_string::iterator +basic_string:: +reallocate_and_copy(iterator pos, const_iterator first, const_iterator last) +{ + const auto r = pos - buffer_; + const auto old_cap = cap_; + const size_type n = mystl::distance(first, last); + const auto new_cap = mystl::max(old_cap + n, old_cap + (old_cap >> 1)); + auto new_buffer = data_allocator::allocate(new_cap); + auto e1 = char_traits::move(new_buffer, buffer_, r) + r; + auto e2 = mystl::uninitialized_copy_n(first, n, e1) + n; + char_traits::move(e2, buffer_ + r, size_ - r); + data_allocator::deallocate(buffer_, old_cap); + buffer_ = new_buffer; + size_ += n; + cap_ = new_cap; + return buffer_ + r; +} + +/*****************************************************************************************/ +// 重载全局操作符 + +// 重载 operator+ +template +basic_string +operator+(const basic_string& lhs, + const basic_string& rhs) +{ + basic_string tmp(lhs); + tmp.append(rhs); + return tmp; +} + +template +basic_string +operator+(const CharType* lhs, const basic_string& rhs) +{ + basic_string tmp(lhs); + tmp.append(rhs); + return tmp; +} + +template +basic_string +operator+(CharType ch, const basic_string& rhs) +{ + basic_string tmp(1, ch); + tmp.append(rhs); + return tmp; +} + +template +basic_string +operator+(const basic_string& lhs, const CharType* rhs) +{ + basic_string tmp(lhs); + tmp.append(rhs); + return tmp; +} + +template +basic_string +operator+(const basic_string& lhs, CharType ch) +{ + basic_string tmp(lhs); + tmp.append(1, ch); + return tmp; +} + +template +basic_string +operator+(basic_string&& lhs, + const basic_string& rhs) +{ + basic_string tmp(mystl::move(lhs)); + tmp.append(rhs); + return tmp; +} + +template +basic_string +operator+(const basic_string& lhs, + basic_string&& rhs) +{ + basic_string tmp(mystl::move(rhs)); + tmp.insert(tmp.begin(), lhs.begin(), lhs.end()); + return tmp; +} + +template +basic_string +operator+(basic_string&& lhs, + basic_string&& rhs) +{ + basic_string tmp(mystl::move(lhs)); + tmp.append(rhs); + return tmp; +} + +template +basic_string +operator+(const CharType* lhs, basic_string&& rhs) +{ + basic_string tmp(mystl::move(rhs)); + tmp.insert(tmp.begin(), lhs, lhs + char_traits::length(lhs)); + return tmp; +} + +template +basic_string +operator+(CharType ch, basic_string&& rhs) +{ + basic_string tmp(mystl::move(rhs)); + tmp.insert(tmp.begin(), ch); + return tmp; +} + +template +basic_string +operator+(basic_string&& lhs, const CharType* rhs) +{ + basic_string tmp(mystl::move(lhs)); + tmp.append(rhs); + return tmp; +} + +template +basic_string +operator+(basic_string&& lhs, CharType ch) +{ + basic_string tmp(mystl::move(lhs)); + tmp.append(1, ch); + return tmp; +} + +// 重载比较操作符 +template +bool operator==(const basic_string& lhs, + const basic_string& rhs) +{ + return lhs.size() == rhs.size() && lhs.compare(rhs) == 0; +} + +template +bool operator!=(const basic_string& lhs, + const basic_string& rhs) +{ + return lhs.size() != rhs.size() || lhs.compare(rhs) != 0; +} + +template +bool operator<(const basic_string& lhs, + const basic_string& rhs) +{ + return lhs.compare(rhs) < 0; +} + +template +bool operator<=(const basic_string& lhs, + const basic_string& rhs) +{ + return lhs.compare(rhs) <= 0; +} + +template +bool operator>(const basic_string& lhs, + const basic_string& rhs) +{ + return lhs.compare(rhs) > 0; +} + +template +bool operator>=(const basic_string& lhs, + const basic_string& rhs) +{ + return lhs.compare(rhs) >= 0; +} + +// 重载 mystl 的 swap +template +void swap(basic_string& lhs, + basic_string& rhs) noexcept +{ + lhs.swap(rhs); +} + +// 特化 mystl::hash +template +struct hash> +{ + size_t operator()(const basic_string& str) + { + return bitwise_hash((const unsigned char*)str.c_str(), + str.size() * sizeof(CharType)); + } +}; + +} // namespace mystl +#endif // !MYTINYSTL_BASIC_STRING_H_ + diff --git a/src/MyTinySTL-master/MyTinySTL-master/MyTinySTL/construct.h b/src/MyTinySTL-master/MyTinySTL-master/MyTinySTL/construct.h new file mode 100755 index 0000000..aeda991 --- /dev/null +++ b/src/MyTinySTL-master/MyTinySTL-master/MyTinySTL/construct.h @@ -0,0 +1,85 @@ +#ifndef MYTINYSTL_CONSTRUCT_H_ +#define MYTINYSTL_CONSTRUCT_H_ + +// 这个头文件包含两个函数 construct,destroy +// construct : 负责对象的构造 +// destroy : 负责对象的析构 + +#include + +#include "type_traits.h" +#include "iterator.h" + +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable : 4100) // unused parameter +#endif // _MSC_VER + +namespace mystl +{ + +// construct 构造对象 + +template +void construct(Ty* ptr) +{ + ::new ((void*)ptr) Ty(); +} + +template +void construct(Ty1* ptr, const Ty2& value) +{ + ::new ((void*)ptr) Ty1(value); +} + +template +void construct(Ty* ptr, Args&&... args) +{ + ::new ((void*)ptr) Ty(mystl::forward(args)...); +} + +// destroy 将对象析构 + +template +void destroy_one(Ty*, std::true_type) {} + +template +void destroy_one(Ty* pointer, std::false_type) +{ + if (pointer != nullptr) + { + pointer->~Ty(); + } +} + +template +void destroy_cat(ForwardIter , ForwardIter , std::true_type) {} + +template +void destroy_cat(ForwardIter first, ForwardIter last, std::false_type) +{ + for (; first != last; ++first) + destroy(&*first); +} + +template +void destroy(Ty* pointer) +{ + destroy_one(pointer, std::is_trivially_destructible{}); +} + +template +void destroy(ForwardIter first, ForwardIter last) +{ + destroy_cat(first, last, std::is_trivially_destructible< + typename iterator_traits::value_type>{}); +} + +} // namespace mystl + +#ifdef _MSC_VER +#pragma warning(pop) +#endif // _MSC_VER + +#endif // !MYTINYSTL_CONSTRUCT_H_ + diff --git a/src/MyTinySTL-master/MyTinySTL-master/MyTinySTL/deque.h b/src/MyTinySTL-master/MyTinySTL-master/MyTinySTL/deque.h new file mode 100755 index 0000000..7975d83 --- /dev/null +++ b/src/MyTinySTL-master/MyTinySTL-master/MyTinySTL/deque.h @@ -0,0 +1,1426 @@ +#ifndef MYTINYSTL_DEQUE_H_ +#define MYTINYSTL_DEQUE_H_ + +// 这个头文件包含了一个模板类 deque +// deque: 双端队列 + +// notes: +// +// 异常保证: +// mystl::deque 满足基本异常保证,部分函数无异常保证,并对以下等函数做强异常安全保证: +// * emplace_front +// * emplace_back +// * emplace +// * push_front +// * push_back +// * insert + +#include + +#include "iterator.h" +#include "memory.h" +#include "util.h" +#include "exceptdef.h" + +namespace mystl +{ + +#ifdef max +#pragma message("#undefing marco max") +#undef max +#endif // max + +#ifdef min +#pragma message("#undefing marco min") +#undef min +#endif // min + +// deque map 初始化的大小 +#ifndef DEQUE_MAP_INIT_SIZE +#define DEQUE_MAP_INIT_SIZE 8 +#endif + +template +struct deque_buf_size +{ + static constexpr size_t value = sizeof(T) < 256 ? 4096 / sizeof(T) : 16; +}; + +// deque 的迭代器设计 +template +struct deque_iterator : public iterator +{ + typedef deque_iterator iterator; + typedef deque_iterator const_iterator; + typedef deque_iterator self; + + typedef T value_type; + typedef Ptr pointer; + typedef Ref reference; + typedef size_t size_type; + typedef ptrdiff_t difference_type; + typedef T* value_pointer; + typedef T** map_pointer; + + static const size_type buffer_size = deque_buf_size::value; + + // 迭代器所含成员数据 + value_pointer cur; // 指向所在缓冲区的当前元素 + value_pointer first; // 指向所在缓冲区的头部 + value_pointer last; // 指向所在缓冲区的尾部 + map_pointer node; // 缓冲区所在节点 + + // 构造、复制、移动函数 + deque_iterator() noexcept + :cur(nullptr), first(nullptr), last(nullptr), node(nullptr) {} + + deque_iterator(value_pointer v, map_pointer n) + :cur(v), first(*n), last(*n + buffer_size), node(n) {} + + deque_iterator(const iterator& rhs) + :cur(rhs.cur), first(rhs.first), last(rhs.last), node(rhs.node) + { + } + deque_iterator(iterator&& rhs) noexcept + :cur(rhs.cur), first(rhs.first), last(rhs.last), node(rhs.node) + { + rhs.cur = nullptr; + rhs.first = nullptr; + rhs.last = nullptr; + rhs.node = nullptr; + } + + deque_iterator(const const_iterator& rhs) + :cur(rhs.cur), first(rhs.first), last(rhs.last), node(rhs.node) + { + } + + self& operator=(const iterator& rhs) + { + if (this != &rhs) + { + cur = rhs.cur; + first = rhs.first; + last = rhs.last; + node = rhs.node; + } + return *this; + } + + // 转到另一个缓冲区 + void set_node(map_pointer new_node) + { + node = new_node; + first = *new_node; + last = first + buffer_size; + } + + // 重载运算符 + reference operator*() const { return *cur; } + pointer operator->() const { return cur; } + + difference_type operator-(const self& x) const + { + return static_cast(buffer_size) * (node - x.node) + + (cur - first) - (x.cur - x.first); + } + + self& operator++() + { + ++cur; + if (cur == last) + { // 如果到达缓冲区的尾 + set_node(node + 1); + cur = first; + } + return *this; + } + self operator++(int) + { + self tmp = *this; + ++*this; + return tmp; + } + + self& operator--() + { + if (cur == first) + { // 如果到达缓冲区的头 + set_node(node - 1); + cur = last; + } + --cur; + return *this; + } + self operator--(int) + { + self tmp = *this; + --*this; + return tmp; + } + + self& operator+=(difference_type n) + { + const auto offset = n + (cur - first); + if (offset >= 0 && offset < static_cast(buffer_size)) + { // 仍在当前缓冲区 + cur += n; + } + else + { // 要跳到其他的缓冲区 + const auto node_offset = offset > 0 + ? offset / static_cast(buffer_size) + : -static_cast((-offset - 1) / buffer_size) - 1; + set_node(node + node_offset); + cur = first + (offset - node_offset * static_cast(buffer_size)); + } + return *this; + } + self operator+(difference_type n) const + { + self tmp = *this; + return tmp += n; + } + self& operator-=(difference_type n) + { + return *this += -n; + } + self operator-(difference_type n) const + { + self tmp = *this; + return tmp -= n; + } + + reference operator[](difference_type n) const { return *(*this + n); } + + // 重载比较操作符 + bool operator==(const self& rhs) const { return cur == rhs.cur; } + bool operator< (const self& rhs) const + { return node == rhs.node ? (cur < rhs.cur) : (node < rhs.node); } + bool operator!=(const self& rhs) const { return !(*this == rhs); } + bool operator> (const self& rhs) const { return rhs < *this; } + bool operator<=(const self& rhs) const { return !(rhs < *this); } + bool operator>=(const self& rhs) const { return !(*this < rhs); } +}; + +// 模板类 deque +// 模板参数代表数据类型 +template +class deque +{ +public: + // deque 的型别定义 + typedef mystl::allocator allocator_type; + typedef mystl::allocator data_allocator; + typedef mystl::allocator map_allocator; + + typedef typename allocator_type::value_type value_type; + typedef typename allocator_type::pointer pointer; + typedef typename allocator_type::const_pointer const_pointer; + typedef typename allocator_type::reference reference; + typedef typename allocator_type::const_reference const_reference; + typedef typename allocator_type::size_type size_type; + typedef typename allocator_type::difference_type difference_type; + typedef pointer* map_pointer; + typedef const_pointer* const_map_pointer; + + typedef deque_iterator iterator; + typedef deque_iterator const_iterator; + typedef mystl::reverse_iterator reverse_iterator; + typedef mystl::reverse_iterator const_reverse_iterator; + + allocator_type get_allocator() { return allocator_type(); } + + static const size_type buffer_size = deque_buf_size::value; + +private: + // 用以下四个数据来表现一个 deque + iterator begin_; // 指向第一个节点 + iterator end_; // 指向最后一个结点 + map_pointer map_; // 指向一块 map,map 中的每个元素都是一个指针,指向一个缓冲区 + size_type map_size_; // map 内指针的数目 + +public: + // 构造、复制、移动、析构函数 + + deque() + { fill_init(0, value_type()); } + + explicit deque(size_type n) + { fill_init(n, value_type()); } + + deque(size_type n, const value_type& value) + { fill_init(n, value); } + + template ::value, int>::type = 0> + deque(IIter first, IIter last) + { copy_init(first, last, iterator_category(first)); } + + deque(std::initializer_list ilist) + { + copy_init(ilist.begin(), ilist.end(), mystl::forward_iterator_tag()); + } + + deque(const deque& rhs) + { + copy_init(rhs.begin(), rhs.end(), mystl::forward_iterator_tag()); + } + deque(deque&& rhs) noexcept + :begin_(mystl::move(rhs.begin_)), + end_(mystl::move(rhs.end_)), + map_(rhs.map_), + map_size_(rhs.map_size_) + { + rhs.map_ = nullptr; + rhs.map_size_ = 0; + } + + deque& operator=(const deque& rhs); + deque& operator=(deque&& rhs); + + deque& operator=(std::initializer_list ilist) + { + deque tmp(ilist); + swap(tmp); + return *this; + } + + ~deque() + { + if (map_ != nullptr) + { + clear(); + data_allocator::deallocate(*begin_.node, buffer_size); + *begin_.node = nullptr; + map_allocator::deallocate(map_, map_size_); + map_ = nullptr; + } + } + +public: + // 迭代器相关操作 + + iterator begin() noexcept + { return begin_; } + const_iterator begin() const noexcept + { return begin_; } + iterator end() noexcept + { return end_; } + const_iterator end() const noexcept + { return end_; } + + reverse_iterator rbegin() noexcept + { return reverse_iterator(end()); } + const_reverse_iterator rbegin() const noexcept + { return reverse_iterator(end()); } + reverse_iterator rend() noexcept + { return reverse_iterator(begin()); } + const_reverse_iterator rend() const noexcept + { return reverse_iterator(begin()); } + + const_iterator cbegin() const noexcept + { return begin(); } + const_iterator cend() const noexcept + { return end(); } + const_reverse_iterator crbegin() const noexcept + { return rbegin(); } + const_reverse_iterator crend() const noexcept + { return rend(); } + + // 容量相关操作 + + bool empty() const noexcept { return begin() == end(); } + size_type size() const noexcept { return end_ - begin_; } + size_type max_size() const noexcept { return static_cast(-1); } + void resize(size_type new_size) { resize(new_size, value_type()); } + void resize(size_type new_size, const value_type& value); + void shrink_to_fit() noexcept; + + // 访问元素相关操作 + reference operator[](size_type n) + { + MYSTL_DEBUG(n < size()); + return begin_[n]; + } + const_reference operator[](size_type n) const + { + MYSTL_DEBUG(n < size()); + return begin_[n]; + } + + reference at(size_type n) + { + THROW_OUT_OF_RANGE_IF(!(n < size()), "deque::at() subscript out of range"); + return (*this)[n]; + } + const_reference at(size_type n) const + { + THROW_OUT_OF_RANGE_IF(!(n < size()), "deque::at() subscript out of range"); + return (*this)[n]; + } + + reference front() + { + MYSTL_DEBUG(!empty()); + return *begin(); + } + const_reference front() const + { + MYSTL_DEBUG(!empty()); + return *begin(); + } + reference back() + { + MYSTL_DEBUG(!empty()); + return *(end() - 1); + } + const_reference back() const + { + MYSTL_DEBUG(!empty()); + return *(end() - 1); + } + + // 修改容器相关操作 + + // assign + + void assign(size_type n, const value_type& value) + { fill_assign(n, value); } + + template ::value, int>::type = 0> + void assign(IIter first, IIter last) + { copy_assign(first, last, iterator_category(first)); } + + void assign(std::initializer_list ilist) + { copy_assign(ilist.begin(), ilist.end(), mystl::forward_iterator_tag{}); } + + // emplace_front / emplace_back / emplace + + template + void emplace_front(Args&& ...args); + template + void emplace_back(Args&& ...args); + template + iterator emplace(iterator pos, Args&& ...args); + + // push_front / push_back + + void push_front(const value_type& value); + void push_back(const value_type& value); + + void push_front(value_type&& value) { emplace_front(mystl::move(value)); } + void push_back(value_type&& value) { emplace_back(mystl::move(value)); } + + // pop_back / pop_front + + void pop_front(); + void pop_back(); + + // insert + + iterator insert(iterator position, const value_type& value); + iterator insert(iterator position, value_type&& value); + void insert(iterator position, size_type n, const value_type& value); + template ::value, int>::type = 0> + void insert(iterator position, IIter first, IIter last) + { insert_dispatch(position, first, last, iterator_category(first)); } + + // erase /clear + + iterator erase(iterator position); + iterator erase(iterator first, iterator last); + void clear(); + + // swap + + void swap(deque& rhs) noexcept; + +private: + // helper functions + + // create node / destroy node + map_pointer create_map(size_type size); + void create_buffer(map_pointer nstart, map_pointer nfinish); + void destroy_buffer(map_pointer nstart, map_pointer nfinish); + + // initialize + void map_init(size_type nelem); + void fill_init(size_type n, const value_type& value); + template + void copy_init(IIter, IIter, input_iterator_tag); + template + void copy_init(FIter, FIter, forward_iterator_tag); + + // assign + void fill_assign(size_type n, const value_type& value); + template + void copy_assign(IIter first, IIter last, input_iterator_tag); + template + void copy_assign(FIter first, FIter last, forward_iterator_tag); + + // insert + template + iterator insert_aux(iterator position, Args&& ...args); + void fill_insert(iterator position, size_type n, const value_type& x); + template + void copy_insert(iterator, FIter, FIter, size_type); + template + void insert_dispatch(iterator, IIter, IIter, input_iterator_tag); + template + void insert_dispatch(iterator, FIter, FIter, forward_iterator_tag); + + // reallocate + void require_capacity(size_type n, bool front); + void reallocate_map_at_front(size_type need); + void reallocate_map_at_back(size_type need); + +}; + +/*****************************************************************************************/ + +// 复制赋值运算符 +template +deque& deque::operator=(const deque& rhs) +{ + if (this != &rhs) + { + const auto len = size(); + if (len >= rhs.size()) + { + erase(mystl::copy(rhs.begin_, rhs.end_, begin_), end_); + } + else + { + iterator mid = rhs.begin() + static_cast(len); + mystl::copy(rhs.begin_, mid, begin_); + insert(end_, mid, rhs.end_); + } + } + return *this; +} + +// 移动赋值运算符 +template +deque& deque::operator=(deque&& rhs) +{ + clear(); + begin_ = mystl::move(rhs.begin_); + end_ = mystl::move(rhs.end_); + map_ = rhs.map_; + map_size_ = rhs.map_size_; + rhs.map_ = nullptr; + rhs.map_size_ = 0; + return *this; +} + +// 重置容器大小 +template +void deque::resize(size_type new_size, const value_type& value) +{ + const auto len = size(); + if (new_size < len) + { + erase(begin_ + new_size, end_); + } + else + { + insert(end_, new_size - len, value); + } +} + +// 减小容器容量 +template +void deque::shrink_to_fit() noexcept +{ + // 至少会留下头部缓冲区 + for (auto cur = map_; cur < begin_.node; ++cur) + { + data_allocator::deallocate(*cur, buffer_size); + *cur = nullptr; + } + for (auto cur = end_.node + 1; cur < map_ + map_size_; ++cur) + { + data_allocator::deallocate(*cur, buffer_size); + *cur = nullptr; + } +} + +// 在头部就地构建元素 +template +template +void deque::emplace_front(Args&& ...args) +{ + if (begin_.cur != begin_.first) + { + data_allocator::construct(begin_.cur - 1, mystl::forward(args)...); + --begin_.cur; + } + else + { + require_capacity(1, true); + try + { + --begin_; + data_allocator::construct(begin_.cur, mystl::forward(args)...); + } + catch (...) + { + ++begin_; + throw; + } + } +} + +// 在尾部就地构建元素 +template +template +void deque::emplace_back(Args&& ...args) +{ + if (end_.cur != end_.last - 1) + { + data_allocator::construct(end_.cur, mystl::forward(args)...); + ++end_.cur; + } + else + { + require_capacity(1, false); + data_allocator::construct(end_.cur, mystl::forward(args)...); + ++end_; + } +} + +// 在 pos 位置就地构建元素 +template +template +typename deque::iterator deque::emplace(iterator pos, Args&& ...args) +{ + if (pos.cur == begin_.cur) + { + emplace_front(mystl::forward(args)...); + return begin_; + } + else if (pos.cur == end_.cur) + { + emplace_back(mystl::forward(args)...); + return end_ - 1; + } + return insert_aux(pos, mystl::forward(args)...); +} + +// 在头部插入元素 +template +void deque::push_front(const value_type& value) +{ + if (begin_.cur != begin_.first) + { + data_allocator::construct(begin_.cur - 1, value); + --begin_.cur; + } + else + { + require_capacity(1, true); + try + { + --begin_; + data_allocator::construct(begin_.cur, value); + } + catch (...) + { + ++begin_; + throw; + } + } +} + +// 在尾部插入元素 +template +void deque::push_back(const value_type& value) +{ + if (end_.cur != end_.last - 1) + { + data_allocator::construct(end_.cur, value); + ++end_.cur; + } + else + { + require_capacity(1, false); + data_allocator::construct(end_.cur, value); + ++end_; + } +} + +// 弹出头部元素 +template +void deque::pop_front() +{ + MYSTL_DEBUG(!empty()); + if (begin_.cur != begin_.last - 1) + { + data_allocator::destroy(begin_.cur); + ++begin_.cur; + } + else + { + data_allocator::destroy(begin_.cur); + ++begin_; + destroy_buffer(begin_.node - 1, begin_.node - 1); + } +} + +// 弹出尾部元素 +template +void deque::pop_back() +{ + MYSTL_DEBUG(!empty()); + if (end_.cur != end_.first) + { + --end_.cur; + data_allocator::destroy(end_.cur); + } + else + { + --end_; + data_allocator::destroy(end_.cur); + destroy_buffer(end_.node + 1, end_.node + 1); + } +} + +// 在 position 处插入元素 +template +typename deque::iterator +deque::insert(iterator position, const value_type& value) +{ + if (position.cur == begin_.cur) + { + push_front(value); + return begin_; + } + else if (position.cur == end_.cur) + { + push_back(value); + auto tmp = end_; + --tmp; + return tmp; + } + else + { + return insert_aux(position, value); + } +} + +template +typename deque::iterator +deque::insert(iterator position, value_type&& value) +{ + if (position.cur == begin_.cur) + { + emplace_front(mystl::move(value)); + return begin_; + } + else if (position.cur == end_.cur) + { + emplace_back(mystl::move(value)); + auto tmp = end_; + --tmp; + return tmp; + } + else + { + return insert_aux(position, mystl::move(value)); + } +} + +// 在 position 位置插入 n 个元素 +template +void deque::insert(iterator position, size_type n, const value_type& value) +{ + if (position.cur == begin_.cur) + { + require_capacity(n, true); + auto new_begin = begin_ - n; + mystl::uninitialized_fill_n(new_begin, n, value); + begin_ = new_begin; + } + else if (position.cur == end_.cur) + { + require_capacity(n, false); + auto new_end = end_ + n; + mystl::uninitialized_fill_n(end_, n, value); + end_ = new_end; + } + else + { + fill_insert(position, n, value); + } +} + +// 删除 position 处的元素 +template +typename deque::iterator +deque::erase(iterator position) +{ + auto next = position; + ++next; + const size_type elems_before = position - begin_; + if (elems_before < (size() / 2)) + { + mystl::copy_backward(begin_, position, next); + pop_front(); + } + else + { + mystl::copy(next, end_, position); + pop_back(); + } + return begin_ + elems_before; +} + +// 删除[first, last)上的元素 +template +typename deque::iterator +deque::erase(iterator first, iterator last) +{ + if (first == begin_ && last == end_) + { + clear(); + return end_; + } + else + { + const size_type len = last - first; + const size_type elems_before = first - begin_; + if (elems_before < ((size() - len) / 2)) + { + mystl::copy_backward(begin_, first, last); + auto new_begin = begin_ + len; + data_allocator::destroy(begin_.cur, new_begin.cur); + begin_ = new_begin; + } + else + { + mystl::copy(last, end_, first); + auto new_end = end_ - len; + data_allocator::destroy(new_end.cur, end_.cur); + end_ = new_end; + } + return begin_ + elems_before; + } +} + +// 清空 deque +template +void deque::clear() +{ + // clear 会保留头部的缓冲区 + for (map_pointer cur = begin_.node + 1; cur < end_.node; ++cur) + { + data_allocator::destroy(*cur, *cur + buffer_size); + } + if (begin_.node != end_.node) + { // 有两个以上的缓冲区 + mystl::destroy(begin_.cur, begin_.last); + mystl::destroy(end_.first, end_.cur); + } + else + { + mystl::destroy(begin_.cur, end_.cur); + } + shrink_to_fit(); + end_ = begin_; +} + +// 交换两个 deque +template +void deque::swap(deque& rhs) noexcept +{ + if (this != &rhs) + { + mystl::swap(begin_, rhs.begin_); + mystl::swap(end_, rhs.end_); + mystl::swap(map_, rhs.map_); + mystl::swap(map_size_, rhs.map_size_); + } +} + +/*****************************************************************************************/ +// helper function + +template +typename deque::map_pointer +deque::create_map(size_type size) +{ + map_pointer mp = nullptr; + mp = map_allocator::allocate(size); + for (size_type i = 0; i < size; ++i) + *(mp + i) = nullptr; + return mp; +} + +// create_buffer 函数 +template +void deque:: +create_buffer(map_pointer nstart, map_pointer nfinish) +{ + map_pointer cur; + try + { + for (cur = nstart; cur <= nfinish; ++cur) + { + *cur = data_allocator::allocate(buffer_size); + } + } + catch (...) + { + while (cur != nstart) + { + --cur; + data_allocator::deallocate(*cur, buffer_size); + *cur = nullptr; + } + throw; + } +} + +// destroy_buffer 函数 +template +void deque:: +destroy_buffer(map_pointer nstart, map_pointer nfinish) +{ + for (map_pointer n = nstart; n <= nfinish; ++n) + { + data_allocator::deallocate(*n, buffer_size); + *n = nullptr; + } +} + +// map_init 函数 +template +void deque:: +map_init(size_type nElem) +{ + const size_type nNode = nElem / buffer_size + 1; // 需要分配的缓冲区个数 + map_size_ = mystl::max(static_cast(DEQUE_MAP_INIT_SIZE), nNode + 2); + try + { + map_ = create_map(map_size_); + } + catch (...) + { + map_ = nullptr; + map_size_ = 0; + throw; + } + + // 让 nstart 和 nfinish 都指向 map_ 最中央的区域,方便向头尾扩充 + map_pointer nstart = map_ + (map_size_ - nNode) / 2; + map_pointer nfinish = nstart + nNode - 1; + try + { + create_buffer(nstart, nfinish); + } + catch (...) + { + map_allocator::deallocate(map_, map_size_); + map_ = nullptr; + map_size_ = 0; + throw; + } + begin_.set_node(nstart); + end_.set_node(nfinish); + begin_.cur = begin_.first; + end_.cur = end_.first + (nElem % buffer_size); +} + +// fill_init 函数 +template +void deque:: +fill_init(size_type n, const value_type& value) +{ + map_init(n); + if (n != 0) + { + for (auto cur = begin_.node; cur < end_.node; ++cur) + { + mystl::uninitialized_fill(*cur, *cur + buffer_size, value); + } + mystl::uninitialized_fill(end_.first, end_.cur, value); + } +} + +// copy_init 函数 +template +template +void deque:: +copy_init(IIter first, IIter last, input_iterator_tag) +{ + const size_type n = mystl::distance(first, last); + map_init(n); + for (; first != last; ++first) + emplace_back(*first); +} + +template +template +void deque:: +copy_init(FIter first, FIter last, forward_iterator_tag) +{ + const size_type n = mystl::distance(first, last); + map_init(n); + for (auto cur = begin_.node; cur < end_.node; ++cur) + { + auto next = first; + mystl::advance(next, buffer_size); + mystl::uninitialized_copy(first, next, *cur); + first = next; + } + mystl::uninitialized_copy(first, last, end_.first); +} + +// fill_assign 函数 +template +void deque:: +fill_assign(size_type n, const value_type& value) +{ + if (n > size()) + { + mystl::fill(begin(), end(), value); + insert(end(), n - size(), value); + } + else + { + erase(begin() + n, end()); + mystl::fill(begin(), end(), value); + } +} + +// copy_assign 函数 +template +template +void deque:: +copy_assign(IIter first, IIter last, input_iterator_tag) +{ + auto first1 = begin(); + auto last1 = end(); + for (; first != last && first1 != last1; ++first, ++first1) + { + *first1 = *first; + } + if (first1 != last1) + { + erase(first1, last1); + } + else + { + insert_dispatch(end_, first, last, input_iterator_tag{}); + } +} + +template +template +void deque:: +copy_assign(FIter first, FIter last, forward_iterator_tag) +{ + const size_type len1 = size(); + const size_type len2 = mystl::distance(first, last); + if (len1 < len2) + { + auto next = first; + mystl::advance(next, len1); + mystl::copy(first, next, begin_); + insert_dispatch(end_, next, last, forward_iterator_tag{}); + } + else + { + erase(mystl::copy(first, last, begin_), end_); + } +} + +// insert_aux 函数 +template +template +typename deque::iterator +deque:: +insert_aux(iterator position, Args&& ...args) +{ + const size_type elems_before = position - begin_; + value_type value_copy = value_type(mystl::forward(args)...); + if (elems_before < (size() / 2)) + { // 在前半段插入 + emplace_front(front()); + auto front1 = begin_; + ++front1; + auto front2 = front1; + ++front2; + position = begin_ + elems_before; + auto pos = position; + ++pos; + mystl::copy(front2, pos, front1); + } + else + { // 在后半段插入 + emplace_back(back()); + auto back1 = end_; + --back1; + auto back2 = back1; + --back2; + position = begin_ + elems_before; + mystl::copy_backward(position, back2, back1); + } + *position = mystl::move(value_copy); + return position; +} + +// fill_insert 函数 +template +void deque:: +fill_insert(iterator position, size_type n, const value_type& value) +{ + const size_type elems_before = position - begin_; + const size_type len = size(); + auto value_copy = value; + if (elems_before < (len / 2)) + { + require_capacity(n, true); + // 原来的迭代器可能会失效 + auto old_begin = begin_; + auto new_begin = begin_ - n; + position = begin_ + elems_before; + try + { + if (elems_before >= n) + { + auto begin_n = begin_ + n; + mystl::uninitialized_copy(begin_, begin_n, new_begin); + begin_ = new_begin; + mystl::copy(begin_n, position, old_begin); + mystl::fill(position - n, position, value_copy); + } + else + { + mystl::uninitialized_fill( + mystl::uninitialized_copy(begin_, position, new_begin), begin_, value_copy); + begin_ = new_begin; + mystl::fill(old_begin, position, value_copy); + } + } + catch (...) + { + if (new_begin.node != begin_.node) + destroy_buffer(new_begin.node, begin_.node - 1); + throw; + } + } + else + { + require_capacity(n, false); + // 原来的迭代器可能会失效 + auto old_end = end_; + auto new_end = end_ + n; + const size_type elems_after = len - elems_before; + position = end_ - elems_after; + try + { + if (elems_after > n) + { + auto end_n = end_ - n; + mystl::uninitialized_copy(end_n, end_, end_); + end_ = new_end; + mystl::copy_backward(position, end_n, old_end); + mystl::fill(position, position + n, value_copy); + } + else + { + mystl::uninitialized_fill(end_, position + n, value_copy); + mystl::uninitialized_copy(position, end_, position + n); + end_ = new_end; + mystl::fill(position, old_end, value_copy); + } + } + catch (...) + { + if(new_end.node != end_.node) + destroy_buffer(end_.node + 1, new_end.node); + throw; + } + } +} + +// copy_insert +template +template +void deque:: +copy_insert(iterator position, FIter first, FIter last, size_type n) +{ + const size_type elems_before = position - begin_; + auto len = size(); + if (elems_before < (len / 2)) + { + require_capacity(n, true); + // 原来的迭代器可能会失效 + auto old_begin = begin_; + auto new_begin = begin_ - n; + position = begin_ + elems_before; + try + { + if (elems_before >= n) + { + auto begin_n = begin_ + n; + mystl::uninitialized_copy(begin_, begin_n, new_begin); + begin_ = new_begin; + mystl::copy(begin_n, position, old_begin); + mystl::copy(first, last, position - n); + } + else + { + auto mid = first; + mystl::advance(mid, n - elems_before); + mystl::uninitialized_copy(first, mid, + mystl::uninitialized_copy(begin_, position, new_begin)); + begin_ = new_begin; + mystl::copy(mid, last, old_begin); + } + } + catch (...) + { + if(new_begin.node != begin_.node) + destroy_buffer(new_begin.node, begin_.node - 1); + throw; + } + } + else + { + require_capacity(n, false); + // 原来的迭代器可能会失效 + auto old_end = end_; + auto new_end = end_ + n; + const auto elems_after = len - elems_before; + position = end_ - elems_after; + try + { + if (elems_after > n) + { + auto end_n = end_ - n; + mystl::uninitialized_copy(end_n, end_, end_); + end_ = new_end; + mystl::copy_backward(position, end_n, old_end); + mystl::copy(first, last, position); + } + else + { + auto mid = first; + mystl::advance(mid, elems_after); + mystl::uninitialized_copy(position, end_, + mystl::uninitialized_copy(mid, last, end_)); + end_ = new_end; + mystl::copy(first, mid, position); + } + } + catch (...) + { + if(new_end.node != end_.node) + destroy_buffer(end_.node + 1, new_end.node); + throw; + } + } +} + +// insert_dispatch 函数 +template +template +void deque:: +insert_dispatch(iterator position, IIter first, IIter last, input_iterator_tag) +{ + if (last <= first) return; + const size_type n = mystl::distance(first, last); + const size_type elems_before = position - begin_; + if (elems_before < (size() / 2)) + { + require_capacity(n, true); + } + else + { + require_capacity(n, false); + } + position = begin_ + elems_before; + auto cur = --last; + for (size_type i = 0; i < n; ++i, --cur) + { + insert(position, *cur); + } +} + +template +template +void deque:: +insert_dispatch(iterator position, FIter first, FIter last, forward_iterator_tag) +{ + if (last <= first) return; + const size_type n = mystl::distance(first, last); + if (position.cur == begin_.cur) + { + require_capacity(n, true); + auto new_begin = begin_ - n; + try + { + mystl::uninitialized_copy(first, last, new_begin); + begin_ = new_begin; + } + catch (...) + { + if(new_begin.node != begin_.node) + destroy_buffer(new_begin.node, begin_.node - 1); + throw; + } + } + else if (position.cur == end_.cur) + { + require_capacity(n, false); + auto new_end = end_ + n; + try + { + mystl::uninitialized_copy(first, last, end_); + end_ = new_end; + } + catch (...) + { + if(new_end.node != end_.node) + destroy_buffer(end_.node + 1, new_end.node); + throw; + } + } + else + { + copy_insert(position, first, last, n); + } +} + +// require_capacity 函数 +template +void deque::require_capacity(size_type n, bool front) +{ + if (front && (static_cast(begin_.cur - begin_.first) < n)) + { + const size_type need_buffer = (n - (begin_.cur - begin_.first)) / buffer_size + 1; + if (need_buffer > static_cast(begin_.node - map_)) + { + reallocate_map_at_front(need_buffer); + return; + } + create_buffer(begin_.node - need_buffer, begin_.node - 1); + } + else if (!front && (static_cast(end_.last - end_.cur - 1) < n)) + { + const size_type need_buffer = (n - (end_.last - end_.cur - 1)) / buffer_size + 1; + if (need_buffer > static_cast((map_ + map_size_) - end_.node - 1)) + { + reallocate_map_at_back(need_buffer); + return; + } + create_buffer(end_.node + 1, end_.node + need_buffer); + } +} + +// reallocate_map_at_front 函数 +template +void deque::reallocate_map_at_front(size_type need_buffer) +{ + const size_type new_map_size = mystl::max(map_size_ << 1, + map_size_ + need_buffer + DEQUE_MAP_INIT_SIZE); + map_pointer new_map = create_map(new_map_size); + const size_type old_buffer = end_.node - begin_.node + 1; + const size_type new_buffer = old_buffer + need_buffer; + + // 另新的 map 中的指针指向原来的 buffer,并开辟新的 buffer + auto begin = new_map + (new_map_size - new_buffer) / 2; + auto mid = begin + need_buffer; + auto end = mid + old_buffer; + create_buffer(begin, mid - 1); + for (auto begin1 = mid, begin2 = begin_.node; begin1 != end; ++begin1, ++begin2) + *begin1 = *begin2; + + // 更新数据 + map_allocator::deallocate(map_, map_size_); + map_ = new_map; + map_size_ = new_map_size; + begin_ = iterator(*mid + (begin_.cur - begin_.first), mid); + end_ = iterator(*(end - 1) + (end_.cur - end_.first), end - 1); +} + +// reallocate_map_at_back 函数 +template +void deque::reallocate_map_at_back(size_type need_buffer) +{ + const size_type new_map_size = mystl::max(map_size_ << 1, + map_size_ + need_buffer + DEQUE_MAP_INIT_SIZE); + map_pointer new_map = create_map(new_map_size); + const size_type old_buffer = end_.node - begin_.node + 1; + const size_type new_buffer = old_buffer + need_buffer; + + // 另新的 map 中的指针指向原来的 buffer,并开辟新的 buffer + auto begin = new_map + ((new_map_size - new_buffer) / 2); + auto mid = begin + old_buffer; + auto end = mid + need_buffer; + for (auto begin1 = begin, begin2 = begin_.node; begin1 != mid; ++begin1, ++begin2) + *begin1 = *begin2; + create_buffer(mid, end - 1); + + // 更新数据 + map_allocator::deallocate(map_, map_size_); + map_ = new_map; + map_size_ = new_map_size; + begin_ = iterator(*begin + (begin_.cur - begin_.first), begin); + end_ = iterator(*(mid - 1) + (end_.cur - end_.first), mid - 1); +} + +// 重载比较操作符 +template +bool operator==(const deque& lhs, const deque& rhs) +{ + return lhs.size() == rhs.size() && + mystl::equal(lhs.begin(), lhs.end(), rhs.begin()); +} + +template +bool operator<(const deque& lhs, const deque& rhs) +{ + return mystl::lexicographical_compare( + lhs.begin(), lhs.end(), rhs.begin(), rhs.end()); +} + +template +bool operator!=(const deque& lhs, const deque& rhs) +{ + return !(lhs == rhs); +} + +template +bool operator>(const deque& lhs, const deque& rhs) +{ + return rhs < lhs; +} + +template +bool operator<=(const deque& lhs, const deque& rhs) +{ + return !(rhs < lhs); +} + +template +bool operator>=(const deque& lhs, const deque& rhs) +{ + return !(lhs < rhs); +} + +// 重载 mystl 的 swap +template +void swap(deque& lhs, deque& rhs) +{ + lhs.swap(rhs); +} + +} // namespace mystl +#endif // !MYTINYSTL_DEQUE_H_ + diff --git a/src/MyTinySTL-master/MyTinySTL-master/MyTinySTL/exceptdef.h b/src/MyTinySTL-master/MyTinySTL-master/MyTinySTL/exceptdef.h new file mode 100755 index 0000000..ef8b983 --- /dev/null +++ b/src/MyTinySTL-master/MyTinySTL-master/MyTinySTL/exceptdef.h @@ -0,0 +1,26 @@ +#ifndef MYTINYSTL_EXCEPTDEF_H_ +#define MYTINYSTL_EXCEPTDEF_H_ + +#include + +#include + +namespace mystl +{ + +#define MYSTL_DEBUG(expr) \ + assert(expr) + +#define THROW_LENGTH_ERROR_IF(expr, what) \ + if ((expr)) throw std::length_error(what) + +#define THROW_OUT_OF_RANGE_IF(expr, what) \ + if ((expr)) throw std::out_of_range(what) + +#define THROW_RUNTIME_ERROR_IF(expr, what) \ + if ((expr)) throw std::runtime_error(what) + +} // namepsace mystl + +#endif // !MYTINYSTL_EXCEPTDEF_H_ + diff --git a/src/MyTinySTL-master/MyTinySTL-master/MyTinySTL/functional.h b/src/MyTinySTL-master/MyTinySTL-master/MyTinySTL/functional.h new file mode 100755 index 0000000..b445017 --- /dev/null +++ b/src/MyTinySTL-master/MyTinySTL-master/MyTinySTL/functional.h @@ -0,0 +1,285 @@ +#ifndef MYTINYSTL_FUNCTIONAL_H_ +#define MYTINYSTL_FUNCTIONAL_H_ + +// 这个头文件包含了 mystl 的函数对象与哈希函数 + +#include + +namespace mystl +{ + +// 定义一元函数的参数型别和返回值型别 +template +struct unarg_function +{ + typedef Arg argument_type; + typedef Result result_type; +}; + +// 定义二元函数的参数型别的返回值型别 +template +struct binary_function +{ + typedef Arg1 first_argument_type; + typedef Arg2 second_argument_type; + typedef Result result_type; +}; + +// 函数对象:加法 +template +struct plus :public binary_function +{ + T operator()(const T& x, const T& y) const { return x + y; } +}; + +// 函数对象:减法 +template +struct minus :public binary_function +{ + T operator()(const T& x, const T& y) const { return x - y; } +}; + +// 函数对象:乘法 +template +struct multiplies :public binary_function +{ + T operator()(const T& x, const T& y) const { return x * y; } +}; + +// 函数对象:除法 +template +struct divides :public binary_function +{ + T operator()(const T& x, const T& y) const { return x / y; } +}; + +// 函数对象:模取 +template +struct modulus :public binary_function +{ + T operator()(const T& x, const T& y) const { return x % y; } +}; + +// 函数对象:否定 +template +struct negate :public unarg_function +{ + T operator()(const T& x) const { return -x; } +}; + +// 加法的证同元素 +template +T identity_element(plus) { return T(0); } + +// 乘法的证同元素 +template +T identity_element(multiplies) { return T(1); } + +// 函数对象:等于 +template +struct equal_to :public binary_function +{ + bool operator()(const T& x, const T& y) const { return x == y; } +}; + +// 函数对象:不等于 +template +struct not_equal_to :public binary_function +{ + bool operator()(const T& x, const T& y) const { return x != y; } +}; + +// 函数对象:大于 +template +struct greater :public binary_function +{ + bool operator()(const T& x, const T& y) const { return x > y; } +}; + +// 函数对象:小于 +template +struct less :public binary_function +{ + bool operator()(const T& x, const T& y) const { return x < y; } +}; + +// 函数对象:大于等于 +template +struct greater_equal :public binary_function +{ + bool operator()(const T& x, const T& y) const { return x >= y; } +}; + +// 函数对象:小于等于 +template +struct less_equal :public binary_function +{ + bool operator()(const T& x, const T& y) const { return x <= y; } +}; + +// 函数对象:逻辑与 +template +struct logical_and :public binary_function +{ + bool operator()(const T& x, const T& y) const { return x && y; } +}; + +// 函数对象:逻辑或 +template +struct logical_or :public binary_function +{ + bool operator()(const T& x, const T& y) const { return x || y; } +}; + +// 函数对象:逻辑非 +template +struct logical_not :public unarg_function +{ + bool operator()(const T& x) const { return !x; } +}; + +// 证同函数:不会改变元素,返回本身 +template +struct identity :public unarg_function +{ + const T& operator()(const T& x) const { return x; } +}; + +// 选择函数:接受一个 pair,返回第一个元素 +template +struct selectfirst :public unarg_function +{ + const typename Pair::first_type& operator()(const Pair& x) const + { + return x.first; + } +}; + +// 选择函数:接受一个 pair,返回第二个元素 +template +struct selectsecond :public unarg_function +{ + const typename Pair::second_type& operator()(const Pair& x) const + { + return x.second; + } +}; + +// 投射函数:返回第一参数 +template +struct projectfirst :public binary_function +{ + Arg1 operator()(const Arg1& x, const Arg2&) const { return x; } +}; + +// 投射函数:返回第二参数 +template +struct projectsecond :public binary_function +{ + Arg2 operator()(const Arg1&, const Arg2& y) const { return y; } +}; + +/*****************************************************************************************/ +// 哈希函数对象 + +// 对于大部分类型,hash function 什么都不做 +template +struct hash {}; + +// 针对指针的偏特化版本 +template +struct hash +{ + size_t operator()(T* p) const noexcept + { return reinterpret_cast(p); } +}; + +// 对于整型类型,只是返回原值 +#define MYSTL_TRIVIAL_HASH_FCN(Type) \ +template <> struct hash \ +{ \ + size_t operator()(Type val) const noexcept \ + { return static_cast(val); } \ +}; + +MYSTL_TRIVIAL_HASH_FCN(bool) + +MYSTL_TRIVIAL_HASH_FCN(char) + +MYSTL_TRIVIAL_HASH_FCN(signed char) + +MYSTL_TRIVIAL_HASH_FCN(unsigned char) + +MYSTL_TRIVIAL_HASH_FCN(wchar_t) + +MYSTL_TRIVIAL_HASH_FCN(char16_t) + +MYSTL_TRIVIAL_HASH_FCN(char32_t) + +MYSTL_TRIVIAL_HASH_FCN(short) + +MYSTL_TRIVIAL_HASH_FCN(unsigned short) + +MYSTL_TRIVIAL_HASH_FCN(int) + +MYSTL_TRIVIAL_HASH_FCN(unsigned int) + +MYSTL_TRIVIAL_HASH_FCN(long) + +MYSTL_TRIVIAL_HASH_FCN(unsigned long) + +MYSTL_TRIVIAL_HASH_FCN(long long) + +MYSTL_TRIVIAL_HASH_FCN(unsigned long long) + +#undef MYSTL_TRIVIAL_HASH_FCN + +// 对于浮点数,逐位哈希 +inline size_t bitwise_hash(const unsigned char* first, size_t count) +{ +#if (_MSC_VER && _WIN64) || ((__GNUC__ || __clang__) &&__SIZEOF_POINTER__ == 8) + const size_t fnv_offset = 14695981039346656037ull; + const size_t fnv_prime = 1099511628211ull; +#else + const size_t fnv_offset = 2166136261u; + const size_t fnv_prime = 16777619u; +#endif + size_t result = fnv_offset; + for (size_t i = 0; i < count; ++i) + { + result ^= (size_t)first[i]; + result *= fnv_prime; + } + return result; +} + +template <> +struct hash +{ + size_t operator()(const float& val) + { + return val == 0.0f ? 0 : bitwise_hash((const unsigned char*)&val, sizeof(float)); + } +}; + +template <> +struct hash +{ + size_t operator()(const double& val) + { + return val == 0.0f ? 0 : bitwise_hash((const unsigned char*)&val, sizeof(double)); + } +}; + +template <> +struct hash +{ + size_t operator()(const long double& val) + { + return val == 0.0f ? 0 : bitwise_hash((const unsigned char*)&val, sizeof(long double)); + } +}; + +} // namespace mystl +#endif // !MYTINYSTL_FUNCTIONAL_H_ + diff --git a/src/MyTinySTL-master/MyTinySTL-master/MyTinySTL/hashtable.h b/src/MyTinySTL-master/MyTinySTL-master/MyTinySTL/hashtable.h new file mode 100755 index 0000000..9296fc2 --- /dev/null +++ b/src/MyTinySTL-master/MyTinySTL-master/MyTinySTL/hashtable.h @@ -0,0 +1,1609 @@ +#ifndef MYTINYSTL_HASHTABLE_H_ +#define MYTINYSTL_HASHTABLE_H_ + +// 这个头文件包含了一个模板类 hashtable +// hashtable : 哈希表,使用开链法处理冲突 + +#include + +#include "algo.h" +#include "functional.h" +#include "memory.h" +#include "vector.h" +#include "util.h" +#include "exceptdef.h" + +namespace mystl +{ + +// hashtable 的节点定义 +template +struct hashtable_node +{ + hashtable_node* next; // 指向下一个节点 + T value; // 储存实值 + + hashtable_node() = default; + hashtable_node(const T& n) :next(nullptr), value(n) {} + + hashtable_node(const hashtable_node& node) :next(node.next), value(node.value) {} + hashtable_node(hashtable_node&& node) :next(node.next), value(mystl::move(node.value)) + { + node.next = nullptr; + } +}; + +// value traits +template +struct ht_value_traits_imp +{ + typedef T key_type; + typedef T mapped_type; + typedef T value_type; + + template + static const key_type& get_key(const Ty& value) + { + return value; + } + + template + static const value_type& get_value(const Ty& value) + { + return value; + } +}; + +template +struct ht_value_traits_imp +{ + typedef typename std::remove_cv::type key_type; + typedef typename T::second_type mapped_type; + typedef T value_type; + + template + static const key_type& get_key(const Ty& value) + { + return value.first; + } + + template + static const value_type& get_value(const Ty& value) + { + return value; + } +}; + +template +struct ht_value_traits +{ + static constexpr bool is_map = mystl::is_pair::value; + + typedef ht_value_traits_imp value_traits_type; + + typedef typename value_traits_type::key_type key_type; + typedef typename value_traits_type::mapped_type mapped_type; + typedef typename value_traits_type::value_type value_type; + + template + static const key_type& get_key(const Ty& value) + { + return value_traits_type::get_key(value); + } + + template + static const value_type& get_value(const Ty& value) + { + return value_traits_type::get_value(value); + } +}; + + +// forward declaration + +template +class hashtable; + +template +struct ht_iterator; + +template +struct ht_const_iterator; + +template +struct ht_local_iterator; + +template +struct ht_const_local_iterator; + +// ht_iterator + +template +struct ht_iterator_base :public mystl::iterator +{ + typedef mystl::hashtable hashtable; + typedef ht_iterator_base base; + typedef mystl::ht_iterator iterator; + typedef mystl::ht_const_iterator const_iterator; + typedef hashtable_node* node_ptr; + typedef hashtable* contain_ptr; + typedef const node_ptr const_node_ptr; + typedef const contain_ptr const_contain_ptr; + + typedef size_t size_type; + typedef ptrdiff_t difference_type; + + node_ptr node; // 迭代器当前所指节点 + contain_ptr ht; // 保持与容器的连结 + + ht_iterator_base() = default; + + bool operator==(const base& rhs) const { return node == rhs.node; } + bool operator!=(const base& rhs) const { return node != rhs.node; } +}; + +template +struct ht_iterator :public ht_iterator_base +{ + typedef ht_iterator_base base; + typedef typename base::hashtable hashtable; + typedef typename base::iterator iterator; + typedef typename base::const_iterator const_iterator; + typedef typename base::node_ptr node_ptr; + typedef typename base::contain_ptr contain_ptr; + + typedef ht_value_traits value_traits; + typedef T value_type; + typedef value_type* pointer; + typedef value_type& reference; + + using base::node; + using base::ht; + + ht_iterator() = default; + ht_iterator(node_ptr n, contain_ptr t) + { + node = n; + ht = t; + } + ht_iterator(const iterator& rhs) + { + node = rhs.node; + ht = rhs.ht; + } + ht_iterator(const const_iterator& rhs) + { + node = rhs.node; + ht = rhs.ht; + } + iterator& operator=(const iterator& rhs) + { + if (this != &rhs) + { + node = rhs.node; + ht = rhs.ht; + } + return *this; + } + iterator& operator=(const const_iterator& rhs) + { + if (this != &rhs) + { + node = rhs.node; + ht = rhs.ht; + } + return *this; + } + + // 重载操作符 + reference operator*() const { return node->value; } + pointer operator->() const { return &(operator*()); } + + iterator& operator++() + { + MYSTL_DEBUG(node != nullptr); + const node_ptr old = node; + node = node->next; + if (node == nullptr) + { // 如果下一个位置为空,跳到下一个 bucket 的起始处 + auto index = ht->hash(value_traits::get_key(old->value)); + while (!node && ++index < ht->bucket_size_) + node = ht->buckets_[index]; + } + return *this; + } + iterator operator++(int) + { + iterator tmp = *this; + ++*this; + return tmp; + } +}; + +template +struct ht_const_iterator :public ht_iterator_base +{ + typedef ht_iterator_base base; + typedef typename base::hashtable hashtable; + typedef typename base::iterator iterator; + typedef typename base::const_iterator const_iterator; + typedef typename base::const_node_ptr node_ptr; + typedef typename base::const_contain_ptr contain_ptr; + + typedef ht_value_traits value_traits; + typedef T value_type; + typedef const value_type* pointer; + typedef const value_type& reference; + + using base::node; + using base::ht; + + ht_const_iterator() = default; + ht_const_iterator(node_ptr n, contain_ptr t) + { + node = n; + ht = t; + } + ht_const_iterator(const iterator& rhs) + { + node = rhs.node; + ht = rhs.ht; + } + ht_const_iterator(const const_iterator& rhs) + { + node = rhs.node; + ht = rhs.ht; + } + const_iterator& operator=(const iterator& rhs) + { + if (this != &rhs) + { + node = rhs.node; + ht = rhs.ht; + } + return *this; + } + const_iterator& operator=(const const_iterator& rhs) + { + if (this != &rhs) + { + node = rhs.node; + ht = rhs.ht; + } + return *this; + } + + // 重载操作符 + reference operator*() const { return node->value; } + pointer operator->() const { return &(operator*()); } + + const_iterator& operator++() + { + MYSTL_DEBUG(node != nullptr); + const node_ptr old = node; + node = node->next; + if (node == nullptr) + { // 如果下一个位置为空,跳到下一个 bucket 的起始处 + auto index = ht->hash(value_traits::get_key(old->value)); + while (!node && ++index < ht->bucket_size_) + { + node = ht->buckets_[index]; + } + } + return *this; + } + const_iterator operator++(int) + { + const_iterator tmp = *this; + ++*this; + return tmp; + } +}; + +// local iterator +template +struct ht_local_iterator :public mystl::iterator +{ + typedef T value_type; + typedef value_type* pointer; + typedef value_type& reference; + typedef size_t size_type; + typedef ptrdiff_t difference_type; + typedef hashtable_node* node_ptr; + + typedef ht_local_iterator self; + typedef ht_local_iterator local_iterator; + typedef ht_const_local_iterator const_local_iterator; + node_ptr node; + + ht_local_iterator(node_ptr n) + :node(n) + { + } + ht_local_iterator(const local_iterator& rhs) + :node(rhs.node) + { + } + ht_local_iterator(const const_local_iterator& rhs) + :node(rhs.node) + { + } + + reference operator*() const { return node->value; } + pointer operator->() const { return &(operator*()); } + + self& operator++() + { + MYSTL_DEBUG(node != nullptr); + node = node->next; + return *this; + } + + self operator++(int) + { + self tmp(*this); + ++*this; + return tmp; + } + + bool operator==(const self& other) const { return node == other.node; } + bool operator!=(const self& other) const { return node != other.node; } +}; + +template +struct ht_const_local_iterator :public mystl::iterator +{ + typedef T value_type; + typedef const value_type* pointer; + typedef const value_type& reference; + typedef size_t size_type; + typedef ptrdiff_t difference_type; + typedef const hashtable_node* node_ptr; + + typedef ht_const_local_iterator self; + typedef ht_local_iterator local_iterator; + typedef ht_const_local_iterator const_local_iterator; + + node_ptr node; + + ht_const_local_iterator(node_ptr n) + :node(n) + { + } + ht_const_local_iterator(const local_iterator& rhs) + :node(rhs.node) + { + } + ht_const_local_iterator(const const_local_iterator& rhs) + :node(rhs.node) + { + } + + reference operator*() const { return node->value; } + pointer operator->() const { return &(operator*()); } + + self& operator++() + { + MYSTL_DEBUG(node != nullptr); + node = node->next; + return *this; + } + + self operator++(int) + { + self tmp(*this); + ++*this; + return tmp; + } + + bool operator==(const self& other) const { return node == other.node; } + bool operator!=(const self& other) const { return node != other.node; } +}; + +// bucket 使用的大小 + +#if (_MSC_VER && _WIN64) || ((__GNUC__ || __clang__) &&__SIZEOF_POINTER__ == 8) +#define SYSTEM_64 1 +#else +#define SYSTEM_32 1 +#endif + +#ifdef SYSTEM_64 + +#define PRIME_NUM 99 + +// 1. start with p = 101 +// 2. p = next_prime(p * 1.7) +// 3. if p < (2 << 63), go to step 2, otherwise, go to step 4 +// 4. end with p = prev_prime(2 << 63 - 1) +static constexpr size_t ht_prime_list[] = { + 101ull, 173ull, 263ull, 397ull, 599ull, 907ull, 1361ull, 2053ull, 3083ull, + 4637ull, 6959ull, 10453ull, 15683ull, 23531ull, 35311ull, 52967ull, 79451ull, + 119179ull, 178781ull, 268189ull, 402299ull, 603457ull, 905189ull, 1357787ull, + 2036687ull, 3055043ull, 4582577ull, 6873871ull, 10310819ull, 15466229ull, + 23199347ull, 34799021ull, 52198537ull, 78297827ull, 117446801ull, 176170229ull, + 264255353ull, 396383041ull, 594574583ull, 891861923ull, 1337792887ull, + 2006689337ull, 3010034021ull, 4515051137ull, 6772576709ull, 10158865069ull, + 15238297621ull, 22857446471ull, 34286169707ull, 51429254599ull, 77143881917ull, + 115715822899ull, 173573734363ull, 260360601547ull, 390540902329ull, + 585811353559ull, 878717030339ull, 1318075545511ull, 1977113318311ull, + 2965669977497ull, 4448504966249ull, 6672757449409ull, 10009136174239ull, + 15013704261371ull, 22520556392057ull, 33780834588157ull, 50671251882247ull, + 76006877823377ull, 114010316735089ull, 171015475102649ull, 256523212653977ull, + 384784818980971ull, 577177228471507ull, 865765842707309ull, 1298648764060979ull, + 1947973146091477ull, 2921959719137273ull, 4382939578705967ull, 6574409368058969ull, + 9861614052088471ull, 14792421078132871ull, 22188631617199337ull, 33282947425799017ull, + 49924421138698549ull, 74886631708047827ull, 112329947562071807ull, 168494921343107851ull, + 252742382014661767ull, 379113573021992729ull, 568670359532989111ull, 853005539299483657ull, + 1279508308949225477ull, 1919262463423838231ull, 2878893695135757317ull, 4318340542703636011ull, + 6477510814055453699ull, 9716266221083181299ull, 14574399331624771603ull, 18446744073709551557ull +}; + +#else + +#define PRIME_NUM 44 + +// 1. start with p = 101 +// 2. p = next_prime(p * 1.7) +// 3. if p < (2 << 31), go to step 2, otherwise, go to step 4 +// 4. end with p = prev_prime(2 << 31 - 1) +static constexpr size_t ht_prime_list[] = { + 101u, 173u, 263u, 397u, 599u, 907u, 1361u, 2053u, 3083u, 4637u, 6959u, + 10453u, 15683u, 23531u, 35311u, 52967u, 79451u, 119179u, 178781u, 268189u, + 402299u, 603457u, 905189u, 1357787u, 2036687u, 3055043u, 4582577u, 6873871u, + 10310819u, 15466229u, 23199347u, 34799021u, 52198537u, 78297827u, 117446801u, + 176170229u, 264255353u, 396383041u, 594574583u, 891861923u, 1337792887u, + 2006689337u, 3010034021u, 4294967291u, +}; + +#endif + +// 找出最接近并大于等于 n 的那个质数 +inline size_t ht_next_prime(size_t n) +{ + const size_t* first = ht_prime_list; + const size_t* last = ht_prime_list + PRIME_NUM; + const size_t* pos = mystl::lower_bound(first, last, n); + return pos == last ? *(last - 1) : *pos; +} + +// 模板类 hashtable +// 参数一代表数据类型,参数二代表哈希函数,参数三代表键值相等的比较函数 +template +class hashtable +{ + + friend struct mystl::ht_iterator; + friend struct mystl::ht_const_iterator; + +public: + // hashtable 的型别定义 + typedef ht_value_traits value_traits; + typedef typename value_traits::key_type key_type; + typedef typename value_traits::mapped_type mapped_type; + typedef typename value_traits::value_type value_type; + typedef Hash hasher; + typedef KeyEqual key_equal; + + typedef hashtable_node node_type; + typedef node_type* node_ptr; + typedef mystl::vector bucket_type; + + typedef mystl::allocator allocator_type; + typedef mystl::allocator data_allocator; + typedef mystl::allocator node_allocator; + + typedef typename allocator_type::pointer pointer; + typedef typename allocator_type::const_pointer const_pointer; + typedef typename allocator_type::reference reference; + typedef typename allocator_type::const_reference const_reference; + typedef typename allocator_type::size_type size_type; + typedef typename allocator_type::difference_type difference_type; + + typedef mystl::ht_iterator iterator; + typedef mystl::ht_const_iterator const_iterator; + typedef mystl::ht_local_iterator local_iterator; + typedef mystl::ht_const_local_iterator const_local_iterator; + + allocator_type get_allocator() const { return allocator_type(); } + +private: + // 用以下六个参数来表现 hashtable + bucket_type buckets_; + size_type bucket_size_; + size_type size_; + float mlf_; + hasher hash_; + key_equal equal_; + +private: + bool is_equal(const key_type& key1, const key_type& key2) + { + return equal_(key1, key2); + } + + bool is_equal(const key_type& key1, const key_type& key2) const + { + return equal_(key1, key2); + } + + const_iterator M_cit(node_ptr node) const noexcept + { + return const_iterator(node, const_cast(this)); + } + + iterator M_begin() noexcept + { + for (size_type n = 0; n < bucket_size_; ++n) + { + if (buckets_[n]) // 找到第一个有节点的位置就返回 + return iterator(buckets_[n], this); + } + return iterator(nullptr, this); + } + + const_iterator M_begin() const noexcept + { + for (size_type n = 0; n < bucket_size_; ++n) + { + if (buckets_[n]) // 找到第一个有节点的位置就返回 + return M_cit(buckets_[n]); + } + return M_cit(nullptr); + } + +public: + // 构造、复制、移动、析构函数 + explicit hashtable(size_type bucket_count, + const Hash& hash = Hash(), + const KeyEqual& equal = KeyEqual()) + :size_(0), mlf_(1.0f), hash_(hash), equal_(equal) + { + init(bucket_count); + } + + template ::value, int>::type = 0> + hashtable(Iter first, Iter last, + size_type bucket_count, + const Hash& hash = Hash(), + const KeyEqual& equal = KeyEqual()) + :size_(mystl::distance(first, last)), mlf_(1.0f), hash_(hash), equal_(equal) + { + init(mystl::max(bucket_count, static_cast(mystl::distance(first, last)))); + } + + hashtable(const hashtable& rhs) + :hash_(rhs.hash_), equal_(rhs.equal_) + { + copy_init(rhs); + } + hashtable(hashtable&& rhs) noexcept + : bucket_size_(rhs.bucket_size_), + size_(rhs.size_), + mlf_(rhs.mlf_), + hash_(rhs.hash_), + equal_(rhs.equal_) + { + buckets_ = mystl::move(rhs.buckets_); + rhs.bucket_size_ = 0; + rhs.size_ = 0; + rhs.mlf_ = 0.0f; + } + + hashtable& operator=(const hashtable& rhs); + hashtable& operator=(hashtable&& rhs) noexcept; + + ~hashtable() { clear(); } + + // 迭代器相关操作 + iterator begin() noexcept + { return M_begin(); } + const_iterator begin() const noexcept + { return M_begin(); } + iterator end() noexcept + { return iterator(nullptr, this); } + const_iterator end() const noexcept + { return M_cit(nullptr); } + + const_iterator cbegin() const noexcept + { return begin(); } + const_iterator cend() const noexcept + { return end(); } + + // 容量相关操作 + bool empty() const noexcept { return size_ == 0; } + size_type size() const noexcept { return size_; } + size_type max_size() const noexcept { return static_cast(-1); } + + // 修改容器相关操作 + + // emplace / empalce_hint + + template + iterator emplace_multi(Args&& ...args); + + template + pair emplace_unique(Args&& ...args); + + // [note]: hint 对于 hash_table 其实没有意义,因为即使提供了 hint,也要做一次 hash, + // 来确保 hash_table 的性质,所以选择忽略它 + template + iterator emplace_multi_use_hint(const_iterator /*hint*/, Args&& ...args) + { return emplace_multi(mystl::forward(args)...); } + + template + iterator emplace_unique_use_hint(const_iterator /*hint*/, Args&& ...args) + { return emplace_unique(mystl::forward(args)...).first; } + + // insert + + iterator insert_multi_noresize(const value_type& value); + pair insert_unique_noresize(const value_type& value); + + iterator insert_multi(const value_type& value) + { + rehash_if_need(1); + return insert_multi_noresize(value); + } + iterator insert_multi(value_type&& value) + { return emplace_multi(mystl::move(value)); } + + + pair insert_unique(const value_type& value) + { + rehash_if_need(1); + return insert_unique_noresize(value); + } + pair insert_unique(value_type&& value) + { return emplace_unique(mystl::move(value)); } + + // [note]: 同 emplace_hint + iterator insert_multi_use_hint(const_iterator /*hint*/, const value_type& value) + { return insert_multi(value); } + iterator insert_multi_use_hint(const_iterator /*hint*/, value_type&& value) + { return emplace_multi(mystl::move(value)); } + + iterator insert_unique_use_hint(const_iterator /*hint*/, const value_type& value) + { return insert_unique(value).first; } + iterator insert_unique_use_hint(const_iterator /*hint*/, value_type&& value) + { return emplace_unique(mystl::move(value)); } + + template + void insert_multi(InputIter first, InputIter last) + { copy_insert_multi(first, last, iterator_category(first)); } + + template + void insert_unique(InputIter first, InputIter last) + { copy_insert_unique(first, last, iterator_category(first)); } + + // erase / clear + + void erase(const_iterator position); + void erase(const_iterator first, const_iterator last); + + size_type erase_multi(const key_type& key); + size_type erase_unique(const key_type& key); + + void clear(); + + void swap(hashtable& rhs) noexcept; + + // 查找相关操作 + + size_type count(const key_type& key) const; + + iterator find(const key_type& key); + const_iterator find(const key_type& key) const; + + pair equal_range_multi(const key_type& key); + pair equal_range_multi(const key_type& key) const; + + pair equal_range_unique(const key_type& key); + pair equal_range_unique(const key_type& key) const; + + // bucket interface + + local_iterator begin(size_type n) noexcept + { + MYSTL_DEBUG(n < size_); + return buckets_[n]; + } + const_local_iterator begin(size_type n) const noexcept + { + MYSTL_DEBUG(n < size_); + return buckets_[n]; + } + const_local_iterator cbegin(size_type n) const noexcept + { + MYSTL_DEBUG(n < size_); + return buckets_[n]; + } + + local_iterator end(size_type n) noexcept + { + MYSTL_DEBUG(n < size_); + return nullptr; + } + const_local_iterator end(size_type n) const noexcept + { + MYSTL_DEBUG(n < size_); + return nullptr; + } + const_local_iterator cend(size_type n) const noexcept + { + MYSTL_DEBUG(n < size_); + return nullptr; + } + + size_type bucket_count() const noexcept + { return bucket_size_; } + size_type max_bucket_count() const noexcept + { return ht_prime_list[PRIME_NUM - 1]; } + + size_type bucket_size(size_type n) const noexcept; + size_type bucket(const key_type& key) const + { return hash(key); } + + // hash policy + + float load_factor() const noexcept + { return bucket_size_ != 0 ? (float)size_ / bucket_size_ : 0.0f; } + + float max_load_factor() const noexcept + { return mlf_; } + void max_load_factor(float ml) + { + THROW_OUT_OF_RANGE_IF(ml != ml || ml < 0, "invalid hash load factor"); + mlf_ = ml; + } + + void rehash(size_type count); + + void reserve(size_type count) + { rehash(static_cast((float)count / max_load_factor() + 0.5f)); } + + hasher hash_fcn() const { return hash_; } + key_equal key_eq() const { return equal_; } + +private: + // hashtable 成员函数 + + // init + void init(size_type n); + void copy_init(const hashtable& ht); + + // node + template + node_ptr create_node(Args&& ...args); + void destroy_node(node_ptr n); + + // hash + size_type next_size(size_type n) const; + size_type hash(const key_type& key, size_type n) const; + size_type hash(const key_type& key) const; + void rehash_if_need(size_type n); + + // insert + template + void copy_insert_multi(InputIter first, InputIter last, mystl::input_iterator_tag); + template + void copy_insert_multi(ForwardIter first, ForwardIter last, mystl::forward_iterator_tag); + template + void copy_insert_unique(InputIter first, InputIter last, mystl::input_iterator_tag); + template + void copy_insert_unique(ForwardIter first, ForwardIter last, mystl::forward_iterator_tag); + + // insert node + pair insert_node_unique(node_ptr np); + iterator insert_node_multi(node_ptr np); + + // bucket operator + void replace_bucket(size_type bucket_count); + void erase_bucket(size_type n, node_ptr first, node_ptr last); + void erase_bucket(size_type n, node_ptr last); + + // comparision + bool equal_to_multi(const hashtable& other); + bool equal_to_unique(const hashtable& other); +}; + +/*****************************************************************************************/ + +// 复制赋值运算符 +template +hashtable& +hashtable:: +operator=(const hashtable& rhs) +{ + if (this != &rhs) + { + hashtable tmp(rhs); + swap(tmp); + } + return *this; +} + +// 移动赋值运算符 +template +hashtable& +hashtable:: +operator=(hashtable&& rhs) noexcept +{ + hashtable tmp(mystl::move(rhs)); + swap(tmp); + return *this; +} + +// 就地构造元素,键值允许重复 +// 强异常安全保证 +template +template +typename hashtable::iterator +hashtable:: +emplace_multi(Args&& ...args) +{ + auto np = create_node(mystl::forward(args)...); + try + { + if ((float)(size_ + 1) > (float)bucket_size_ * max_load_factor()) + rehash(size_ + 1); + } + catch (...) + { + destroy_node(np); + throw; + } + return insert_node_multi(np); +} + +// 就地构造元素,键值允许重复 +// 强异常安全保证 +template +template +pair::iterator, bool> +hashtable:: +emplace_unique(Args&& ...args) +{ + auto np = create_node(mystl::forward(args)...); + try + { + if ((float)(size_ + 1) > (float)bucket_size_ * max_load_factor()) + rehash(size_ + 1); + } + catch (...) + { + destroy_node(np); + throw; + } + return insert_node_unique(np); +} + +// 在不需要重建表格的情况下插入新节点,键值不允许重复 +template +pair::iterator, bool> +hashtable:: +insert_unique_noresize(const value_type& value) +{ + const auto n = hash(value_traits::get_key(value)); + auto first = buckets_[n]; + for (auto cur = first; cur; cur = cur->next) + { + if (is_equal(value_traits::get_key(cur->value), value_traits::get_key(value))) + return mystl::make_pair(iterator(cur, this), false); + } + // 让新节点成为链表的第一个节点 + auto tmp = create_node(value); + tmp->next = first; + buckets_[n] = tmp; + ++size_; + return mystl::make_pair(iterator(tmp, this), true); +} + +// 在不需要重建表格的情况下插入新节点,键值允许重复 +template +typename hashtable::iterator +hashtable:: +insert_multi_noresize(const value_type& value) +{ + const auto n = hash(value_traits::get_key(value)); + auto first = buckets_[n]; + auto tmp = create_node(value); + for (auto cur = first; cur; cur = cur->next) + { + if (is_equal(value_traits::get_key(cur->value), value_traits::get_key(value))) + { // 如果链表中存在相同键值的节点就马上插入,然后返回 + tmp->next = cur->next; + cur->next = tmp; + ++size_; + return iterator(tmp, this); + } + } + // 否则插入在链表头部 + tmp->next = first; + buckets_[n] = tmp; + ++size_; + return iterator(tmp, this); +} + +// 删除迭代器所指的节点 +template +void hashtable:: +erase(const_iterator position) +{ + auto p = position.node; + if (p) + { + const auto n = hash(value_traits::get_key(p->value)); + auto cur = buckets_[n]; + if (cur == p) + { // p 位于链表头部 + buckets_[n] = cur->next; + destroy_node(cur); + --size_; + } + else + { + auto next = cur->next; + while (next) + { + if (next == p) + { + cur->next = next->next; + destroy_node(next); + --size_; + break; + } + else + { + cur = next; + next = cur->next; + } + } + } + } +} + +// 删除[first, last)内的节点 +template +void hashtable:: +erase(const_iterator first, const_iterator last) +{ + if (first.node == last.node) + return; + auto first_bucket = first.node + ? hash(value_traits::get_key(first.node->value)) + : bucket_size_; + auto last_bucket = last.node + ? hash(value_traits::get_key(last.node->value)) + : bucket_size_; + if (first_bucket == last_bucket) + { // 如果在 bucket 在同一个位置 + erase_bucket(first_bucket, first.node, last.node); + } + else + { + erase_bucket(first_bucket, first.node, nullptr); + for (auto n = first_bucket + 1; n < last_bucket; ++n) + { + if(buckets_[n] != nullptr) + erase_bucket(n, nullptr); + } + if (last_bucket != bucket_size_) + { + erase_bucket(last_bucket, last.node); + } + } +} + +// 删除键值为 key 的节点 +template +typename hashtable::size_type +hashtable:: +erase_multi(const key_type& key) +{ + auto p = equal_range_multi(key); + if (p.first.node != nullptr) + { + erase(p.first, p.second); + return mystl::distance(p.first, p.second); + } + return 0; +} + +template +typename hashtable::size_type +hashtable:: +erase_unique(const key_type& key) +{ + const auto n = hash(key); + auto first = buckets_[n]; + if (first) + { + if (is_equal(value_traits::get_key(first->value), key)) + { + buckets_[n] = first->next; + destroy_node(first); + --size_; + return 1; + } + else + { + auto next = first->next; + while (next) + { + if (is_equal(value_traits::get_key(next->value), key)) + { + first->next = next->next; + destroy_node(next); + --size_; + return 1; + } + first = next; + next = first->next; + } + } + } + return 0; +} + +// 清空 hashtable +template +void hashtable:: +clear() +{ + if (size_ != 0) + { + for (size_type i = 0; i < bucket_size_; ++i) + { + node_ptr cur = buckets_[i]; + while (cur != nullptr) + { + node_ptr next = cur->next; + destroy_node(cur); + cur = next; + } + buckets_[i] = nullptr; + } + size_ = 0; + } +} + +// 在某个 bucket 节点的个数 +template +typename hashtable::size_type +hashtable:: +bucket_size(size_type n) const noexcept +{ + size_type result = 0; + for (auto cur = buckets_[n]; cur; cur = cur->next) + { + ++result; + } + return result; +} + +// 重新对元素进行一遍哈希,插入到新的位置 +template +void hashtable:: +rehash(size_type count) +{ + auto n = ht_next_prime(count); + if (n > bucket_size_) + { + replace_bucket(n); + } + else + { + if ((float)size_ / (float)n < max_load_factor() - 0.25f && + (float)n < (float)bucket_size_ * 0.75) // worth rehash + { + replace_bucket(n); + } + } +} + +// 查找键值为 key 的节点,返回其迭代器 +template +typename hashtable::iterator +hashtable:: +find(const key_type& key) +{ + const auto n = hash(key); + node_ptr first = buckets_[n]; + for (; first && !is_equal(value_traits::get_key(first->value), key); first = first->next) {} + return iterator(first, this); +} + +template +typename hashtable::const_iterator +hashtable:: +find(const key_type& key) const +{ + const auto n = hash(key); + node_ptr first = buckets_[n]; + for (; first && !is_equal(value_traits::get_key(first->value), key); first = first->next) {} + return M_cit(first); +} + +// 查找键值为 key 出现的次数 +template +typename hashtable::size_type +hashtable:: +count(const key_type& key) const +{ + const auto n = hash(key); + size_type result = 0; + for (node_ptr cur = buckets_[n]; cur; cur = cur->next) + { + if (is_equal(value_traits::get_key(cur->value), key)) + ++result; + } + return result; +} + +// 查找与键值 key 相等的区间,返回一个 pair,指向相等区间的首尾 +template +pair::iterator, + typename hashtable::iterator> +hashtable:: +equal_range_multi(const key_type& key) +{ + const auto n = hash(key); + for (node_ptr first = buckets_[n]; first; first = first->next) + { + if (is_equal(value_traits::get_key(first->value), key)) + { // 如果出现相等的键值 + for (node_ptr second = first->next; second; second = second->next) + { + if (!is_equal(value_traits::get_key(second->value), key)) + return mystl::make_pair(iterator(first, this), iterator(second, this)); + } + for (auto m = n + 1; m < bucket_size_; ++m) + { // 整个链表都相等,查找下一个链表出现的位置 + if (buckets_[m]) + return mystl::make_pair(iterator(first, this), iterator(buckets_[m], this)); + } + return mystl::make_pair(iterator(first, this), end()); + } + } + return mystl::make_pair(end(), end()); +} + +template +pair::const_iterator, + typename hashtable::const_iterator> +hashtable:: +equal_range_multi(const key_type& key) const +{ + const auto n = hash(key); + for (node_ptr first = buckets_[n]; first; first = first->next) + { + if (is_equal(value_traits::get_key(first->value), key)) + { + for (node_ptr second = first->next; second; second = second->next) + { + if (!is_equal(value_traits::get_key(second->value), key)) + return mystl::make_pair(M_cit(first), M_cit(second)); + } + for (auto m = n + 1; m < bucket_size_; ++m) + { // 整个链表都相等,查找下一个链表出现的位置 + if (buckets_[m]) + return mystl::make_pair(M_cit(first), M_cit(buckets_[m])); + } + return mystl::make_pair(M_cit(first), cend()); + } + } + return mystl::make_pair(cend(), cend()); +} + +template +pair::iterator, + typename hashtable::iterator> +hashtable:: +equal_range_unique(const key_type& key) +{ + const auto n = hash(key); + for (node_ptr first = buckets_[n]; first; first = first->next) + { + if (is_equal(value_traits::get_key(first->value), key)) + { + if (first->next) + return mystl::make_pair(iterator(first, this), iterator(first->next, this)); + for (auto m = n + 1; m < bucket_size_; ++m) + { // 整个链表都相等,查找下一个链表出现的位置 + if (buckets_[m]) + return mystl::make_pair(iterator(first, this), iterator(buckets_[m], this)); + } + return mystl::make_pair(iterator(first, this), end()); + } + } + return mystl::make_pair(end(), end()); +} + +template +pair::const_iterator, + typename hashtable::const_iterator> +hashtable:: +equal_range_unique(const key_type& key) const +{ + const auto n = hash(key); + for (node_ptr first = buckets_[n]; first; first = first->next) + { + if (is_equal(value_traits::get_key(first->value), key)) + { + if (first->next) + return mystl::make_pair(M_cit(first), M_cit(first->next)); + for (auto m = n + 1; m < bucket_size_; ++m) + { // 整个链表都相等,查找下一个链表出现的位置 + if (buckets_[m]) + return mystl::make_pair(M_cit(first), M_cit(buckets_[m])); + } + return mystl::make_pair(M_cit(first), cend()); + } + } + return mystl::make_pair(cend(), cend()); +} + +// 交换 hashtable +template +void hashtable:: +swap(hashtable& rhs) noexcept +{ + if (this != &rhs) + { + buckets_.swap(rhs.buckets_); + mystl::swap(bucket_size_, rhs.bucket_size_); + mystl::swap(size_, rhs.size_); + mystl::swap(mlf_, rhs.mlf_); + mystl::swap(hash_, rhs.hash_); + mystl::swap(equal_, rhs.equal_); + } +} + +/****************************************************************************************/ +// helper function + +// init 函数 +template +void hashtable:: +init(size_type n) +{ + const auto bucket_nums = next_size(n); + try + { + buckets_.reserve(bucket_nums); + buckets_.assign(bucket_nums, nullptr); + } + catch (...) + { + bucket_size_ = 0; + size_ = 0; + throw; + } + bucket_size_ = buckets_.size(); +} + +// copy_init 函数 +template +void hashtable:: +copy_init(const hashtable& ht) +{ + bucket_size_ = 0; + buckets_.reserve(ht.bucket_size_); + buckets_.assign(ht.bucket_size_, nullptr); + try + { + for (size_type i = 0; i < ht.bucket_size_; ++i) + { + node_ptr cur = ht.buckets_[i]; + if (cur) + { // 如果某 bucket 存在链表 + auto copy = create_node(cur->value); + buckets_[i] = copy; + for (auto next = cur->next; next; cur = next, next = cur->next) + { //复制链表 + copy->next = create_node(next->value); + copy = copy->next; + } + copy->next = nullptr; + } + } + bucket_size_ = ht.bucket_size_; + mlf_ = ht.mlf_; + size_ = ht.size_; + } + catch (...) + { + clear(); + } +} + +// create_node 函数 +template +template +typename hashtable::node_ptr +hashtable:: +create_node(Args&& ...args) +{ + node_ptr tmp = node_allocator::allocate(1); + try + { + data_allocator::construct(mystl::address_of(tmp->value), mystl::forward(args)...); + tmp->next = nullptr; + } + catch (...) + { + node_allocator::deallocate(tmp); + throw; + } + return tmp; +} + +// destroy_node 函数 +template +void hashtable:: +destroy_node(node_ptr node) +{ + data_allocator::destroy(mystl::address_of(node->value)); + node_allocator::deallocate(node); + node = nullptr; +} + +// next_size 函数 +template +typename hashtable::size_type +hashtable::next_size(size_type n) const +{ + return ht_next_prime(n); +} + +// hash 函数 +template +typename hashtable::size_type +hashtable:: +hash(const key_type& key, size_type n) const +{ + return hash_(key) % n; +} + +template +typename hashtable::size_type +hashtable:: +hash(const key_type& key) const +{ + return hash_(key) % bucket_size_; +} + +// rehash_if_need 函数 +template +void hashtable:: +rehash_if_need(size_type n) +{ + if (static_cast(size_ + n) > (float)bucket_size_ * max_load_factor()) + rehash(size_ + n); +} + +// copy_insert +template +template +void hashtable:: +copy_insert_multi(InputIter first, InputIter last, mystl::input_iterator_tag) +{ + rehash_if_need(mystl::distance(first, last)); + for (; first != last; ++first) + insert_multi_noresize(*first); +} + +template +template +void hashtable:: +copy_insert_multi(ForwardIter first, ForwardIter last, mystl::forward_iterator_tag) +{ + size_type n = mystl::distance(first, last); + rehash_if_need(n); + for (; n > 0; --n, ++first) + insert_multi_noresize(*first); +} + +template +template +void hashtable:: +copy_insert_unique(InputIter first, InputIter last, mystl::input_iterator_tag) +{ + rehash_if_need(mystl::distance(first, last)); + for (; first != last; ++first) + insert_unique_noresize(*first); +} + +template +template +void hashtable:: +copy_insert_unique(ForwardIter first, ForwardIter last, mystl::forward_iterator_tag) +{ + size_type n = mystl::distance(first, last); + rehash_if_need(n); + for (; n > 0; --n, ++first) + insert_unique_noresize(*first); +} + +// insert_node 函数 +template +typename hashtable::iterator +hashtable:: +insert_node_multi(node_ptr np) +{ + const auto n = hash(value_traits::get_key(np->value)); + auto cur = buckets_[n]; + if (cur == nullptr) + { + buckets_[n] = np; + ++size_; + return iterator(np, this); + } + for (; cur; cur = cur->next) + { + if (is_equal(value_traits::get_key(cur->value), value_traits::get_key(np->value))) + { + np->next = cur->next; + cur->next = np; + ++size_; + return iterator(np, this); + } + } + np->next = buckets_[n]; + buckets_[n] = np; + ++size_; + return iterator(np, this); +} + +// insert_node_unique 函数 +template +pair::iterator, bool> +hashtable:: +insert_node_unique(node_ptr np) +{ + const auto n = hash(value_traits::get_key(np->value)); + auto cur = buckets_[n]; + if (cur == nullptr) + { + buckets_[n] = np; + ++size_; + return mystl::make_pair(iterator(np, this), true); + } + for (; cur; cur = cur->next) + { + if (is_equal(value_traits::get_key(cur->value), value_traits::get_key(np->value))) + { + return mystl::make_pair(iterator(cur, this), false); + } + } + np->next = buckets_[n]; + buckets_[n] = np; + ++size_; + return mystl::make_pair(iterator(np, this), true); +} + +// replace_bucket 函数 +template +void hashtable:: +replace_bucket(size_type bucket_count) +{ + bucket_type bucket(bucket_count); + if (size_ != 0) + { + for (size_type i = 0; i < bucket_size_; ++i) + { + for (auto first = buckets_[i]; first; first = first->next) + { + auto tmp = create_node(first->value); + const auto n = hash(value_traits::get_key(first->value), bucket_count); + auto f = bucket[n]; + bool is_inserted = false; + for (auto cur = f; cur; cur = cur->next) + { + if (is_equal(value_traits::get_key(cur->value), value_traits::get_key(first->value))) + { + tmp->next = cur->next; + cur->next = tmp; + is_inserted = true; + break; + } + } + if (!is_inserted) + { + tmp->next = f; + bucket[n] = tmp; + } + } + } + } + buckets_.swap(bucket); + bucket_size_ = buckets_.size(); +} + +// erase_bucket 函数 +// 在第 n 个 bucket 内,删除 [first, last) 的节点 +template +void hashtable:: +erase_bucket(size_type n, node_ptr first, node_ptr last) +{ + auto cur = buckets_[n]; + if (cur == first) + { + erase_bucket(n, last); + } + else + { + node_ptr next = cur->next; + for (; next != first; cur = next, next = cur->next) {} + while (next != last) + { + cur->next = next->next; + destroy_node(next); + next = cur->next; + --size_; + } + } +} + +// erase_bucket 函数 +// 在第 n 个 bucket 内,删除 [buckets_[n], last) 的节点 +template +void hashtable:: +erase_bucket(size_type n, node_ptr last) +{ + auto cur = buckets_[n]; + while (cur != last) + { + auto next = cur->next; + destroy_node(cur); + cur = next; + --size_; + } + buckets_[n] = last; +} + +// equal_to 函数 +template +bool hashtable::equal_to_multi(const hashtable& other) +{ + if (size_ != other.size_) + return false; + for (auto f = begin(), l = end(); f != l;) + { + auto p1 = equal_range_multi(value_traits::get_key(*f)); + auto p2 = other.equal_range_multi(value_traits::get_key(*f)); + if (mystl::distance(p1.first, p1.last) != mystl::distance(p2.first, p2.last) || + !mystl::is_permutation(p1.first, p2.last, p2.first, p2.last)) + return false; + f = p1.last; + } + return true; +} + +template +bool hashtable::equal_to_unique(const hashtable& other) +{ + if (size_ != other.size_) + return false; + for (auto f = begin(), l = end(); f != l; ++f) + { + auto res = other.find(value_traits::get_key(*f)); + if (res.node == nullptr || *res != *f) + return false; + } + return true; +} + +// 重载 mystl 的 swap +template +void swap(hashtable& lhs, + hashtable& rhs) noexcept +{ + lhs.swap(rhs); +} + +} // namespace mystl +#endif // !MYTINYSTL_HASHTABLE_H_ + diff --git a/src/MyTinySTL-master/MyTinySTL-master/MyTinySTL/heap_algo.h b/src/MyTinySTL-master/MyTinySTL-master/MyTinySTL/heap_algo.h new file mode 100755 index 0000000..5ab74e2 --- /dev/null +++ b/src/MyTinySTL-master/MyTinySTL-master/MyTinySTL/heap_algo.h @@ -0,0 +1,227 @@ +#ifndef MYTINYSTL_HEAP_ALGO_H_ +#define MYTINYSTL_HEAP_ALGO_H_ + +// 这个头文件包含 heap 的四个算法 : push_heap, pop_heap, sort_heap, make_heap + +#include "iterator.h" + +namespace mystl +{ + +/*****************************************************************************************/ +// push_heap +// 该函数接受两个迭代器,表示一个 heap 容器的首尾,并且新元素已经插入到底部容器的最尾端,调整 heap +/*****************************************************************************************/ +template +void push_heap_aux(RandomIter first, Distance holeIndex, Distance topIndex, T value) +{ + auto parent = (holeIndex - 1) / 2; + while (holeIndex > topIndex && *(first + parent) < value) + { + // 使用 operator<,所以 heap 为 max-heap + *(first + holeIndex) = *(first + parent); + holeIndex = parent; + parent = (holeIndex - 1) / 2; + } + *(first + holeIndex) = value; +} + +template +void push_heap_d(RandomIter first, RandomIter last, Distance*) +{ + mystl::push_heap_aux(first, (last - first) - 1, static_cast(0), *(last - 1)); +} + +template +void push_heap(RandomIter first, RandomIter last) +{ // 新元素应该已置于底部容器的最尾端 + mystl::push_heap_d(first, last, distance_type(first)); +} + +// 重载版本使用函数对象 comp 代替比较操作 +template +void push_heap_aux(RandomIter first, Distance holeIndex, Distance topIndex, T value, + Compared comp) +{ + auto parent = (holeIndex - 1) / 2; + while (holeIndex > topIndex && comp(*(first + parent), value)) + { + *(first + holeIndex) = *(first + parent); + holeIndex = parent; + parent = (holeIndex - 1) / 2; + } + *(first + holeIndex) = value; +} + +template +void push_heap_d(RandomIter first, RandomIter last, Distance*, Compared comp) +{ + mystl::push_heap_aux(first, (last - first) - 1, static_cast(0), + *(last - 1), comp); +} + +template +void push_heap(RandomIter first, RandomIter last, Compared comp) +{ + mystl::push_heap_d(first, last, distance_type(first), comp); +} + +/*****************************************************************************************/ +// pop_heap +// 该函数接受两个迭代器,表示 heap 容器的首尾,将 heap 的根节点取出放到容器尾部,调整 heap +/*****************************************************************************************/ +template +void adjust_heap(RandomIter first, Distance holeIndex, Distance len, T value) +{ + // 先进行下溯(percolate down)过程 + auto topIndex = holeIndex; + auto rchild = 2 * holeIndex + 2; + while (rchild < len) + { + if (*(first + rchild) < *(first + rchild - 1)) + --rchild; + *(first + holeIndex) = *(first + rchild); + holeIndex = rchild; + rchild = 2 * (rchild + 1); + } + if (rchild == len) + { // 如果没有右子节点 + *(first + holeIndex) = *(first + (rchild - 1)); + holeIndex = rchild - 1; + } + // 再执行一次上溯(percolate up)过程 + mystl::push_heap_aux(first, holeIndex, topIndex, value); +} + +template +void pop_heap_aux(RandomIter first, RandomIter last, RandomIter result, T value, + Distance*) +{ + // 先将首值调至尾节点,然后调整[first, last - 1)使之重新成为一个 max-heap + *result = *first; + mystl::adjust_heap(first, static_cast(0), last - first, value); +} + +template +void pop_heap(RandomIter first, RandomIter last) +{ + mystl::pop_heap_aux(first, last - 1, last - 1, *(last - 1), distance_type(first)); +} + +// 重载版本使用函数对象 comp 代替比较操作 +template +void adjust_heap(RandomIter first, Distance holeIndex, Distance len, T value, + Compared comp) +{ + // 先进行下溯(percolate down)过程 + auto topIndex = holeIndex; + auto rchild = 2 * holeIndex + 2; + while (rchild < len) + { + if (comp(*(first + rchild), *(first + rchild - 1))) --rchild; + *(first + holeIndex) = *(first + rchild); + holeIndex = rchild; + rchild = 2 * (rchild + 1); + } + if (rchild == len) + { + *(first + holeIndex) = *(first + (rchild - 1)); + holeIndex = rchild - 1; + } + // 再执行一次上溯(percolate up)过程 + mystl::push_heap_aux(first, holeIndex, topIndex, value, comp); +} + +template +void pop_heap_aux(RandomIter first, RandomIter last, RandomIter result, + T value, Distance*, Compared comp) +{ + *result = *first; // 先将尾指设置成首值,即尾指为欲求结果 + mystl::adjust_heap(first, static_cast(0), last - first, value, comp); +} + +template +void pop_heap(RandomIter first, RandomIter last, Compared comp) +{ + mystl::pop_heap_aux(first, last - 1, last - 1, *(last - 1), + distance_type(first), comp); +} + +/*****************************************************************************************/ +// sort_heap +// 该函数接受两个迭代器,表示 heap 容器的首尾,不断执行 pop_heap 操作,直到首尾最多相差1 +/*****************************************************************************************/ +template +void sort_heap(RandomIter first, RandomIter last) +{ + // 每执行一次 pop_heap,最大的元素都被放到尾部,直到容器最多只有一个元素,完成排序 + while (last - first > 1) + { + mystl::pop_heap(first, last--); + } +} + +// 重载版本使用函数对象 comp 代替比较操作 +template +void sort_heap(RandomIter first, RandomIter last, Compared comp) +{ + while (last - first > 1) + { + mystl::pop_heap(first, last--, comp); + } +} + +/*****************************************************************************************/ +// make_heap +// 该函数接受两个迭代器,表示 heap 容器的首尾,把容器内的数据变为一个 heap +/*****************************************************************************************/ +template +void make_heap_aux(RandomIter first, RandomIter last, Distance*) +{ + if (last - first < 2) + return; + auto len = last - first; + auto holeIndex = (len - 2) / 2; + while (true) + { + // 重排以 holeIndex 为首的子树 + mystl::adjust_heap(first, holeIndex, len, *(first + holeIndex)); + if (holeIndex == 0) + return; + holeIndex--; + } +} + +template +void make_heap(RandomIter first, RandomIter last) +{ + mystl::make_heap_aux(first, last, distance_type(first));; +} + +// 重载版本使用函数对象 comp 代替比较操作 +template +void make_heap_aux(RandomIter first, RandomIter last, Distance*, Compared comp) +{ + if (last - first < 2) + return; + auto len = last - first; + auto holeIndex = (len - 2) / 2; + while (true) + { + // 重排以 holeIndex 为首的子树 + mystl::adjust_heap(first, holeIndex, len, *(first + holeIndex), comp); + if (holeIndex == 0) + return; + holeIndex--; + } +} + +template +void make_heap(RandomIter first, RandomIter last, Compared comp) +{ + mystl::make_heap_aux(first, last, distance_type(first), comp); +} + +} // namespace mystl +#endif // !MYTINYSTL_HEAP_ALGO_H_ + diff --git a/src/MyTinySTL-master/MyTinySTL-master/MyTinySTL/iterator.h b/src/MyTinySTL-master/MyTinySTL-master/MyTinySTL/iterator.h new file mode 100755 index 0000000..28a9a69 --- /dev/null +++ b/src/MyTinySTL-master/MyTinySTL-master/MyTinySTL/iterator.h @@ -0,0 +1,366 @@ +#ifndef MYTINYSTL_ITERATOR_H_ +#define MYTINYSTL_ITERATOR_H_ + +// 这个头文件用于迭代器设计,包含了一些模板结构体与全局函数, + +#include + +#include "type_traits.h" + +namespace mystl +{ + +// 五种迭代器类型 +struct input_iterator_tag {}; +struct output_iterator_tag {}; +struct forward_iterator_tag : public input_iterator_tag {}; +struct bidirectional_iterator_tag : public forward_iterator_tag {}; +struct random_access_iterator_tag : public bidirectional_iterator_tag {}; + +// iterator 模板 +template + struct iterator +{ + typedef Category iterator_category; + typedef T value_type; + typedef Pointer pointer; + typedef Reference reference; + typedef Distance difference_type; +}; + +// iterator traits + +template +struct has_iterator_cat +{ +private: + struct two { char a; char b; }; + template static two test(...); + template static char test(typename U::iterator_category* = 0); +public: + static const bool value = sizeof(test(0)) == sizeof(char); +}; + +template +struct iterator_traits_impl {}; + +template +struct iterator_traits_impl +{ + typedef typename Iterator::iterator_category iterator_category; + typedef typename Iterator::value_type value_type; + typedef typename Iterator::pointer pointer; + typedef typename Iterator::reference reference; + typedef typename Iterator::difference_type difference_type; +}; + +template +struct iterator_traits_helper {}; + +template +struct iterator_traits_helper + : public iterator_traits_impl::value || + std::is_convertible::value> +{ +}; + +// 萃取迭代器的特性 +template +struct iterator_traits + : public iterator_traits_helper::value> {}; + +// 针对原生指针的偏特化版本 +template +struct iterator_traits +{ + typedef random_access_iterator_tag iterator_category; + typedef T value_type; + typedef T* pointer; + typedef T& reference; + typedef ptrdiff_t difference_type; +}; + +template +struct iterator_traits +{ + typedef random_access_iterator_tag iterator_category; + typedef T value_type; + typedef const T* pointer; + typedef const T& reference; + typedef ptrdiff_t difference_type; +}; + +template >::value> +struct has_iterator_cat_of + : public m_bool_constant::iterator_category, U>::value> +{ +}; + +// 萃取某种迭代器 +template +struct has_iterator_cat_of : public m_false_type {}; + +template +struct is_input_iterator : public has_iterator_cat_of {}; + +template +struct is_output_iterator : public has_iterator_cat_of {}; + +template +struct is_forward_iterator : public has_iterator_cat_of {}; + +template +struct is_bidirectional_iterator : public has_iterator_cat_of {}; + +template +struct is_random_access_iterator : public has_iterator_cat_of {}; + +template +struct is_iterator : + public m_bool_constant::value || + is_output_iterator::value> +{ +}; + +// 萃取某个迭代器的 category +template +typename iterator_traits::iterator_category +iterator_category(const Iterator&) +{ + typedef typename iterator_traits::iterator_category Category; + return Category(); +} + +// 萃取某个迭代器的 distance_type +template +typename iterator_traits::difference_type* +distance_type(const Iterator&) +{ + return static_cast::difference_type*>(0); +} + +// 萃取某个迭代器的 value_type +template +typename iterator_traits::value_type* +value_type(const Iterator&) +{ + return static_cast::value_type*>(0); +} + +// 以下函数用于计算迭代器间的距离 + +// distance 的 input_iterator_tag 的版本 +template +typename iterator_traits::difference_type +distance_dispatch(InputIterator first, InputIterator last, input_iterator_tag) +{ + typename iterator_traits::difference_type n = 0; + while (first != last) + { + ++first; + ++n; + } + return n; +} + +// distance 的 random_access_iterator_tag 的版本 +template +typename iterator_traits::difference_type +distance_dispatch(RandomIter first, RandomIter last, + random_access_iterator_tag) +{ + return last - first; +} + +template +typename iterator_traits::difference_type +distance(InputIterator first, InputIterator last) +{ + return distance_dispatch(first, last, iterator_category(first)); +} + +// 以下函数用于让迭代器前进 n 个距离 + +// advance 的 input_iterator_tag 的版本 +template +void advance_dispatch(InputIterator& i, Distance n, input_iterator_tag) +{ + while (n--) + ++i; +} + +// advance 的 bidirectional_iterator_tag 的版本 +template +void advance_dispatch(BidirectionalIterator& i, Distance n, bidirectional_iterator_tag) +{ + if (n >= 0) + while (n--) ++i; + else + while (n++) --i; +} + +// advance 的 random_access_iterator_tag 的版本 +template +void advance_dispatch(RandomIter& i, Distance n, random_access_iterator_tag) +{ + i += n; +} + +template +void advance(InputIterator& i, Distance n) +{ + advance_dispatch(i, n, iterator_category(i)); +} + +/*****************************************************************************************/ + +// 模板类 : reverse_iterator +// 代表反向迭代器,使前进为后退,后退为前进 +template +class reverse_iterator +{ +private: + Iterator current; // 记录对应的正向迭代器 + +public: + // 反向迭代器的五种相应型别 + typedef typename iterator_traits::iterator_category iterator_category; + typedef typename iterator_traits::value_type value_type; + typedef typename iterator_traits::difference_type difference_type; + typedef typename iterator_traits::pointer pointer; + typedef typename iterator_traits::reference reference; + + typedef Iterator iterator_type; + typedef reverse_iterator self; + +public: + // 构造函数 + reverse_iterator() {} + explicit reverse_iterator(iterator_type i) :current(i) {} + reverse_iterator(const self& rhs) :current(rhs.current) {} + +public: + // 取出对应的正向迭代器 + iterator_type base() const + { return current; } + + // 重载操作符 + reference operator*() const + { // 实际对应正向迭代器的前一个位置 + auto tmp = current; + return *--tmp; + } + pointer operator->() const + { + return &(operator*()); + } + + // 前进(++)变为后退(--) + self& operator++() + { + --current; + return *this; + } + self operator++(int) + { + self tmp = *this; + --current; + return tmp; + } + // 后退(--)变为前进(++) + self& operator--() + { + ++current; + return *this; + } + self operator--(int) + { + self tmp = *this; + ++current; + return tmp; + } + + self& operator+=(difference_type n) + { + current -= n; + return *this; + } + self operator+(difference_type n) const + { + return self(current - n); + } + self& operator-=(difference_type n) + { + current += n; + return *this; + } + self operator-(difference_type n) const + { + return self(current + n); + } + + reference operator[](difference_type n) const + { + return *(*this + n); + } +}; + +// 重载 operator- +template +typename reverse_iterator::difference_type +operator-(const reverse_iterator& lhs, + const reverse_iterator& rhs) +{ + return rhs.base() - lhs.base(); +} + +// 重载比较操作符 +template +bool operator==(const reverse_iterator& lhs, + const reverse_iterator& rhs) +{ + return lhs.base() == rhs.base(); +} + +template +bool operator<(const reverse_iterator& lhs, + const reverse_iterator& rhs) +{ + return rhs.base() < lhs.base(); +} + +template +bool operator!=(const reverse_iterator& lhs, + const reverse_iterator& rhs) +{ + return !(lhs == rhs); +} + +template +bool operator>(const reverse_iterator& lhs, + const reverse_iterator& rhs) +{ + return rhs < lhs; +} + +template +bool operator<=(const reverse_iterator& lhs, + const reverse_iterator& rhs) +{ + return !(rhs < lhs); +} + +template +bool operator>=(const reverse_iterator& lhs, + const reverse_iterator& rhs) +{ + return !(lhs < rhs); +} + +} // namespace mystl + +#endif // !MYTINYSTL_ITERATOR_H_ + diff --git a/src/MyTinySTL-master/MyTinySTL-master/MyTinySTL/list.h b/src/MyTinySTL-master/MyTinySTL-master/MyTinySTL/list.h new file mode 100755 index 0000000..e6bfc1c --- /dev/null +++ b/src/MyTinySTL-master/MyTinySTL-master/MyTinySTL/list.h @@ -0,0 +1,1210 @@ +#ifndef MYTINYSTL_LIST_H_ +#define MYTINYSTL_LIST_H_ + +// 这个头文件包含了一个模板类 list +// list : 双向链表 + +// notes: +// +// 异常保证: +// mystl::list 满足基本异常保证,部分函数无异常保证,并对以下等函数做强异常安全保证: +// * emplace_front +// * emplace_back +// * emplace +// * push_front +// * push_back +// * insert + +#include + +#include "iterator.h" +#include "memory.h" +#include "functional.h" +#include "util.h" +#include "exceptdef.h" + +namespace mystl +{ + +template struct list_node_base; +template struct list_node; + +template +struct node_traits +{ + typedef list_node_base* base_ptr; + typedef list_node* node_ptr; +}; + +// list 的节点结构 + +template +struct list_node_base +{ + typedef typename node_traits::base_ptr base_ptr; + typedef typename node_traits::node_ptr node_ptr; + + base_ptr prev; // 前一节点 + base_ptr next; // 下一节点 + + list_node_base() = default; + + node_ptr as_node() + { + return static_cast(self()); + } + + void unlink() + { + prev = next = self(); + } + + base_ptr self() + { + return static_cast(&*this); + } +}; + +template +struct list_node : public list_node_base +{ + typedef typename node_traits::base_ptr base_ptr; + typedef typename node_traits::node_ptr node_ptr; + + T value; // 数据域 + + list_node() = default; + list_node(const T& v) + :value(v) + { + } + list_node(T&& v) + :value(mystl::move(v)) + { + } + + base_ptr as_base() + { + return static_cast(&*this); + } + node_ptr self() + { + return static_cast(&*this); + } +}; + +// list 的迭代器设计 +template +struct list_iterator : public mystl::iterator +{ + typedef T value_type; + typedef T* pointer; + typedef T& reference; + typedef typename node_traits::base_ptr base_ptr; + typedef typename node_traits::node_ptr node_ptr; + typedef list_iterator self; + + base_ptr node_; // 指向当前节点 + + // 构造函数 + list_iterator() = default; + list_iterator(base_ptr x) + :node_(x) {} + list_iterator(node_ptr x) + :node_(x->as_base()) {} + list_iterator(const list_iterator& rhs) + :node_(rhs.node_) {} + + // 重载操作符 + reference operator*() const { return node_->as_node()->value; } + pointer operator->() const { return &(operator*()); } + + self& operator++() + { + MYSTL_DEBUG(node_ != nullptr); + node_ = node_->next; + return *this; + } + self operator++(int) + { + self tmp = *this; + ++*this; + return tmp; + } + self& operator--() + { + MYSTL_DEBUG(node_ != nullptr); + node_ = node_->prev; + return *this; + } + self operator--(int) + { + self tmp = *this; + --*this; + return tmp; + } + + // 重载比较操作符 + bool operator==(const self& rhs) const { return node_ == rhs.node_; } + bool operator!=(const self& rhs) const { return node_ != rhs.node_; } +}; + +template +struct list_const_iterator : public iterator +{ + typedef T value_type; + typedef const T* pointer; + typedef const T& reference; + typedef typename node_traits::base_ptr base_ptr; + typedef typename node_traits::node_ptr node_ptr; + typedef list_const_iterator self; + + base_ptr node_; + + list_const_iterator() = default; + list_const_iterator(base_ptr x) + :node_(x) {} + list_const_iterator(node_ptr x) + :node_(x->as_base()) {} + list_const_iterator(const list_iterator& rhs) + :node_(rhs.node_) {} + list_const_iterator(const list_const_iterator& rhs) + :node_(rhs.node_) {} + + reference operator*() const { return node_->as_node()->value; } + pointer operator->() const { return &(operator*()); } + + self& operator++() + { + MYSTL_DEBUG(node_ != nullptr); + node_ = node_->next; + return *this; + } + self operator++(int) + { + self tmp = *this; + ++*this; + return tmp; + } + self& operator--() + { + MYSTL_DEBUG(node_ != nullptr); + node_ = node_->prev; + return *this; + } + self operator--(int) + { + self tmp = *this; + --*this; + return tmp; + } + + // 重载比较操作符 + bool operator==(const self& rhs) const { return node_ == rhs.node_; } + bool operator!=(const self& rhs) const { return node_ != rhs.node_; } +}; + +// 模板类: list +// 模板参数 T 代表数据类型 +template +class list +{ +public: + // list 的嵌套型别定义 + typedef mystl::allocator allocator_type; + typedef mystl::allocator data_allocator; + typedef mystl::allocator> base_allocator; + typedef mystl::allocator> node_allocator; + + typedef typename allocator_type::value_type value_type; + typedef typename allocator_type::pointer pointer; + typedef typename allocator_type::const_pointer const_pointer; + typedef typename allocator_type::reference reference; + typedef typename allocator_type::const_reference const_reference; + typedef typename allocator_type::size_type size_type; + typedef typename allocator_type::difference_type difference_type; + + typedef list_iterator iterator; + typedef list_const_iterator const_iterator; + typedef mystl::reverse_iterator reverse_iterator; + typedef mystl::reverse_iterator const_reverse_iterator; + + typedef typename node_traits::base_ptr base_ptr; + typedef typename node_traits::node_ptr node_ptr; + + allocator_type get_allocator() { return node_allocator(); } + +private: + base_ptr node_; // 指向末尾节点 + size_type size_; // 大小 + +public: + // 构造、复制、移动、析构函数 + list() + { fill_init(0, value_type()); } + + explicit list(size_type n) + { fill_init(n, value_type()); } + + list(size_type n, const T& value) + { fill_init(n, value); } + + template ::value, int>::type = 0> + list(Iter first, Iter last) + { copy_init(first, last); } + + list(std::initializer_list ilist) + { copy_init(ilist.begin(), ilist.end()); } + + list(const list& rhs) + { copy_init(rhs.cbegin(), rhs.cend()); } + + list(list&& rhs) noexcept + :node_(rhs.node_), size_(rhs.size_) + { + rhs.node_ = nullptr; + rhs.size_ = 0; + } + + list& operator=(const list& rhs) + { + if (this != &rhs) + { + assign(rhs.begin(), rhs.end()); + } + return *this; + } + + list& operator=(list&& rhs) noexcept + { + clear(); + splice(end(), rhs); + return *this; + } + + list& operator=(std::initializer_list ilist) + { + list tmp(ilist.begin(), ilist.end()); + swap(tmp); + return *this; + } + + ~list() + { + if (node_) + { + clear(); + base_allocator::deallocate(node_); + node_ = nullptr; + size_ = 0; + } + } + +public: + // 迭代器相关操作 + iterator begin() noexcept + { return node_->next; } + const_iterator begin() const noexcept + { return node_->next; } + iterator end() noexcept + { return node_; } + const_iterator end() const noexcept + { return node_; } + + reverse_iterator rbegin() noexcept + { return reverse_iterator(end()); } + const_reverse_iterator rbegin() const noexcept + { return reverse_iterator(end()); } + reverse_iterator rend() noexcept + { return reverse_iterator(begin()); } + const_reverse_iterator rend() const noexcept + { return reverse_iterator(begin()); } + + const_iterator cbegin() const noexcept + { return begin(); } + const_iterator cend() const noexcept + { return end(); } + const_reverse_iterator crbegin() const noexcept + { return rbegin(); } + const_reverse_iterator crend() const noexcept + { return rend(); } + + // 容量相关操作 + bool empty() const noexcept + { return node_->next == node_; } + + size_type size() const noexcept + { return size_; } + + size_type max_size() const noexcept + { return static_cast(-1); } + + // 访问元素相关操作 + reference front() + { + MYSTL_DEBUG(!empty()); + return *begin(); + } + + const_reference front() const + { + MYSTL_DEBUG(!empty()); + return *begin(); + } + + reference back() + { + MYSTL_DEBUG(!empty()); + return *(--end()); + } + + const_reference back() const + { + MYSTL_DEBUG(!empty()); + return *(--end()); + } + + // 调整容器相关操作 + + // assign + + void assign(size_type n, const value_type& value) + { fill_assign(n, value); } + + template ::value, int>::type = 0> + void assign(Iter first, Iter last) + { copy_assign(first, last); } + + void assign(std::initializer_list ilist) + { copy_assign(ilist.begin(), ilist.end()); } + + // emplace_front / emplace_back / emplace + + template + void emplace_front(Args&& ...args) + { + THROW_LENGTH_ERROR_IF(size_ > max_size() - 1, "list's size too big"); + auto link_node = create_node(mystl::forward(args)...); + link_nodes_at_front(link_node->as_base(), link_node->as_base()); + ++size_; + } + + template + void emplace_back(Args&& ...args) + { + THROW_LENGTH_ERROR_IF(size_ > max_size() - 1, "list's size too big"); + auto link_node = create_node(mystl::forward(args)...); + link_nodes_at_back(link_node->as_base(), link_node->as_base()); + ++size_; + } + + template + iterator emplace(const_iterator pos, Args&& ...args) + { + THROW_LENGTH_ERROR_IF(size_ > max_size() - 1, "list's size too big"); + auto link_node = create_node(mystl::forward(args)...); + link_nodes(pos.node_, link_node->as_base(), link_node->as_base()); + ++size_; + return iterator(link_node); + } + + // insert + + iterator insert(const_iterator pos, const value_type& value) + { + THROW_LENGTH_ERROR_IF(size_ > max_size() - 1, "list's size too big"); + auto link_node = create_node(value); + ++size_; + return link_iter_node(pos, link_node->as_base()); + } + + iterator insert(const_iterator pos, value_type&& value) + { + THROW_LENGTH_ERROR_IF(size_ > max_size() - 1, "list's size too big"); + auto link_node = create_node(mystl::move(value)); + ++size_; + return link_iter_node(pos, link_node->as_base()); + } + + iterator insert(const_iterator pos, size_type n, const value_type& value) + { + THROW_LENGTH_ERROR_IF(size_ > max_size() - n, "list's size too big"); + return fill_insert(pos, n, value); + } + + template ::value, int>::type = 0> + iterator insert(const_iterator pos, Iter first, Iter last) + { + size_type n = mystl::distance(first, last); + THROW_LENGTH_ERROR_IF(size_ > max_size() - n, "list's size too big"); + return copy_insert(pos, n, first); + } + + // push_front / push_back + + void push_front(const value_type& value) + { + THROW_LENGTH_ERROR_IF(size_ > max_size() - 1, "list's size too big"); + auto link_node = create_node(value); + link_nodes_at_front(link_node->as_base(), link_node->as_base()); + ++size_; + } + + void push_front(value_type&& value) + { + emplace_front(mystl::move(value)); + } + + void push_back(const value_type& value) + { + THROW_LENGTH_ERROR_IF(size_ > max_size() - 1, "list's size too big"); + auto link_node = create_node(value); + link_nodes_at_back(link_node->as_base(), link_node->as_base()); + ++size_; + } + + void push_back(value_type&& value) + { + emplace_back(mystl::move(value)); + } + + // pop_front / pop_back + + void pop_front() + { + MYSTL_DEBUG(!empty()); + auto n = node_->next; + unlink_nodes(n, n); + destroy_node(n->as_node()); + --size_; + } + + void pop_back() + { + MYSTL_DEBUG(!empty()); + auto n = node_->prev; + unlink_nodes(n, n); + destroy_node(n->as_node()); + --size_; + } + + // erase / clear + + iterator erase(const_iterator pos); + iterator erase(const_iterator first, const_iterator last); + + void clear(); + + // resize + + void resize(size_type new_size) { resize(new_size, value_type()); } + void resize(size_type new_size, const value_type& value); + + void swap(list& rhs) noexcept + { + mystl::swap(node_, rhs.node_); + mystl::swap(size_, rhs.size_); + } + + // list 相关操作 + + void splice(const_iterator pos, list& other); + void splice(const_iterator pos, list& other, const_iterator it); + void splice(const_iterator pos, list& other, const_iterator first, const_iterator last); + + void remove(const value_type& value) + { remove_if([&](const value_type& v) {return v == value; }); } + template + void remove_if(UnaryPredicate pred); + + void unique() + { unique(mystl::equal_to()); } + template + void unique(BinaryPredicate pred); + + void merge(list& x) + { merge(x, mystl::less()); } + template + void merge(list& x, Compare comp); + + void sort() + { list_sort(begin(), end(), size(), mystl::less()); } + template + void sort(Compared comp) + { list_sort(begin(), end(), size(), comp); } + + void reverse(); + +private: + // helper functions + + // create / destroy node + template + node_ptr create_node(Args&& ...agrs); + void destroy_node(node_ptr p); + + // initialize + void fill_init(size_type n, const value_type& value); + template + void copy_init(Iter first, Iter last); + + // link / unlink + iterator link_iter_node(const_iterator pos, base_ptr node); + void link_nodes(base_ptr p, base_ptr first, base_ptr last); + void link_nodes_at_front(base_ptr first, base_ptr last); + void link_nodes_at_back(base_ptr first, base_ptr last); + void unlink_nodes(base_ptr f, base_ptr l); + + // assign + void fill_assign(size_type n, const value_type& value); + template + void copy_assign(Iter first, Iter last); + + // insert + iterator fill_insert(const_iterator pos, size_type n, const value_type& value); + template + iterator copy_insert(const_iterator pos, size_type n, Iter first); + + // sort + template + iterator list_sort(iterator first, iterator last, size_type n, Compared comp); + +}; + +/*****************************************************************************************/ + +// 删除 pos 处的元素 +template +typename list::iterator +list::erase(const_iterator pos) +{ + MYSTL_DEBUG(pos != cend()); + auto n = pos.node_; + auto next = n->next; + unlink_nodes(n, n); + destroy_node(n->as_node()); + --size_; + return iterator(next); +} + +// 删除 [first, last) 内的元素 +template +typename list::iterator +list::erase(const_iterator first, const_iterator last) +{ + if (first != last) + { + unlink_nodes(first.node_, last.node_->prev); + while (first != last) + { + auto cur = first.node_; + ++first; + destroy_node(cur->as_node()); + --size_; + } + } + return iterator(last.node_); +} + +// 清空 list +template +void list::clear() +{ + if (size_ != 0) + { + auto cur = node_->next; + for (base_ptr next = cur->next; cur != node_; cur = next, next = cur->next) + { + destroy_node(cur->as_node()); + } + node_->unlink(); + size_ = 0; + } +} + +// 重置容器大小 +template +void list::resize(size_type new_size, const value_type& value) +{ + auto i = begin(); + size_type len = 0; + while (i != end() && len < new_size) + { + ++i; + ++len; + } + if (len == new_size) + { + erase(i, node_); + } + else + { + insert(node_, new_size - len, value); + } +} + +// 将 list x 接合于 pos 之前 +template +void list::splice(const_iterator pos, list& x) +{ + MYSTL_DEBUG(this != &x); + if (!x.empty()) + { + THROW_LENGTH_ERROR_IF(size_ > max_size() - x.size_, "list's size too big"); + + auto f = x.node_->next; + auto l = x.node_->prev; + + x.unlink_nodes(f, l); + link_nodes(pos.node_, f, l); + + size_ += x.size_; + x.size_ = 0; + } +} + +// 将 it 所指的节点接合于 pos 之前 +template +void list::splice(const_iterator pos, list& x, const_iterator it) +{ + if (pos.node_ != it.node_ && pos.node_ != it.node_->next) + { + THROW_LENGTH_ERROR_IF(size_ > max_size() - 1, "list's size too big"); + + auto f = it.node_; + + x.unlink_nodes(f, f); + link_nodes(pos.node_, f, f); + + ++size_; + --x.size_; + } +} + +// 将 list x 的 [first, last) 内的节点接合于 pos 之前 +template +void list::splice(const_iterator pos, list& x, const_iterator first, const_iterator last) +{ + if (first != last && this != &x) + { + size_type n = mystl::distance(first, last); + THROW_LENGTH_ERROR_IF(size_ > max_size() - n, "list's size too big"); + auto f = first.node_; + auto l = last.node_->prev; + + x.unlink_nodes(f, l); + link_nodes(pos.node_, f, l); + + size_ += n; + x.size_ -= n; + } +} + +// 将另一元操作 pred 为 true 的所有元素移除 +template +template +void list::remove_if(UnaryPredicate pred) +{ + auto f = begin(); + auto l = end(); + for (auto next = f; f != l; f = next) + { + ++next; + if (pred(*f)) + { + erase(f); + } + } +} + +// 移除 list 中满足 pred 为 true 重复元素 +template +template +void list::unique(BinaryPredicate pred) +{ + auto i = begin(); + auto e = end(); + auto j = i; + ++j; + while (j != e) + { + if (pred(*i, *j)) + { + erase(j); + } + else + { + i = j; + } + j = i; + ++j; + } +} + +// 与另一个 list 合并,按照 comp 为 true 的顺序 +template +template +void list::merge(list& x, Compare comp) +{ + if (this != &x) + { + THROW_LENGTH_ERROR_IF(size_ > max_size() - x.size_, "list's size too big"); + + auto f1 = begin(); + auto l1 = end(); + auto f2 = x.begin(); + auto l2 = x.end(); + + while (f1 != l1 && f2 != l2) + { + if (comp(*f2, *f1)) + { + // 使 comp 为 true 的一段区间 + auto next = f2; + ++next; + for (; next != l2 && comp(*next, *f1); ++next) + ; + auto f = f2.node_; + auto l = next.node_->prev; + f2 = next; + + // link node + x.unlink_nodes(f, l); + link_nodes(f1.node_, f, l); + ++f1; + } + else + { + ++f1; + } + } + // 连接剩余部分 + if (f2 != l2) + { + auto f = f2.node_; + auto l = l2.node_->prev; + x.unlink_nodes(f, l); + link_nodes(l1.node_, f, l); + } + + size_ += x.size_; + x.size_ = 0; + } +} + +// 将 list 反转 +template +void list::reverse() +{ + if (size_ <= 1) + { + return; + } + auto i = begin(); + auto e = end(); + while (i.node_ != e.node_) + { + mystl::swap(i.node_->prev, i.node_->next); + i.node_ = i.node_->prev; + } + mystl::swap(e.node_->prev, e.node_->next); +} + +/*****************************************************************************************/ +// helper function + +// 创建结点 +template +template +typename list::node_ptr +list::create_node(Args&& ...args) +{ + node_ptr p = node_allocator::allocate(1); + try + { + data_allocator::construct(mystl::address_of(p->value), mystl::forward(args)...); + p->prev = nullptr; + p->next = nullptr; + } + catch (...) + { + node_allocator::deallocate(p); + throw; + } + return p; +} + +// 销毁结点 +template +void list::destroy_node(node_ptr p) +{ + data_allocator::destroy(mystl::address_of(p->value)); + node_allocator::deallocate(p); +} + +// 用 n 个元素初始化容器 +template +void list::fill_init(size_type n, const value_type& value) +{ + node_ = base_allocator::allocate(1); + node_->unlink(); + size_ = n; + try + { + for (; n > 0; --n) + { + auto node = create_node(value); + link_nodes_at_back(node->as_base(), node->as_base()); + } + } + catch (...) + { + clear(); + base_allocator::deallocate(node_); + node_ = nullptr; + throw; + } +} + +// 以 [first, last) 初始化容器 +template +template +void list::copy_init(Iter first, Iter last) +{ + node_ = base_allocator::allocate(1); + node_->unlink(); + size_type n = mystl::distance(first, last); + size_ = n; + try + { + for (; n > 0; --n, ++first) + { + auto node = create_node(*first); + link_nodes_at_back(node->as_base(), node->as_base()); + } + } + catch (...) + { + clear(); + base_allocator::deallocate(node_); + node_ = nullptr; + throw; + } +} + +// 在 pos 处连接一个节点 +template +typename list::iterator +list::link_iter_node(const_iterator pos, base_ptr link_node) +{ + if (pos == node_->next) + { + link_nodes_at_front(link_node, link_node); + } + else if (pos == node_) + { + link_nodes_at_back(link_node, link_node); + } + else + { + link_nodes(pos.node_, link_node, link_node); + } + return iterator(link_node); +} + +// 在 pos 处连接 [first, last] 的结点 +template +void list::link_nodes(base_ptr pos, base_ptr first, base_ptr last) +{ + pos->prev->next = first; + first->prev = pos->prev; + pos->prev = last; + last->next = pos; +} + +// 在头部连接 [first, last] 结点 +template +void list::link_nodes_at_front(base_ptr first, base_ptr last) +{ + first->prev = node_; + last->next = node_->next; + last->next->prev = last; + node_->next = first; +} + +// 在尾部连接 [first, last] 结点 +template +void list::link_nodes_at_back(base_ptr first, base_ptr last) +{ + last->next = node_; + first->prev = node_->prev; + first->prev->next = first; + node_->prev = last; +} + +// 容器与 [first, last] 结点断开连接 +template +void list::unlink_nodes(base_ptr first, base_ptr last) +{ + first->prev->next = last->next; + last->next->prev = first->prev; +} + +// 用 n 个元素为容器赋值 +template +void list::fill_assign(size_type n, const value_type& value) +{ + auto i = begin(); + auto e = end(); + for (; n > 0 && i != e; --n, ++i) + { + *i = value; + } + if (n > 0) + { + insert(e, n, value); + } + else + { + erase(i, e); + } +} + +// 复制[f2, l2)为容器赋值 +template +template +void list::copy_assign(Iter f2, Iter l2) +{ + auto f1 = begin(); + auto l1 = end(); + for (; f1 != l1 && f2 != l2; ++f1, ++f2) + { + *f1 = *f2; + } + if (f2 == l2) + { + erase(f1, l1); + } + else + { + insert(l1, f2, l2); + } +} + +// 在 pos 处插入 n 个元素 +template +typename list::iterator +list::fill_insert(const_iterator pos, size_type n, const value_type& value) +{ + iterator r(pos.node_); + if (n != 0) + { + const auto add_size = n; + auto node = create_node(value); + node->prev = nullptr; + r = iterator(node); + iterator end = r; + try + { + // 前面已经创建了一个节点,还需 n - 1 个 + for (--n; n > 0; --n, ++end) + { + auto next = create_node(value); + end.node_->next = next->as_base(); // link node + next->prev = end.node_; + } + size_ += add_size; + } + catch (...) + { + auto enode = end.node_; + while (true) + { + auto prev = enode->prev; + destroy_node(enode->as_node()); + if (prev == nullptr) + break; + enode = prev; + } + throw; + } + link_nodes(pos.node_, r.node_, end.node_); + } + return r; +} + +// 在 pos 处插入 [first, last) 的元素 +template +template +typename list::iterator +list::copy_insert(const_iterator pos, size_type n, Iter first) +{ + iterator r(pos.node_); + if (n != 0) + { + const auto add_size = n; + auto node = create_node(*first); + node->prev = nullptr; + r = iterator(node); + iterator end = r; + try + { + for (--n, ++first; n > 0; --n, ++first, ++end) + { + auto next = create_node(*first); + end.node_->next = next->as_base(); // link node + next->prev = end.node_; + } + size_ += add_size; + } + catch (...) + { + auto enode = end.node_; + while (true) + { + auto prev = enode->prev; + destroy_node(enode->as_node()); + if (prev == nullptr) + break; + enode = prev; + } + throw; + } + link_nodes(pos.node_, r.node_, end.node_); + } + return r; +} + +// 对 list 进行归并排序,返回一个迭代器指向区间最小元素的位置 +template +template +typename list::iterator +list::list_sort(iterator f1, iterator l2, size_type n, Compared comp) +{ + if (n < 2) + return f1; + + if (n == 2) + { + if (comp(*--l2, *f1)) + { + auto ln = l2.node_; + unlink_nodes(ln, ln); + link_nodes(f1.node_, ln, ln); + return l2; + } + return f1; + } + + auto n2 = n / 2; + auto l1 = f1; + mystl::advance(l1, n2); + auto result = f1 = list_sort(f1, l1, n2, comp); // 前半段的最小位置 + auto f2 = l1 = list_sort(l1, l2, n - n2, comp); // 后半段的最小位置 + + // 把较小的一段区间移到前面 + if (comp(*f2, *f1)) + { + auto m = f2; + ++m; + for (; m != l2 && comp(*m, *f1); ++m) + ; + auto f = f2.node_; + auto l = m.node_->prev; + result = f2; + l1 = f2 = m; + unlink_nodes(f, l); + m = f1; + ++m; + link_nodes(f1.node_, f, l); + f1 = m; + } + else + { + ++f1; + } + + // 合并两段有序区间 + while (f1 != l1 && f2 != l2) + { + if (comp(*f2, *f1)) + { + auto m = f2; + ++m; + for (; m != l2 && comp(*m, *f1); ++m) + ; + auto f = f2.node_; + auto l = m.node_->prev; + if (l1 == f2) + l1 = m; + f2 = m; + unlink_nodes(f, l); + m = f1; + ++m; + link_nodes(f1.node_, f, l); + f1 = m; + } + else + { + ++f1; + } + } + return result; +} + +// 重载比较操作符 +template +bool operator==(const list& lhs, const list& rhs) +{ + auto f1 = lhs.cbegin(); + auto f2 = rhs.cbegin(); + auto l1 = lhs.cend(); + auto l2 = rhs.cend(); + for (; f1 != l1 && f2 != l2 && *f1 == *f2; ++f1, ++f2) + ; + return f1 == l1 && f2 == l2; +} + +template +bool operator<(const list& lhs, const list& rhs) +{ + return mystl::lexicographical_compare(lhs.cbegin(), lhs.cend(), rhs.cbegin(), rhs.cend()); +} + +template +bool operator!=(const list& lhs, const list& rhs) +{ + return !(lhs == rhs); +} + +template +bool operator>(const list& lhs, const list& rhs) +{ + return rhs < lhs; +} + +template +bool operator<=(const list& lhs, const list& rhs) +{ + return !(rhs < lhs); +} + +template +bool operator>=(const list& lhs, const list& rhs) +{ + return !(lhs < rhs); +} + +// 重载 mystl 的 swap +template +void swap(list& lhs, list& rhs) noexcept +{ + lhs.swap(rhs); +} + +} // namespace mystl +#endif // !MYTINYSTL_LIST_H_ + diff --git a/src/MyTinySTL-master/MyTinySTL-master/MyTinySTL/map.h b/src/MyTinySTL-master/MyTinySTL-master/MyTinySTL/map.h new file mode 100755 index 0000000..da61c59 --- /dev/null +++ b/src/MyTinySTL-master/MyTinySTL-master/MyTinySTL/map.h @@ -0,0 +1,549 @@ +#ifndef MYTINYSTL_MAP_H_ +#define MYTINYSTL_MAP_H_ + +// 这个头文件包含了两个模板类 map 和 multimap +// map : 映射,元素具有键值和实值,会根据键值大小自动排序,键值不允许重复 +// multimap : 映射,元素具有键值和实值,会根据键值大小自动排序,键值允许重复 + +// notes: +// +// 异常保证: +// mystl::map / mystl::multimap 满足基本异常保证,对以下等函数做强异常安全保证: +// * emplace +// * emplace_hint +// * insert + +#include "rb_tree.h" + +namespace mystl +{ + +// 模板类 map,键值不允许重复 +// 参数一代表键值类型,参数二代表实值类型,参数三代表键值的比较方式,缺省使用 mystl::less +template > +class map +{ +public: + // map 的嵌套型别定义 + typedef Key key_type; + typedef T mapped_type; + typedef mystl::pair value_type; + typedef Compare key_compare; + + // 定义一个 functor,用来进行元素比较 + class value_compare : public binary_function + { + friend class map; + private: + Compare comp; + value_compare(Compare c) : comp(c) {} + public: + bool operator()(const value_type& lhs, const value_type& rhs) const + { + return comp(lhs.first, rhs.first); // 比较键值的大小 + } + }; + +private: + // 以 mystl::rb_tree 作为底层机制 + typedef mystl::rb_tree base_type; + base_type tree_; + +public: + // 使用 rb_tree 的型别 + typedef typename base_type::node_type node_type; + typedef typename base_type::pointer pointer; + typedef typename base_type::const_pointer const_pointer; + typedef typename base_type::reference reference; + typedef typename base_type::const_reference const_reference; + typedef typename base_type::iterator iterator; + typedef typename base_type::const_iterator const_iterator; + typedef typename base_type::reverse_iterator reverse_iterator; + typedef typename base_type::const_reverse_iterator const_reverse_iterator; + typedef typename base_type::size_type size_type; + typedef typename base_type::difference_type difference_type; + typedef typename base_type::allocator_type allocator_type; + +public: + // 构造、复制、移动、赋值函数 + + map() = default; + + template + map(InputIterator first, InputIterator last) + :tree_() + { tree_.insert_unique(first, last); } + + map(std::initializer_list ilist) + :tree_() + { tree_.insert_unique(ilist.begin(), ilist.end()); } + + map(const map& rhs) + :tree_(rhs.tree_) + { + } + map(map&& rhs) noexcept + :tree_(mystl::move(rhs.tree_)) + { + } + + map& operator=(const map& rhs) + { + tree_ = rhs.tree_; + return *this; + } + map& operator=(map&& rhs) + { + tree_ = mystl::move(rhs.tree_); + return *this; + } + + map& operator=(std::initializer_list ilist) + { + tree_.clear(); + tree_.insert_unique(ilist.begin(), ilist.end()); + return *this; + } + + // 相关接口 + + key_compare key_comp() const { return tree_.key_comp(); } + value_compare value_comp() const { return value_compare(tree_.key_comp()); } + allocator_type get_allocator() const { return tree_.get_allocator(); } + + // 迭代器相关 + + iterator begin() noexcept + { return tree_.begin(); } + const_iterator begin() const noexcept + { return tree_.begin(); } + iterator end() noexcept + { return tree_.end(); } + const_iterator end() const noexcept + { return tree_.end(); } + + reverse_iterator rbegin() noexcept + { return reverse_iterator(end()); } + const_reverse_iterator rbegin() const noexcept + { return const_reverse_iterator(end()); } + reverse_iterator rend() noexcept + { return reverse_iterator(begin()); } + const_reverse_iterator rend() const noexcept + { return const_reverse_iterator(begin()); } + + const_iterator cbegin() const noexcept + { return begin(); } + const_iterator cend() const noexcept + { return end(); } + const_reverse_iterator crbegin() const noexcept + { return rbegin(); } + const_reverse_iterator crend() const noexcept + { return rend(); } + + // 容量相关 + bool empty() const noexcept { return tree_.empty(); } + size_type size() const noexcept { return tree_.size(); } + size_type max_size() const noexcept { return tree_.max_size(); } + + // 访问元素相关 + + // 若键值不存在,at 会抛出一个异常 + mapped_type& at(const key_type& key) + { + iterator it = lower_bound(key); + // it->first >= key + THROW_OUT_OF_RANGE_IF(it == end() || key_comp()(it->first, key), + "map no such element exists"); + return it->second; + } + const mapped_type& at(const key_type& key) const + { + const_iterator it = lower_bound(key); + // it->first >= key + THROW_OUT_OF_RANGE_IF(it == end() || key_comp()(it->first, key), + "map no such element exists"); + return it->second; + } + + mapped_type& operator[](const key_type& key) + { + iterator it = lower_bound(key); + // it->first >= key + if (it == end() || key_comp()(key, it->first)) + it = emplace_hint(it, key, T{}); + return it->second; + } + mapped_type& operator[](key_type&& key) + { + iterator it = lower_bound(key); + // it->first >= key + if (it == end() || key_comp()(key, it->first)) + it = emplace_hint(it, mystl::move(key), T{}); + return it->second; + } + + // 插入删除相关 + + template + pair emplace(Args&& ...args) + { + return tree_.emplace_unique(mystl::forward(args)...); + } + + template + iterator emplace_hint(iterator hint, Args&& ...args) + { + return tree_.emplace_unique_use_hint(hint, mystl::forward(args)...); + } + + pair insert(const value_type& value) + { + return tree_.insert_unique(value); + } + pair insert(value_type&& value) + { + return tree_.insert_unique(mystl::move(value)); + } + + iterator insert(iterator hint, const value_type& value) + { + return tree_.insert_unique(hint, value); + } + iterator insert(iterator hint, value_type&& value) + { + return tree_.insert_unique(hint, mystl::move(value)); + } + + template + void insert(InputIterator first, InputIterator last) + { + tree_.insert_unique(first, last); + } + + void erase(iterator position) { tree_.erase(position); } + size_type erase(const key_type& key) { return tree_.erase_unique(key); } + void erase(iterator first, iterator last) { tree_.erase(first, last); } + + void clear() { tree_.clear(); } + + // map 相关操作 + + iterator find(const key_type& key) { return tree_.find(key); } + const_iterator find(const key_type& key) const { return tree_.find(key); } + + size_type count(const key_type& key) const { return tree_.count_unique(key); } + + iterator lower_bound(const key_type& key) { return tree_.lower_bound(key); } + const_iterator lower_bound(const key_type& key) const { return tree_.lower_bound(key); } + + iterator upper_bound(const key_type& key) { return tree_.upper_bound(key); } + const_iterator upper_bound(const key_type& key) const { return tree_.upper_bound(key); } + + pair + equal_range(const key_type& key) + { return tree_.equal_range_unique(key); } + + pair + equal_range(const key_type& key) const + { return tree_.equal_range_unique(key); } + + void swap(map& rhs) noexcept + { tree_.swap(rhs.tree_); } + +public: + friend bool operator==(const map& lhs, const map& rhs) { return lhs.tree_ == rhs.tree_; } + friend bool operator< (const map& lhs, const map& rhs) { return lhs.tree_ < rhs.tree_; } +}; + +// 重载比较操作符 +template +bool operator==(const map& lhs, const map& rhs) +{ + return lhs == rhs; +} + +template +bool operator<(const map& lhs, const map& rhs) +{ + return lhs < rhs; +} + +template +bool operator!=(const map& lhs, const map& rhs) +{ + return !(lhs == rhs); +} + +template +bool operator>(const map& lhs, const map& rhs) +{ + return rhs < lhs; +} + +template +bool operator<=(const map& lhs, const map& rhs) +{ + return !(rhs < lhs); +} + +template +bool operator>=(const map& lhs, const map& rhs) +{ + return !(lhs < rhs); +} + +// 重载 mystl 的 swap +template +void swap(map& lhs, map& rhs) noexcept +{ + lhs.swap(rhs); +} + +/*****************************************************************************************/ + +// 模板类 multimap,键值允许重复 +// 参数一代表键值类型,参数二代表实值类型,参数三代表键值的比较方式,缺省使用 mystl::less +template > +class multimap +{ +public: + // multimap 的型别定义 + typedef Key key_type; + typedef T mapped_type; + typedef mystl::pair value_type; + typedef Compare key_compare; + + // 定义一个 functor,用来进行元素比较 + class value_compare : public binary_function + { + friend class multimap; + private: + Compare comp; + value_compare(Compare c) : comp(c) {} + public: + bool operator()(const value_type& lhs, const value_type& rhs) const + { + return comp(lhs.first, rhs.first); + } + }; + +private: + // 用 mystl::rb_tree 作为底层机制 + typedef mystl::rb_tree base_type; + base_type tree_; + +public: + // 使用 rb_tree 的型别 + typedef typename base_type::node_type node_type; + typedef typename base_type::pointer pointer; + typedef typename base_type::const_pointer const_pointer; + typedef typename base_type::reference reference; + typedef typename base_type::const_reference const_reference; + typedef typename base_type::iterator iterator; + typedef typename base_type::const_iterator const_iterator; + typedef typename base_type::reverse_iterator reverse_iterator; + typedef typename base_type::const_reverse_iterator const_reverse_iterator; + typedef typename base_type::size_type size_type; + typedef typename base_type::difference_type difference_type; + typedef typename base_type::allocator_type allocator_type; + +public: + // 构造、复制、移动函数 + + multimap() = default; + + template + multimap(InputIterator first, InputIterator last) + :tree_() + { tree_.insert_multi(first, last); } + multimap(std::initializer_list ilist) + :tree_() + { tree_.insert_multi(ilist.begin(), ilist.end()); } + + multimap(const multimap& rhs) + :tree_(rhs.tree_) + { + } + multimap(multimap&& rhs) noexcept + :tree_(mystl::move(rhs.tree_)) + { + } + + multimap& operator=(const multimap& rhs) + { + tree_ = rhs.tree_; + return *this; + } + multimap& operator=(multimap&& rhs) + { + tree_ = mystl::move(rhs.tree_); + return *this; + } + + multimap& operator=(std::initializer_list ilist) + { + tree_.clear(); + tree_.insert_multi(ilist.begin(), ilist.end()); + return *this; + } + + // 相关接口 + + key_compare key_comp() const { return tree_.key_comp(); } + value_compare value_comp() const { return value_compare(tree_.key_comp()); } + allocator_type get_allocator() const { return tree_.get_allocator(); } + + // 迭代器相关 + + iterator begin() noexcept + { return tree_.begin(); } + const_iterator begin() const noexcept + { return tree_.begin(); } + iterator end() noexcept + { return tree_.end(); } + const_iterator end() const noexcept + { return tree_.end(); } + + reverse_iterator rbegin() noexcept + { return reverse_iterator(end()); } + const_reverse_iterator rbegin() const noexcept + { return const_reverse_iterator(end()); } + reverse_iterator rend() noexcept + { return reverse_iterator(begin()); } + const_reverse_iterator rend() const noexcept + { return const_reverse_iterator(begin()); } + + const_iterator cbegin() const noexcept + { return begin(); } + const_iterator cend() const noexcept + { return end(); } + const_reverse_iterator crbegin() const noexcept + { return rbegin(); } + const_reverse_iterator crend() const noexcept + { return rend(); } + + // 容量相关 + bool empty() const noexcept { return tree_.empty(); } + size_type size() const noexcept { return tree_.size(); } + size_type max_size() const noexcept { return tree_.max_size(); } + + // 插入删除操作 + + template + iterator emplace(Args&& ...args) + { + return tree_.emplace_multi(mystl::forward(args)...); + } + + template + iterator emplace_hint(iterator hint, Args&& ...args) + { + return tree_.emplace_multi_use_hint(hint, mystl::forward(args)...); + } + + iterator insert(const value_type& value) + { + return tree_.insert_multi(value); + } + iterator insert(value_type&& value) + { + return tree_.insert_multi(mystl::move(value)); + } + + iterator insert(iterator hint, const value_type& value) + { + return tree_.insert_multi(hint, value); + } + iterator insert(iterator hint, value_type&& value) + { + return tree_.insert_multi(hint, mystl::move(value)); + } + + template + void insert(InputIterator first, InputIterator last) + { + tree_.insert_multi(first, last); + } + + void erase(iterator position) { tree_.erase(position); } + size_type erase(const key_type& key) { return tree_.erase_multi(key); } + void erase(iterator first, iterator last) { tree_.erase(first, last); } + + void clear() { tree_.clear(); } + + // multimap 相关操作 + + iterator find(const key_type& key) { return tree_.find(key); } + const_iterator find(const key_type& key) const { return tree_.find(key); } + + size_type count(const key_type& key) const { return tree_.count_multi(key); } + + iterator lower_bound(const key_type& key) { return tree_.lower_bound(key); } + const_iterator lower_bound(const key_type& key) const { return tree_.lower_bound(key); } + + iterator upper_bound(const key_type& key) { return tree_.upper_bound(key); } + const_iterator upper_bound(const key_type& key) const { return tree_.upper_bound(key); } + + pair + equal_range(const key_type& key) + { return tree_.equal_range_multi(key); } + + pair + equal_range(const key_type& key) const + { return tree_.equal_range_multi(key); } + + void swap(multimap& rhs) noexcept + { tree_.swap(rhs.tree_); } + +public: + friend bool operator==(const multimap& lhs, const multimap& rhs) { return lhs.tree_ == rhs.tree_; } + friend bool operator< (const multimap& lhs, const multimap& rhs) { return lhs.tree_ < rhs.tree_; } +}; + +// 重载比较操作符 +template +bool operator==(const multimap& lhs, const multimap& rhs) +{ + return lhs == rhs; +} + +template +bool operator<(const multimap& lhs, const multimap& rhs) +{ + return lhs < rhs; +} + +template +bool operator!=(const multimap& lhs, const multimap& rhs) +{ + return !(lhs == rhs); +} + +template +bool operator>(const multimap& lhs, const multimap& rhs) +{ + return rhs < lhs; +} + +template +bool operator<=(const multimap& lhs, const multimap& rhs) +{ + return !(rhs < lhs); +} + +template +bool operator>=(const multimap& lhs, const multimap& rhs) +{ + return !(lhs < rhs); +} + +// 重载 mystl 的 swap +template +void swap(multimap& lhs, multimap& rhs) noexcept +{ + lhs.swap(rhs); +} + +} // namespace mystl +#endif // !MYTINYSTL_MAP_H_ + diff --git a/src/MyTinySTL-master/MyTinySTL-master/MyTinySTL/memory.h b/src/MyTinySTL-master/MyTinySTL-master/MyTinySTL/memory.h new file mode 100755 index 0000000..c24e42c --- /dev/null +++ b/src/MyTinySTL-master/MyTinySTL-master/MyTinySTL/memory.h @@ -0,0 +1,208 @@ +#ifndef MYTINYSTL_MEMORY_H_ +#define MYTINYSTL_MEMORY_H_ + +// 这个头文件负责更高级的动态内存管理 +// 包含一些基本函数、空间配置器、未初始化的储存空间管理,以及一个模板类 auto_ptr + +#include +#include +#include + +#include "algobase.h" +#include "allocator.h" +#include "construct.h" +#include "uninitialized.h" + +namespace mystl +{ + +// 获取对象地址 +template +constexpr Tp* address_of(Tp& value) noexcept +{ + return &value; +} + +// 获取 / 释放 临时缓冲区 + +template +pair get_buffer_helper(ptrdiff_t len, T*) +{ + if (len > static_cast(INT_MAX / sizeof(T))) + len = INT_MAX / sizeof(T); + while (len > 0) + { + T* tmp = static_cast(malloc(static_cast(len) * sizeof(T))); + if (tmp) + return pair(tmp, len); + len /= 2; // 申请失败时减少 len 的大小 + } + return pair(nullptr, 0); +} + +template +pair get_temporary_buffer(ptrdiff_t len) +{ + return get_buffer_helper(len, static_cast(0)); +} + +template +pair get_temporary_buffer(ptrdiff_t len, T*) +{ + return get_buffer_helper(len, static_cast(0)); +} + +template +void release_temporary_buffer(T* ptr) +{ + free(ptr); +} + +// -------------------------------------------------------------------------------------- +// 类模板 : temporary_buffer +// 进行临时缓冲区的申请与释放 +template +class temporary_buffer +{ +private: + ptrdiff_t original_len; // 缓冲区申请的大小 + ptrdiff_t len; // 缓冲区实际的大小 + T* buffer; // 指向缓冲区的指针 + +public: + // 构造、析构函数 + temporary_buffer(ForwardIterator first, ForwardIterator last); + + ~temporary_buffer() + { + mystl::destroy(buffer, buffer + len); + free(buffer); + } + +public: + + ptrdiff_t size() const noexcept { return len; } + ptrdiff_t requested_size() const noexcept { return original_len; } + T* begin() noexcept { return buffer; } + T* end() noexcept { return buffer + len; } + +private: + void allocate_buffer(); + void initialize_buffer(const T&, std::true_type) {} + void initialize_buffer(const T& value, std::false_type) + { mystl::uninitialized_fill_n(buffer, len, value); } + +private: + temporary_buffer(const temporary_buffer&); + void operator=(const temporary_buffer&); +}; + +// 构造函数 +template +temporary_buffer:: +temporary_buffer(ForwardIterator first, ForwardIterator last) +{ + try + { + len = mystl::distance(first, last); + allocate_buffer(); + if (len > 0) + { + initialize_buffer(*first, std::is_trivially_default_constructible()); + } + } + catch (...) + { + free(buffer); + buffer = nullptr; + len = 0; + } +} + +// allocate_buffer 函数 +template +void temporary_buffer::allocate_buffer() +{ + original_len = len; + if (len > static_cast(INT_MAX / sizeof(T))) + len = INT_MAX / sizeof(T); + while (len > 0) + { + buffer = static_cast(malloc(len * sizeof(T))); + if (buffer) + break; + len /= 2; // 申请失败时减少申请空间大小 + } +} + +// -------------------------------------------------------------------------------------- +// 模板类: auto_ptr +// 一个具有严格对象所有权的小型智能指针 +template +class auto_ptr +{ +public: + typedef T elem_type; + +private: + T* m_ptr; // 实际指针 + +public: + // 构造、复制、析构函数 + explicit auto_ptr(T* p = nullptr) :m_ptr(p) {} + auto_ptr(auto_ptr& rhs) :m_ptr(rhs.release()) {} + template + auto_ptr(auto_ptr& rhs) : m_ptr(rhs.release()) {} + + auto_ptr& operator=(auto_ptr& rhs) + { + if (this != &rhs) + { + delete m_ptr; + m_ptr = rhs.release(); + } + return *this; + } + template + auto_ptr& operator=(auto_ptr& rhs) + { + if (this->get() != rhs.get()) + { + delete m_ptr; + m_ptr = rhs.release(); + } + return *this; + } + + ~auto_ptr() { delete m_ptr; } + +public: + // 重载 operator* 和 operator-> + T& operator*() const { return *m_ptr; } + T* operator->() const { return m_ptr; } + + // 获得指针 + T* get() const { return m_ptr; } + + // 释放指针 + T* release() + { + T* tmp = m_ptr; + m_ptr = nullptr; + return tmp; + } + + // 重置指针 + void reset(T* p = nullptr) + { + if (m_ptr != p) + { + delete m_ptr; + m_ptr = p; + } + } +}; + +} // namespace mystl +#endif // !MYTINYSTL_MEMORY_H_ + diff --git a/src/MyTinySTL-master/MyTinySTL-master/MyTinySTL/numeric.h b/src/MyTinySTL-master/MyTinySTL-master/MyTinySTL/numeric.h new file mode 100755 index 0000000..8d6cbb6 --- /dev/null +++ b/src/MyTinySTL-master/MyTinySTL-master/MyTinySTL/numeric.h @@ -0,0 +1,155 @@ +#ifndef MYTINYSTL_NUMERIC_H_ +#define MYTINYSTL_NUMERIC_H_ + +// 这个头文件包含了 mystl 的数值算法 + +#include "iterator.h" + +namespace mystl +{ + +/*****************************************************************************************/ +// accumulate +// 版本1:以初值 init 对每个元素进行累加 +// 版本2:以初值 init 对每个元素进行二元操作 +/*****************************************************************************************/ +// 版本1 +template +T accumulate(InputIter first, InputIter last, T init) +{ + for (; first != last; ++first) + { + init += *first; + } + return init; +} + +// 版本2 +template +T accumulate(InputIter first, InputIter last, T init, BinaryOp binary_op) +{ + for (; first != last; ++first) + { + init = binary_op(init, *first); + } + return init; +} + +/*****************************************************************************************/ +// adjacent_difference +// 版本1:计算相邻元素的差值,结果保存到以 result 为起始的区间上 +// 版本2:自定义相邻元素的二元操作 +/*****************************************************************************************/ +// 版本1 +template +OutputIter adjacent_difference(InputIter first, InputIter last, OutputIter result) +{ + if (first == last) return result; + *result = *first; // 记录第一个元素 + auto value = *first; + while (++first != last) + { + auto tmp = *first; + *++result = tmp - value; + value = tmp; + } + return ++result; +} + +// 版本2 +template +OutputIter adjacent_difference(InputIter first, InputIter last, OutputIter result, + BinaryOp binary_op) +{ + if (first == last) return result; + *result = *first; // 记录第一个元素 + auto value = *first; + while (++first != last) + { + auto tmp = *first; + *++result = binary_op(tmp, value); + value = tmp; + } + return ++result; +} + +/*****************************************************************************************/ +// inner_product +// 版本1:以 init 为初值,计算两个区间的内积 +// 版本2:自定义 operator+ 和 operator* +/*****************************************************************************************/ +// 版本1 +template +T inner_product(InputIter1 first1, InputIter1 last1, InputIter2 first2, T init) +{ + for (; first1 != last1; ++first1, ++first2) + { + init = init + (*first1 * *first2); + } + return init; +} + +// 版本2 +template +T inner_product(InputIter1 first1, InputIter1 last1, InputIter2 first2, T init, + BinaryOp1 binary_op1, BinaryOp2 binary_op2) +{ + for (; first1 != last1; ++first1, ++first2) + { + init = binary_op1(init, binary_op2(*first1, *first2)); + } + return init; +} + +/*****************************************************************************************/ +// iota +// 填充[first, last),以 value 为初值开始递增 +/*****************************************************************************************/ +template +void iota(ForwardIter first, ForwardIter last, T value) +{ + while (first != last) + { + *first++ = value; + ++value; + } +} + +/*****************************************************************************************/ +// partial_sum +// 版本1:计算局部累计求和,结果保存到以 result 为起始的区间上 +// 版本2:进行局部进行自定义二元操作 +/*****************************************************************************************/ +template +OutputIter partial_sum(InputIter first, InputIter last, OutputIter result) +{ + if (first == last) return result; + *result = *first; // 记录第一个元素 + auto value = *first; + while (++first != last) + { + value = value + *first; + *++result = value; + } + return ++result; +} + +// 版本2 +template +OutputIter partial_sum(InputIter first, InputIter last, OutputIter result, + BinaryOp binary_op) +{ + if (first == last) return result; + *result = *first; //记录第一个元素 + auto value = *first; + while (++first != last) + { + value = binary_op(value, *first); + *++result = value; + } + return ++result; +} + +} // namespace mystl +#endif // !MYTINYSTL_NUMERIC_H_ + diff --git a/src/MyTinySTL-master/MyTinySTL-master/MyTinySTL/queue.h b/src/MyTinySTL-master/MyTinySTL-master/MyTinySTL/queue.h new file mode 100755 index 0000000..6a4a939 --- /dev/null +++ b/src/MyTinySTL-master/MyTinySTL-master/MyTinySTL/queue.h @@ -0,0 +1,364 @@ +#ifndef MYTINYSTL_QUEUE_H_ +#define MYTINYSTL_QUEUE_H_ + +// 这个头文件包含了两个模板类 queue 和 priority_queue +// queue : 队列 +// priority_queue : 优先队列 + +#include "deque.h" +#include "vector.h" +#include "functional.h" +#include "heap_algo.h" + +namespace mystl +{ + +// 模板类 queue +// 参数一代表数据类型,参数二代表底层容器类型,缺省使用 mystl::deque 作为底层容器 +template > +class queue +{ +public: + typedef Container container_type; + // 使用底层容器的型别 + typedef typename Container::value_type value_type; + typedef typename Container::size_type size_type; + typedef typename Container::reference reference; + typedef typename Container::const_reference const_reference; + + static_assert(std::is_same::value, + "the value_type of Container should be same with T"); +private: + container_type c_; // 用底层容器表现 queue + +public: + // 构造、复制、移动函数 + + queue() = default; + + explicit queue(size_type n) + :c_(n) + { + } + queue(size_type n, const value_type& value) + :c_(n, value) + { + } + + template + queue(IIter first, IIter last) + :c_(first, last) + { + } + + queue(std::initializer_list ilist) + :c_(ilist.begin(), ilist.end()) + { + } + + queue(const Container& c) + :c_(c) + { + } + queue(Container&& c) noexcept(std::is_nothrow_move_constructible::value) + :c_(mystl::move(c)) + { + } + + queue(const queue& rhs) + :c_(rhs.c_) + { + } + queue(queue&& rhs) noexcept(std::is_nothrow_move_constructible::value) + :c_(mystl::move(rhs.c_)) + { + } + + queue& operator=(const queue& rhs) + { + c_ = rhs.c_; + return *this; + } + queue& operator=(queue&& rhs) noexcept(std::is_nothrow_move_assignable::value) + { + c_ = mystl::move(rhs.c_); + return *this; + } + + queue& operator=(std::initializer_list ilist) + { + c_ = ilist; + return *this; + } + + ~queue() = default; + + // 访问元素相关操作 + reference front() { return c_.front(); } + const_reference front() const { return c_.front(); } + reference back() { return c_.back(); } + const_reference back() const { return c_.back(); } + + // 容量相关操作 + bool empty() const noexcept { return c_.empty(); } + size_type size() const noexcept { return c_.size(); } + + // 修改容器相关操作 + template + void emplace(Args&& ...args) + { c_.emplace_back(mystl::forward(args)...); } + + void push(const value_type& value) + { c_.push_back(value); } + void push(value_type&& value) + { c_.emplace_back(mystl::move(value)); } + + void pop() + { c_.pop_front(); } + + void clear() + { + while (!empty()) + pop(); + } + + void swap(queue& rhs) noexcept(noexcept(mystl::swap(c_, rhs.c_))) + { mystl::swap(c_, rhs.c_); } + +public: + friend bool operator==(const queue& lhs, const queue& rhs) { return lhs.c_ == rhs.c_; } + friend bool operator< (const queue& lhs, const queue& rhs) { return lhs.c_ < rhs.c_; } +}; + +// 重载比较操作符 +template +bool operator==(const queue& lhs, const queue& rhs) +{ + return lhs == rhs; +} + +template +bool operator!=(const queue& lhs, const queue& rhs) +{ + return !(lhs == rhs); +} + +template +bool operator<(const queue& lhs, const queue& rhs) +{ + return lhs < rhs; +} + +template +bool operator>(const queue& lhs, const queue& rhs) +{ + return rhs < lhs; +} + +template +bool operator<=(const queue& lhs, const queue& rhs) +{ + return !(rhs < lhs); +} + +template +bool operator>=(const queue& lhs, const queue& rhs) +{ + return !(lhs < rhs); +} + +// 重载 mystl 的 swap +template +void swap(queue& lhs, queue& rhs) noexcept(noexcept(lhs.swap(rhs))) +{ + lhs.swap(rhs); +} + +/*****************************************************************************************/ + +// 模板类 priority_queue +// 参数一代表数据类型,参数二代表容器类型,缺省使用 mystl::vector 作为底层容器 +// 参数三代表比较权值的方式,缺省使用 mystl::less 作为比较方式 +template , + class Compare = mystl::less> +class priority_queue +{ +public: + typedef Container container_type; + typedef Compare value_compare; + // 使用底层容器的型别 + typedef typename Container::value_type value_type; + typedef typename Container::size_type size_type; + typedef typename Container::reference reference; + typedef typename Container::const_reference const_reference; + + static_assert(std::is_same::value, + "the value_type of Container should be same with T"); + +private: + container_type c_; // 用底层容器来表现 priority_queue + value_compare comp_; // 权值比较的标准 + +public: + // 构造、复制、移动函数 + priority_queue() = default; + + priority_queue(const Compare& c) + :c_(), comp_(c) + { + } + + explicit priority_queue(size_type n) + :c_(n) + { + mystl::make_heap(c_.begin(), c_.end(), comp_); + } + priority_queue(size_type n, const value_type& value) + :c_(n, value) + { + mystl::make_heap(c_.begin(), c_.end(), comp_); + } + + template + priority_queue(IIter first, IIter last) + :c_(first, last) + { + mystl::make_heap(c_.begin(), c_.end(), comp_); + } + + priority_queue(std::initializer_list ilist) + :c_(ilist) + { + mystl::make_heap(c_.begin(), c_.end(), comp_); + } + + priority_queue(const Container& s) + :c_(s) + { + mystl::make_heap(c_.begin(), c_.end(), comp_); + } + priority_queue(Container&& s) + :c_(mystl::move(s)) + { + mystl::make_heap(c_.begin(), c_.end(), comp_); + } + + priority_queue(const priority_queue& rhs) + :c_(rhs.c_), comp_(rhs.comp_) + { + mystl::make_heap(c_.begin(), c_.end(), comp_); + } + priority_queue(priority_queue&& rhs) + :c_(mystl::move(rhs.c_)), comp_(rhs.comp_) + { + mystl::make_heap(c_.begin(), c_.end(), comp_); + } + + priority_queue& operator=(const priority_queue& rhs) + { + c_ = rhs.c_; + comp_ = rhs.comp_; + mystl::make_heap(c_.begin(), c_.end(), comp_); + return *this; + } + priority_queue& operator=(priority_queue&& rhs) + { + c_ = mystl::move(rhs.c_); + comp_ = rhs.comp_; + mystl::make_heap(c_.begin(), c_.end(), comp_); + return *this; + } + priority_queue& operator=(std::initializer_list ilist) + { + c_ = ilist; + comp_ = value_compare(); + mystl::make_heap(c_.begin(), c_.end(), comp_); + return *this; + } + + ~priority_queue() = default; + +public: + + // 访问元素相关操作 + const_reference top() const { return c_.front(); } + + // 容量相关操作 + bool empty() const noexcept { return c_.empty(); } + size_type size() const noexcept { return c_.size(); } + + // 修改容器相关操作 + template + void emplace(Args&& ...args) + { + c_.emplace_back(mystl::forward(args)...); + mystl::push_heap(c_.begin(), c_.end(), comp_); + } + + void push(const value_type& value) + { + c_.push_back(value); + mystl::push_heap(c_.begin(), c_.end(), comp_); + } + void push(value_type&& value) + { + c_.push_back(mystl::move(value)); + mystl::push_heap(c_.begin(), c_.end(), comp_); + } + + void pop() + { + mystl::pop_heap(c_.begin(), c_.end(), comp_); + c_.pop_back(); + } + + void clear() + { + while (!empty()) + pop(); + } + + void swap(priority_queue& rhs) noexcept(noexcept(mystl::swap(c_, rhs.c_)) && + noexcept(mystl::swap(comp_, rhs.comp_))) + { + mystl::swap(c_, rhs.c_); + mystl::swap(comp_, rhs.comp_); + } + +public: + friend bool operator==(const priority_queue& lhs, const priority_queue& rhs) + { + return lhs.c_ == rhs.c_; + } + friend bool operator!=(const priority_queue& lhs, const priority_queue& rhs) + { + return lhs.c_ != rhs.c_; + } +}; + +// 重载比较操作符 +template +bool operator==(priority_queue& lhs, + priority_queue& rhs) +{ + return lhs == rhs; +} + +template +bool operator!=(priority_queue& lhs, + priority_queue& rhs) +{ + return lhs != rhs; +} + +// 重载 mystl 的 swap +template +void swap(priority_queue& lhs, + priority_queue& rhs) noexcept(noexcept(lhs.swap(rhs))) +{ + lhs.swap(rhs); +} + +} // namespace mystl +#endif // !MYTINYSTL_QUEUE_H_ + diff --git a/src/MyTinySTL-master/MyTinySTL-master/MyTinySTL/rb_tree.h b/src/MyTinySTL-master/MyTinySTL-master/MyTinySTL/rb_tree.h new file mode 100755 index 0000000..908e778 --- /dev/null +++ b/src/MyTinySTL-master/MyTinySTL-master/MyTinySTL/rb_tree.h @@ -0,0 +1,1738 @@ +#ifndef MYTINYSTL_RB_TREE_H_ +#define MYTINYSTL_RB_TREE_H_ + +// 这个头文件包含一个模板类 rb_tree +// rb_tree : 红黑树 + +#include + +#include + +#include "functional.h" +#include "iterator.h" +#include "memory.h" +#include "type_traits.h" +#include "exceptdef.h" + +namespace mystl +{ + +// rb tree 节点颜色的类型 + +typedef bool rb_tree_color_type; + +static constexpr rb_tree_color_type rb_tree_red = false; +static constexpr rb_tree_color_type rb_tree_black = true; + +// forward declaration + +template struct rb_tree_node_base; +template struct rb_tree_node; + +template struct rb_tree_iterator; +template struct rb_tree_const_iterator; + +// rb tree value traits + +template +struct rb_tree_value_traits_imp +{ + typedef T key_type; + typedef T mapped_type; + typedef T value_type; + + template + static const key_type& get_key(const Ty& value) + { + return value; + } + + template + static const value_type& get_value(const Ty& value) + { + return value; + } +}; + +template +struct rb_tree_value_traits_imp +{ + typedef typename std::remove_cv::type key_type; + typedef typename T::second_type mapped_type; + typedef T value_type; + + template + static const key_type& get_key(const Ty& value) + { + return value.first; + } + + template + static const value_type& get_value(const Ty& value) + { + return value; + } +}; + +template +struct rb_tree_value_traits +{ + static constexpr bool is_map = mystl::is_pair::value; + + typedef rb_tree_value_traits_imp value_traits_type; + + typedef typename value_traits_type::key_type key_type; + typedef typename value_traits_type::mapped_type mapped_type; + typedef typename value_traits_type::value_type value_type; + + template + static const key_type& get_key(const Ty& value) + { + return value_traits_type::get_key(value); + } + + template + static const value_type& get_value(const Ty& value) + { + return value_traits_type::get_value(value); + } +}; + +// rb tree node traits + +template +struct rb_tree_node_traits +{ + typedef rb_tree_color_type color_type; + + typedef rb_tree_value_traits value_traits; + typedef typename value_traits::key_type key_type; + typedef typename value_traits::mapped_type mapped_type; + typedef typename value_traits::value_type value_type; + + typedef rb_tree_node_base* base_ptr; + typedef rb_tree_node* node_ptr; +}; + +// rb tree 的节点设计 + +template +struct rb_tree_node_base +{ + typedef rb_tree_color_type color_type; + typedef rb_tree_node_base* base_ptr; + typedef rb_tree_node* node_ptr; + + base_ptr parent; // 父节点 + base_ptr left; // 左子节点 + base_ptr right; // 右子节点 + color_type color; // 节点颜色 + + base_ptr get_base_ptr() + { + return &*this; + } + + node_ptr get_node_ptr() + { + return reinterpret_cast(&*this); + } + + node_ptr& get_node_ref() + { + return reinterpret_cast(*this); + } +}; + +template +struct rb_tree_node :public rb_tree_node_base +{ + typedef rb_tree_node_base* base_ptr; + typedef rb_tree_node* node_ptr; + + T value; // 节点值 + + base_ptr get_base_ptr() + { + return static_cast(&*this); + } + + node_ptr get_node_ptr() + { + return &*this; + } +}; + +// rb tree traits + +template +struct rb_tree_traits +{ + typedef rb_tree_value_traits value_traits; + + typedef typename value_traits::key_type key_type; + typedef typename value_traits::mapped_type mapped_type; + typedef typename value_traits::value_type value_type; + + typedef value_type* pointer; + typedef value_type& reference; + typedef const value_type* const_pointer; + typedef const value_type& const_reference; + + typedef rb_tree_node_base base_type; + typedef rb_tree_node node_type; + + typedef base_type* base_ptr; + typedef node_type* node_ptr; +}; + +// rb tree 的迭代器设计 + +template +struct rb_tree_iterator_base :public mystl::iterator +{ + typedef typename rb_tree_traits::base_ptr base_ptr; + + base_ptr node; // 指向节点本身 + + rb_tree_iterator_base() :node(nullptr) {} + + // 使迭代器前进 + void inc() + { + if (node->right != nullptr) + { + node = rb_tree_min(node->right); + } + else + { // 如果没有右子节点 + auto y = node->parent; + while (y->right == node) + { + node = y; + y = y->parent; + } + if (node->right != y) // 应对“寻找根节点的下一节点,而根节点没有右子节点”的特殊情况 + node = y; + } + } + + // 使迭代器后退 + void dec() + { + if (node->parent->parent == node && rb_tree_is_red(node)) + { // 如果 node 为 header + node = node->right; // 指向整棵树的 max 节点 + } + else if (node->left != nullptr) + { + node = rb_tree_max(node->left); + } + else + { // 非 header 节点,也无左子节点 + auto y = node->parent; + while (node == y->left) + { + node = y; + y = y->parent; + } + node = y; + } + } + + bool operator==(const rb_tree_iterator_base& rhs) { return node == rhs.node; } + bool operator!=(const rb_tree_iterator_base& rhs) { return node != rhs.node; } +}; + +template +struct rb_tree_iterator :public rb_tree_iterator_base +{ + typedef rb_tree_traits tree_traits; + + typedef typename tree_traits::value_type value_type; + typedef typename tree_traits::pointer pointer; + typedef typename tree_traits::reference reference; + typedef typename tree_traits::base_ptr base_ptr; + typedef typename tree_traits::node_ptr node_ptr; + + typedef rb_tree_iterator iterator; + typedef rb_tree_const_iterator const_iterator; + typedef iterator self; + + using rb_tree_iterator_base::node; + + // 构造函数 + rb_tree_iterator() {} + rb_tree_iterator(base_ptr x) { node = x; } + rb_tree_iterator(node_ptr x) { node = x; } + rb_tree_iterator(const iterator& rhs) { node = rhs.node; } + rb_tree_iterator(const const_iterator& rhs) { node = rhs.node; } + + // 重载操作符 + reference operator*() const { return node->get_node_ptr()->value; } + pointer operator->() const { return &(operator*()); } + + self& operator++() + { + this->inc(); + return *this; + } + self operator++(int) + { + self tmp(*this); + this->inc(); + return tmp; + } + self& operator--() + { + this->dec(); + return *this; + } + self operator--(int) + { + self tmp(*this); + this->dec(); + return tmp; + } +}; + +template +struct rb_tree_const_iterator :public rb_tree_iterator_base +{ + typedef rb_tree_traits tree_traits; + + typedef typename tree_traits::value_type value_type; + typedef typename tree_traits::const_pointer pointer; + typedef typename tree_traits::const_reference reference; + typedef typename tree_traits::base_ptr base_ptr; + typedef typename tree_traits::node_ptr node_ptr; + + typedef rb_tree_iterator iterator; + typedef rb_tree_const_iterator const_iterator; + typedef const_iterator self; + + using rb_tree_iterator_base::node; + + // 构造函数 + rb_tree_const_iterator() {} + rb_tree_const_iterator(base_ptr x) { node = x; } + rb_tree_const_iterator(node_ptr x) { node = x; } + rb_tree_const_iterator(const iterator& rhs) { node = rhs.node; } + rb_tree_const_iterator(const const_iterator& rhs) { node = rhs.node; } + + // 重载操作符 + reference operator*() const { return node->get_node_ptr()->value; } + pointer operator->() const { return &(operator*()); } + + self& operator++() + { + this->inc(); + return *this; + } + self operator++(int) + { + self tmp(*this); + this->inc(); + return tmp; + } + self& operator--() + { + this->dec(); + return *this; + } + self operator--(int) + { + self tmp(*this); + this->dec(); + return tmp; + } +}; + +// tree algorithm + +template +NodePtr rb_tree_min(NodePtr x) noexcept +{ + while (x->left != nullptr) + x = x->left; + return x; +} + +template +NodePtr rb_tree_max(NodePtr x) noexcept +{ + while (x->right != nullptr) + x = x->right; + return x; +} + +template +bool rb_tree_is_lchild(NodePtr node) noexcept +{ + return node == node->parent->left; +} + +template +bool rb_tree_is_red(NodePtr node) noexcept +{ + return node->color == rb_tree_red; +} + +template +void rb_tree_set_black(NodePtr& node) noexcept +{ + node->color = rb_tree_black; +} + +template +void rb_tree_set_red(NodePtr& node) noexcept +{ + node->color = rb_tree_red; +} + +template +NodePtr rb_tree_next(NodePtr node) noexcept +{ + if (node->right != nullptr) + return rb_tree_min(node->right); + while (!rb_tree_is_lchild(node)) + node = node->parent; + return node->parent; +} + +/*---------------------------------------*\ +| p p | +| / \ / \ | +| x d rotate left y d | +| / \ ===========> / \ | +| a y x c | +| / \ / \ | +| b c a b | +\*---------------------------------------*/ +// 左旋,参数一为左旋点,参数二为根节点 +template +void rb_tree_rotate_left(NodePtr x, NodePtr& root) noexcept +{ + auto y = x->right; // y 为 x 的右子节点 + x->right = y->left; + if (y->left != nullptr) + y->left->parent = x; + y->parent = x->parent; + + if (x == root) + { // 如果 x 为根节点,让 y 顶替 x 成为根节点 + root = y; + } + else if (rb_tree_is_lchild(x)) + { // 如果 x 是左子节点 + x->parent->left = y; + } + else + { // 如果 x 是右子节点 + x->parent->right = y; + } + // 调整 x 与 y 的关系 + y->left = x; + x->parent = y; +} + +/*----------------------------------------*\ +| p p | +| / \ / \ | +| d x rotate right d y | +| / \ ===========> / \ | +| y a b x | +| / \ / \ | +| b c c a | +\*----------------------------------------*/ +// 右旋,参数一为右旋点,参数二为根节点 +template +void rb_tree_rotate_right(NodePtr x, NodePtr& root) noexcept +{ + auto y = x->left; + x->left = y->right; + if (y->right) + y->right->parent = x; + y->parent = x->parent; + + if (x == root) + { // 如果 x 为根节点,让 y 顶替 x 成为根节点 + root = y; + } + else if (rb_tree_is_lchild(x)) + { // 如果 x 是右子节点 + x->parent->left = y; + } + else + { // 如果 x 是左子节点 + x->parent->right = y; + } + // 调整 x 与 y 的关系 + y->right = x; + x->parent = y; +} + +// 插入节点后使 rb tree 重新平衡,参数一为新增节点,参数二为根节点 +// +// case 1: 新增节点位于根节点,令新增节点为黑 +// case 2: 新增节点的父节点为黑,没有破坏平衡,直接返回 +// case 3: 父节点和叔叔节点都为红,令父节点和叔叔节点为黑,祖父节点为红, +// 然后令祖父节点为当前节点,继续处理 +// case 4: 父节点为红,叔叔节点为 NIL 或黑色,父节点为左(右)孩子,当前节点为右(左)孩子, +// 让父节点成为当前节点,再以当前节点为支点左(右)旋 +// case 5: 父节点为红,叔叔节点为 NIL 或黑色,父节点为左(右)孩子,当前节点为左(右)孩子, +// 让父节点变为黑色,祖父节点变为红色,以祖父节点为支点右(左)旋 +// +// 参考博客: http://blog.csdn.net/v_JULY_v/article/details/6105630 +// http://blog.csdn.net/v_JULY_v/article/details/6109153 +template +void rb_tree_insert_rebalance(NodePtr x, NodePtr& root) noexcept +{ + rb_tree_set_red(x); // 新增节点为红色 + while (x != root && rb_tree_is_red(x->parent)) + { + if (rb_tree_is_lchild(x->parent)) + { // 如果父节点是左子节点 + auto uncle = x->parent->parent->right; + if (uncle != nullptr && rb_tree_is_red(uncle)) + { // case 3: 父节点和叔叔节点都为红 + rb_tree_set_black(x->parent); + rb_tree_set_black(uncle); + x = x->parent->parent; + rb_tree_set_red(x); + } + else + { // 无叔叔节点或叔叔节点为黑 + if (!rb_tree_is_lchild(x)) + { // case 4: 当前节点 x 为右子节点 + x = x->parent; + rb_tree_rotate_left(x, root); + } + // 都转换成 case 5: 当前节点为左子节点 + rb_tree_set_black(x->parent); + rb_tree_set_red(x->parent->parent); + rb_tree_rotate_right(x->parent->parent, root); + break; + } + } + else // 如果父节点是右子节点,对称处理 + { + auto uncle = x->parent->parent->left; + if (uncle != nullptr && rb_tree_is_red(uncle)) + { // case 3: 父节点和叔叔节点都为红 + rb_tree_set_black(x->parent); + rb_tree_set_black(uncle); + x = x->parent->parent; + rb_tree_set_red(x); + // 此时祖父节点为红,可能会破坏红黑树的性质,令当前节点为祖父节点,继续处理 + } + else + { // 无叔叔节点或叔叔节点为黑 + if (rb_tree_is_lchild(x)) + { // case 4: 当前节点 x 为左子节点 + x = x->parent; + rb_tree_rotate_right(x, root); + } + // 都转换成 case 5: 当前节点为左子节点 + rb_tree_set_black(x->parent); + rb_tree_set_red(x->parent->parent); + rb_tree_rotate_left(x->parent->parent, root); + break; + } + } + } + rb_tree_set_black(root); // 根节点永远为黑 +} + +// 删除节点后使 rb tree 重新平衡,参数一为要删除的节点,参数二为根节点,参数三为最小节点,参数四为最大节点 +// +// 参考博客: http://blog.csdn.net/v_JULY_v/article/details/6105630 +// http://blog.csdn.net/v_JULY_v/article/details/6109153 +template +NodePtr rb_tree_erase_rebalance(NodePtr z, NodePtr& root, NodePtr& leftmost, NodePtr& rightmost) +{ + // y 是可能的替换节点,指向最终要删除的节点 + auto y = (z->left == nullptr || z->right == nullptr) ? z : rb_tree_next(z); + // x 是 y 的一个独子节点或 NIL 节点 + auto x = y->left != nullptr ? y->left : y->right; + // xp 为 x 的父节点 + NodePtr xp = nullptr; + + // y != z 说明 z 有两个非空子节点,此时 y 指向 z 右子树的最左节点,x 指向 y 的右子节点。 + // 用 y 顶替 z 的位置,用 x 顶替 y 的位置,最后用 y 指向 z + if (y != z) + { + z->left->parent = y; + y->left = z->left; + + // 如果 y 不是 z 的右子节点,那么 z 的右子节点一定有左孩子 + if (y != z->right) + { // x 替换 y 的位置 + xp = y->parent; + if (x != nullptr) + x->parent = y->parent; + + y->parent->left = x; + y->right = z->right; + z->right->parent = y; + } + else + { + xp = y; + } + + // 连接 y 与 z 的父节点 + if (root == z) + root = y; + else if (rb_tree_is_lchild(z)) + z->parent->left = y; + else + z->parent->right = y; + y->parent = z->parent; + mystl::swap(y->color, z->color); + y = z; + } + // y == z 说明 z 至多只有一个孩子 + else + { + xp = y->parent; + if (x) + x->parent = y->parent; + + // 连接 x 与 z 的父节点 + if (root == z) + root = x; + else if (rb_tree_is_lchild(z)) + z->parent->left = x; + else + z->parent->right = x; + + // 此时 z 有可能是最左节点或最右节点,更新数据 + if (leftmost == z) + leftmost = x == nullptr ? xp : rb_tree_min(x); + if (rightmost == z) + rightmost = x == nullptr ? xp : rb_tree_max(x); + } + + // 此时,y 指向要删除的节点,x 为替代节点,从 x 节点开始调整。 + // 如果删除的节点为红色,树的性质没有被破坏,否则按照以下情况调整(x 为左子节点为例): + // case 1: 兄弟节点为红色,令父节点为红,兄弟节点为黑,进行左(右)旋,继续处理 + // case 2: 兄弟节点为黑色,且两个子节点都为黑色或 NIL,令兄弟节点为红,父节点成为当前节点,继续处理 + // case 3: 兄弟节点为黑色,左子节点为红色或 NIL,右子节点为黑色或 NIL, + // 令兄弟节点为红,兄弟节点的左子节点为黑,以兄弟节点为支点右(左)旋,继续处理 + // case 4: 兄弟节点为黑色,右子节点为红色,令兄弟节点为父节点的颜色,父节点为黑色,兄弟节点的右子节点 + // 为黑色,以父节点为支点左(右)旋,树的性质调整完成,算法结束 + if (!rb_tree_is_red(y)) + { // x 为黑色时,调整,否则直接将 x 变为黑色即可 + while (x != root && (x == nullptr || !rb_tree_is_red(x))) + { + if (x == xp->left) + { // 如果 x 为左子节点 + auto brother = xp->right; + if (rb_tree_is_red(brother)) + { // case 1 + rb_tree_set_black(brother); + rb_tree_set_red(xp); + rb_tree_rotate_left(xp, root); + brother = xp->right; + } + // case 1 转为为了 case 2、3、4 中的一种 + if ((brother->left == nullptr || !rb_tree_is_red(brother->left)) && + (brother->right == nullptr || !rb_tree_is_red(brother->right))) + { // case 2 + rb_tree_set_red(brother); + x = xp; + xp = xp->parent; + } + else + { + if (brother->right == nullptr || !rb_tree_is_red(brother->right)) + { // case 3 + if (brother->left != nullptr) + rb_tree_set_black(brother->left); + rb_tree_set_red(brother); + rb_tree_rotate_right(brother, root); + brother = xp->right; + } + // 转为 case 4 + brother->color = xp->color; + rb_tree_set_black(xp); + if (brother->right != nullptr) + rb_tree_set_black(brother->right); + rb_tree_rotate_left(xp, root); + break; + } + } + else // x 为右子节点,对称处理 + { + auto brother = xp->left; + if (rb_tree_is_red(brother)) + { // case 1 + rb_tree_set_black(brother); + rb_tree_set_red(xp); + rb_tree_rotate_right(xp, root); + brother = xp->left; + } + if ((brother->left == nullptr || !rb_tree_is_red(brother->left)) && + (brother->right == nullptr || !rb_tree_is_red(brother->right))) + { // case 2 + rb_tree_set_red(brother); + x = xp; + xp = xp->parent; + } + else + { + if (brother->left == nullptr || !rb_tree_is_red(brother->left)) + { // case 3 + if (brother->right != nullptr) + rb_tree_set_black(brother->right); + rb_tree_set_red(brother); + rb_tree_rotate_left(brother, root); + brother = xp->left; + } + // 转为 case 4 + brother->color = xp->color; + rb_tree_set_black(xp); + if (brother->left != nullptr) + rb_tree_set_black(brother->left); + rb_tree_rotate_right(xp, root); + break; + } + } + } + if (x != nullptr) + rb_tree_set_black(x); + } + return y; +} + +// 模板类 rb_tree +// 参数一代表数据类型,参数二代表键值比较类型 +template +class rb_tree +{ +public: + // rb_tree 的嵌套型别定义 + + typedef rb_tree_traits tree_traits; + typedef rb_tree_value_traits value_traits; + + typedef typename tree_traits::base_type base_type; + typedef typename tree_traits::base_ptr base_ptr; + typedef typename tree_traits::node_type node_type; + typedef typename tree_traits::node_ptr node_ptr; + typedef typename tree_traits::key_type key_type; + typedef typename tree_traits::mapped_type mapped_type; + typedef typename tree_traits::value_type value_type; + typedef Compare key_compare; + + typedef mystl::allocator allocator_type; + typedef mystl::allocator data_allocator; + typedef mystl::allocator base_allocator; + typedef mystl::allocator node_allocator; + + typedef typename allocator_type::pointer pointer; + typedef typename allocator_type::const_pointer const_pointer; + typedef typename allocator_type::reference reference; + typedef typename allocator_type::const_reference const_reference; + typedef typename allocator_type::size_type size_type; + typedef typename allocator_type::difference_type difference_type; + + typedef rb_tree_iterator iterator; + typedef rb_tree_const_iterator const_iterator; + typedef mystl::reverse_iterator reverse_iterator; + typedef mystl::reverse_iterator const_reverse_iterator; + + allocator_type get_allocator() const { return node_allocator(); } + key_compare key_comp() const { return key_comp_; } + +private: + // 用以下三个数据表现 rb tree + base_ptr header_; // 特殊节点,与根节点互为对方的父节点 + size_type node_count_; // 节点数 + key_compare key_comp_; // 节点键值比较的准则 + +private: + // 以下三个函数用于取得根节点,最小节点和最大节点 + base_ptr& root() const { return header_->parent; } + base_ptr& leftmost() const { return header_->left; } + base_ptr& rightmost() const { return header_->right; } + +public: + // 构造、复制、析构函数 + rb_tree() { rb_tree_init(); } + + rb_tree(const rb_tree& rhs); + rb_tree(rb_tree&& rhs) noexcept; + + rb_tree& operator=(const rb_tree& rhs); + rb_tree& operator=(rb_tree&& rhs); + + ~rb_tree() { clear(); } + +public: + // 迭代器相关操作 + + iterator begin() noexcept + { return leftmost(); } + const_iterator begin() const noexcept + { return leftmost(); } + iterator end() noexcept + { return header_; } + const_iterator end() const noexcept + { return header_; } + + reverse_iterator rbegin() noexcept + { return reverse_iterator(end()); } + const_reverse_iterator rbegin() const noexcept + { return const_reverse_iterator(end()); } + reverse_iterator rend() noexcept + { return reverse_iterator(begin()); } + const_reverse_iterator rend() const noexcept + { return const_reverse_iterator(begin()); } + + const_iterator cbegin() const noexcept + { return begin(); } + const_iterator cend() const noexcept + { return end(); } + const_reverse_iterator crbegin() const noexcept + { return rbegin(); } + const_reverse_iterator crend() const noexcept + { return rend(); } + + // 容量相关操作 + + bool empty() const noexcept { return node_count_ == 0; } + size_type size() const noexcept { return node_count_; } + size_type max_size() const noexcept { return static_cast(-1); } + + // 插入删除相关操作 + + // emplace + + template + iterator emplace_multi(Args&& ...args); + + template + mystl::pair emplace_unique(Args&& ...args); + + template + iterator emplace_multi_use_hint(iterator hint, Args&& ...args); + + template + iterator emplace_unique_use_hint(iterator hint, Args&& ...args); + + // insert + + iterator insert_multi(const value_type& value); + iterator insert_multi(value_type&& value) + { + return emplace_multi(mystl::move(value)); + } + + iterator insert_multi(iterator hint, const value_type& value) + { + return emplace_multi_use_hint(hint, value); + } + iterator insert_multi(iterator hint, value_type&& value) + { + return emplace_multi_use_hint(hint, mystl::move(value)); + } + + template + void insert_multi(InputIterator first, InputIterator last) + { + size_type n = mystl::distance(first, last); + THROW_LENGTH_ERROR_IF(node_count_ > max_size() - n, "rb_tree's size too big"); + for (; n > 0; --n, ++first) + insert_multi(end(), *first); + } + + mystl::pair insert_unique(const value_type& value); + mystl::pair insert_unique(value_type&& value) + { + return emplace_unique(mystl::move(value)); + } + + iterator insert_unique(iterator hint, const value_type& value) + { + return emplace_unique_use_hint(hint, value); + } + iterator insert_unique(iterator hint, value_type&& value) + { + return emplace_unique_use_hint(hint, mystl::move(value)); + } + + template + void insert_unique(InputIterator first, InputIterator last) + { + size_type n = mystl::distance(first, last); + THROW_LENGTH_ERROR_IF(node_count_ > max_size() - n, "rb_tree's size too big"); + for (; n > 0; --n, ++first) + insert_unique(end(), *first); + } + + // erase + + iterator erase(iterator hint); + + size_type erase_multi(const key_type& key); + size_type erase_unique(const key_type& key); + + void erase(iterator first, iterator last); + + void clear(); + + // rb_tree 相关操作 + + iterator find(const key_type& key); + const_iterator find(const key_type& key) const; + + size_type count_multi(const key_type& key) const + { + auto p = equal_range_multi(key); + return static_cast(mystl::distance(p.first, p.second)); + } + size_type count_unique(const key_type& key) const + { + return find(key) != end() ? 1 : 0; + } + + iterator lower_bound(const key_type& key); + const_iterator lower_bound(const key_type& key) const; + + iterator upper_bound(const key_type& key); + const_iterator upper_bound(const key_type& key) const; + + mystl::pair + equal_range_multi(const key_type& key) + { + return mystl::pair(lower_bound(key), upper_bound(key)); + } + mystl::pair + equal_range_multi(const key_type& key) const + { + return mystl::pair(lower_bound(key), upper_bound(key)); + } + + mystl::pair + equal_range_unique(const key_type& key) + { + iterator it = find(key); + auto next = it; + return it == end() ? mystl::make_pair(it, it) : mystl::make_pair(it, ++next); + } + mystl::pair + equal_range_unique(const key_type& key) const + { + const_iterator it = find(key); + auto next = it; + return it == end() ? mystl::make_pair(it, it) : mystl::make_pair(it, ++next); + } + + void swap(rb_tree& rhs) noexcept; + +private: + + // node related + template + node_ptr create_node(Args&&... args); + node_ptr clone_node(base_ptr x); + void destroy_node(node_ptr p); + + // init / reset + void rb_tree_init(); + void reset(); + + // get insert pos + mystl::pair + get_insert_multi_pos(const key_type& key); + mystl::pair, bool> + get_insert_unique_pos(const key_type& key); + + // insert value / insert node + iterator insert_value_at(base_ptr x, const value_type& value, bool add_to_left); + iterator insert_node_at(base_ptr x, node_ptr node, bool add_to_left); + + // insert use hint + iterator insert_multi_use_hint(iterator hint, key_type key, node_ptr node); + iterator insert_unique_use_hint(iterator hint, key_type key, node_ptr node); + + // copy tree / erase tree + base_ptr copy_from(base_ptr x, base_ptr p); + void erase_since(base_ptr x); +}; + +/*****************************************************************************************/ + +// 复制构造函数 +template +rb_tree:: +rb_tree(const rb_tree& rhs) +{ + rb_tree_init(); + if (rhs.node_count_ != 0) + { + root() = copy_from(rhs.root(), header_); + leftmost() = rb_tree_min(root()); + rightmost() = rb_tree_max(root()); + } + node_count_ = rhs.node_count_; + key_comp_ = rhs.key_comp_; +} + +// 移动构造函数 +template +rb_tree:: +rb_tree(rb_tree&& rhs) noexcept + :header_(mystl::move(rhs.header_)), + node_count_(rhs.node_count_), + key_comp_(rhs.key_comp_) +{ + rhs.reset(); +} + +// 复制赋值操作符 +template +rb_tree& +rb_tree:: +operator=(const rb_tree& rhs) +{ + if (this != &rhs) + { + clear(); + + if (rhs.node_count_ != 0) + { + root() = copy_from(rhs.root(), header_); + leftmost() = rb_tree_min(root()); + rightmost() = rb_tree_max(root()); + } + + node_count_ = rhs.node_count_; + key_comp_ = rhs.key_comp_; + } + return *this; +} + +// 移动赋值操作符 +template +rb_tree& +rb_tree:: +operator=(rb_tree&& rhs) +{ + clear(); + header_ = mystl::move(rhs.header_); + node_count_ = rhs.node_count_; + key_comp_ = rhs.key_comp_; + rhs.reset(); + return *this; +} + +// 就地插入元素,键值允许重复 +template +template +typename rb_tree::iterator +rb_tree:: +emplace_multi(Args&& ...args) +{ + THROW_LENGTH_ERROR_IF(node_count_ > max_size() - 1, "rb_tree's size too big"); + node_ptr np = create_node(mystl::forward(args)...); + auto res = get_insert_multi_pos(value_traits::get_key(np->value)); + return insert_node_at(res.first, np, res.second); +} + +// 就地插入元素,键值不允许重复 +template +template +mystl::pair::iterator, bool> +rb_tree:: +emplace_unique(Args&& ...args) +{ + THROW_LENGTH_ERROR_IF(node_count_ > max_size() - 1, "rb_tree's size too big"); + node_ptr np = create_node(mystl::forward(args)...); + auto res = get_insert_unique_pos(value_traits::get_key(np->value)); + if (res.second) + { // 插入成功 + return mystl::make_pair(insert_node_at(res.first.first, np, res.first.second), true); + } + destroy_node(np); + return mystl::make_pair(iterator(res.first.first), false); +} + +// 就地插入元素,键值允许重复,当 hint 位置与插入位置接近时,插入操作的时间复杂度可以降低 +template +template +typename rb_tree::iterator +rb_tree:: +emplace_multi_use_hint(iterator hint, Args&& ...args) +{ + THROW_LENGTH_ERROR_IF(node_count_ > max_size() - 1, "rb_tree's size too big"); + node_ptr np = create_node(mystl::forward(args)...); + if (node_count_ == 0) + { + return insert_node_at(header_, np, true); + } + key_type key = value_traits::get_key(np->value); + if (hint == begin()) + { // 位于 begin 处 + if (key_comp_(key, value_traits::get_key(*hint))) + { + return insert_node_at(hint.node, np, true); + } + else + { + auto pos = get_insert_multi_pos(key); + return insert_node_at(pos.first, np, pos.second); + } + } + else if (hint == end()) + { // 位于 end 处 + if (!key_comp_(key, value_traits::get_key(rightmost()->get_node_ptr()->value))) + { + return insert_node_at(rightmost(), np, false); + } + else + { + auto pos = get_insert_multi_pos(key); + return insert_node_at(pos.first, np, pos.second); + } + } + return insert_multi_use_hint(hint, key, np); +} + +// 就地插入元素,键值不允许重复,当 hint 位置与插入位置接近时,插入操作的时间复杂度可以降低 +template +template +typename rb_tree::iterator +rb_tree:: +emplace_unique_use_hint(iterator hint, Args&& ...args) +{ + THROW_LENGTH_ERROR_IF(node_count_ > max_size() - 1, "rb_tree's size too big"); + node_ptr np = create_node(mystl::forward(args)...); + if (node_count_ == 0) + { + return insert_node_at(header_, np, true); + } + key_type key = value_traits::get_key(np->value); + if (hint == begin()) + { // 位于 begin 处 + if (key_comp_(key, value_traits::get_key(*hint))) + { + return insert_node_at(hint.node, np, true); + } + else + { + auto pos = get_insert_unique_pos(key); + if (!pos.second) + { + destroy_node(np); + return pos.first.first; + } + return insert_node_at(pos.first.first, np, pos.first.second); + } + } + else if (hint == end()) + { // 位于 end 处 + if (key_comp_(value_traits::get_key(rightmost()->get_node_ptr()->value), key)) + { + return insert_node_at(rightmost(), np, false); + } + else + { + auto pos = get_insert_unique_pos(key); + if (!pos.second) + { + destroy_node(np); + return pos.first.first; + } + return insert_node_at(pos.first.first, np, pos.first.second); + } + } + return insert_unique_use_hint(hint, key, np); +} + +// 插入元素,节点键值允许重复 +template +typename rb_tree::iterator +rb_tree:: +insert_multi(const value_type& value) +{ + THROW_LENGTH_ERROR_IF(node_count_ > max_size() - 1, "rb_tree's size too big"); + auto res = get_insert_multi_pos(value_traits::get_key(value)); + return insert_value_at(res.first, value, res.second); +} + +// 插入新值,节点键值不允许重复,返回一个 pair,若插入成功,pair 的第二参数为 true,否则为 false +template +mystl::pair::iterator, bool> +rb_tree:: +insert_unique(const value_type& value) +{ + THROW_LENGTH_ERROR_IF(node_count_ > max_size() - 1, "rb_tree's size too big"); + auto res = get_insert_unique_pos(value_traits::get_key(value)); + if (res.second) + { // 插入成功 + return mystl::make_pair(insert_value_at(res.first.first, value, res.first.second), true); + } + return mystl::make_pair(res.first.first, false); +} + +// 删除 hint 位置的节点 +template +typename rb_tree::iterator +rb_tree:: +erase(iterator hint) +{ + auto node = hint.node->get_node_ptr(); + iterator next(node); + ++next; + + rb_tree_erase_rebalance(hint.node, root(), leftmost(), rightmost()); + destroy_node(node); + --node_count_; + return next; +} + +// 删除键值等于 key 的元素,返回删除的个数 +template +typename rb_tree::size_type +rb_tree:: +erase_multi(const key_type& key) +{ + auto p = equal_range_multi(key); + size_type n = mystl::distance(p.first, p.second); + erase(p.first, p.second); + return n; +} + +// 删除键值等于 key 的元素,返回删除的个数 +template +typename rb_tree::size_type +rb_tree:: +erase_unique(const key_type& key) +{ + auto it = find(key); + if (it != end()) + { + erase(it); + return 1; + } + return 0; +} + +// 删除[first, last)区间内的元素 +template +void rb_tree:: +erase(iterator first, iterator last) +{ + if (first == begin() && last == end()) + { + clear(); + } + else + { + while (first != last) + erase(first++); + } +} + +// 清空 rb tree +template +void rb_tree:: +clear() +{ + if (node_count_ != 0) + { + erase_since(root()); + leftmost() = header_; + root() = nullptr; + rightmost() = header_; + node_count_ = 0; + } +} + +// 查找键值为 k 的节点,返回指向它的迭代器 +template +typename rb_tree::iterator +rb_tree:: +find(const key_type& key) +{ + auto y = header_; // 最后一个不小于 key 的节点 + auto x = root(); + while (x != nullptr) + { + if (!key_comp_(value_traits::get_key(x->get_node_ptr()->value), key)) + { // key 小于等于 x 键值,向左走 + y = x, x = x->left; + } + else + { // key 大于 x 键值,向右走 + x = x->right; + } + } + iterator j = iterator(y); + return (j == end() || key_comp_(key, value_traits::get_key(*j))) ? end() : j; +} + +template +typename rb_tree::const_iterator +rb_tree:: +find(const key_type& key) const +{ + auto y = header_; // 最后一个不小于 key 的节点 + auto x = root(); + while (x != nullptr) + { + if (!key_comp_(value_traits::get_key(x->get_node_ptr()->value), key)) + { // key 小于等于 x 键值,向左走 + y = x, x = x->left; + } + else + { // key 大于 x 键值,向右走 + x = x->right; + } + } + const_iterator j = const_iterator(y); + return (j == end() || key_comp_(key, value_traits::get_key(*j))) ? end() : j; +} + +// 键值不小于 key 的第一个位置 +template +typename rb_tree::iterator +rb_tree:: +lower_bound(const key_type& key) +{ + auto y = header_; + auto x = root(); + while (x != nullptr) + { + if (!key_comp_(value_traits::get_key(x->get_node_ptr()->value), key)) + { // key <= x + y = x, x = x->left; + } + else + { + x = x->right; + } + } + return iterator(y); +} + +template +typename rb_tree::const_iterator +rb_tree:: +lower_bound(const key_type& key) const +{ + auto y = header_; + auto x = root(); + while (x != nullptr) + { + if (!key_comp_(value_traits::get_key(x->get_node_ptr()->value), key)) + { // key <= x + y = x, x = x->left; + } + else + { + x = x->right; + } + } + return const_iterator(y); +} + +// 键值不小于 key 的最后一个位置 +template +typename rb_tree::iterator +rb_tree:: +upper_bound(const key_type& key) +{ + auto y = header_; + auto x = root(); + while (x != nullptr) + { + if (key_comp_(key, value_traits::get_key(x->get_node_ptr()->value))) + { // key < x + y = x, x = x->left; + } + else + { + x = x->right; + } + } + return iterator(y); +} + +template +typename rb_tree::const_iterator +rb_tree:: +upper_bound(const key_type& key) const +{ + auto y = header_; + auto x = root(); + while (x != nullptr) + { + if (key_comp_(key, value_traits::get_key(x->get_node_ptr()->value))) + { // key < x + y = x, x = x->left; + } + else + { + x = x->right; + } + } + return const_iterator(y); +} + +// 交换 rb tree +template +void rb_tree:: +swap(rb_tree& rhs) noexcept +{ + if (this != &rhs) + { + mystl::swap(header_, rhs.header_); + mystl::swap(node_count_, rhs.node_count_); + mystl::swap(key_comp_, rhs.key_comp_); + } +} + +/*****************************************************************************************/ +// helper function + +// 创建一个结点 +template +template +typename rb_tree::node_ptr +rb_tree:: +create_node(Args&&... args) +{ + auto tmp = node_allocator::allocate(1); + try + { + data_allocator::construct(mystl::address_of(tmp->value), mystl::forward(args)...); + tmp->left = nullptr; + tmp->right = nullptr; + tmp->parent = nullptr; + } + catch (...) + { + node_allocator::deallocate(tmp); + throw; + } + return tmp; +} + +// 复制一个结点 +template +typename rb_tree::node_ptr +rb_tree:: +clone_node(base_ptr x) +{ + node_ptr tmp = create_node(x->get_node_ptr()->value); + tmp->color = x->color; + tmp->left = nullptr; + tmp->right = nullptr; + return tmp; +} + +// 销毁一个结点 +template +void rb_tree:: +destroy_node(node_ptr p) +{ + data_allocator::destroy(&p->value); + node_allocator::deallocate(p); +} + +// 初始化容器 +template +void rb_tree:: +rb_tree_init() +{ + header_ = base_allocator::allocate(1); + header_->color = rb_tree_red; // header_ 节点颜色为红,与 root 区分 + root() = nullptr; + leftmost() = header_; + rightmost() = header_; + node_count_ = 0; +} + +// reset 函数 +template +void rb_tree::reset() +{ + header_ = nullptr; + node_count_ = 0; +} + +// get_insert_multi_pos 函数 +template +mystl::pair::base_ptr, bool> +rb_tree::get_insert_multi_pos(const key_type& key) +{ + auto x = root(); + auto y = header_; + bool add_to_left = true; + while (x != nullptr) + { + y = x; + add_to_left = key_comp_(key, value_traits::get_key(x->get_node_ptr()->value)); + x = add_to_left ? x->left : x->right; + } + return mystl::make_pair(y, add_to_left); +} + +// get_insert_unique_pos 函数 +template +mystl::pair::base_ptr, bool>, bool> +rb_tree::get_insert_unique_pos(const key_type& key) +{ // 返回一个 pair,第一个值为一个 pair,包含插入点的父节点和一个 bool 表示是否在左边插入, + // 第二个值为一个 bool,表示是否插入成功 + auto x = root(); + auto y = header_; + bool add_to_left = true; // 树为空时也在 header_ 左边插入 + while (x != nullptr) + { + y = x; + add_to_left = key_comp_(key, value_traits::get_key(x->get_node_ptr()->value)); + x = add_to_left ? x->left : x->right; + } + iterator j = iterator(y); // 此时 y 为插入点的父节点 + if (add_to_left) + { + if (y == header_ || j == begin()) + { // 如果树为空树或插入点在最左节点处,肯定可以插入新的节点 + return mystl::make_pair(mystl::make_pair(y, true), true); + } + else + { // 否则,如果存在重复节点,那么 --j 就是重复的值 + --j; + } + } + if (key_comp_(value_traits::get_key(*j), key)) + { // 表明新节点没有重复 + return mystl::make_pair(mystl::make_pair(y, add_to_left), true); + } + // 进行至此,表示新节点与现有节点键值重复 + return mystl::make_pair(mystl::make_pair(y, add_to_left), false); +} + +// insert_value_at 函数 +// x 为插入点的父节点, value 为要插入的值,add_to_left 表示是否在左边插入 +template +typename rb_tree::iterator +rb_tree:: +insert_value_at(base_ptr x, const value_type& value, bool add_to_left) +{ + node_ptr node = create_node(value); + node->parent = x; + auto base_node = node->get_base_ptr(); + if (x == header_) + { + root() = base_node; + leftmost() = base_node; + rightmost() = base_node; + } + else if (add_to_left) + { + x->left = base_node; + if (leftmost() == x) + leftmost() = base_node; + } + else + { + x->right = base_node; + if (rightmost() == x) + rightmost() = base_node; + } + rb_tree_insert_rebalance(base_node, root()); + ++node_count_; + return iterator(node); +} + +// 在 x 节点处插入新的节点 +// x 为插入点的父节点, node 为要插入的节点,add_to_left 表示是否在左边插入 +template +typename rb_tree::iterator +rb_tree:: +insert_node_at(base_ptr x, node_ptr node, bool add_to_left) +{ + node->parent = x; + auto base_node = node->get_base_ptr(); + if (x == header_) + { + root() = base_node; + leftmost() = base_node; + rightmost() = base_node; + } + else if (add_to_left) + { + x->left = base_node; + if (leftmost() == x) + leftmost() = base_node; + } + else + { + x->right = base_node; + if (rightmost() == x) + rightmost() = base_node; + } + rb_tree_insert_rebalance(base_node, root()); + ++node_count_; + return iterator(node); +} + +// 插入元素,键值允许重复,使用 hint +template +typename rb_tree::iterator +rb_tree:: +insert_multi_use_hint(iterator hint, key_type key, node_ptr node) +{ + // 在 hint 附近寻找可插入的位置 + auto np = hint.node; + auto before = hint; + --before; + auto bnp = before.node; + if (!key_comp_(key, value_traits::get_key(*before)) && + !key_comp_(value_traits::get_key(*hint), key)) + { // before <= node <= hint + if (bnp->right == nullptr) + { + return insert_node_at(bnp, node, false); + } + else if (np->left == nullptr) + { + return insert_node_at(np, node, true); + } + } + auto pos = get_insert_multi_pos(key); + return insert_node_at(pos.first, node, pos.second); +} + +// 插入元素,键值不允许重复,使用 hint +template +typename rb_tree::iterator +rb_tree:: +insert_unique_use_hint(iterator hint, key_type key, node_ptr node) +{ + // 在 hint 附近寻找可插入的位置 + auto np = hint.node; + auto before = hint; + --before; + auto bnp = before.node; + if (key_comp_(value_traits::get_key(*before), key) && + key_comp_(key, value_traits::get_key(*hint))) + { // before < node < hint + if (bnp->right == nullptr) + { + return insert_node_at(bnp, node, false); + } + else if (np->left == nullptr) + { + return insert_node_at(np, node, true); + } + } + auto pos = get_insert_unique_pos(key); + if (!pos.second) + { + destroy_node(node); + return pos.first.first; + } + return insert_node_at(pos.first.first, node, pos.first.second); +} + +// copy_from 函数 +// 递归复制一颗树,节点从 x 开始,p 为 x 的父节点 +template +typename rb_tree::base_ptr +rb_tree::copy_from(base_ptr x, base_ptr p) +{ + auto top = clone_node(x); + top->parent = p; + try + { + if (x->right) + top->right = copy_from(x->right, top); + p = top; + x = x->left; + while (x != nullptr) + { + auto y = clone_node(x); + p->left = y; + y->parent = p; + if (x->right) + y->right = copy_from(x->right, y); + p = y; + x = x->left; + } + } + catch (...) + { + erase_since(top); + throw; + } + return top; +} + +// erase_since 函数 +// 从 x 节点开始删除该节点及其子树 +template +void rb_tree:: +erase_since(base_ptr x) +{ + while (x != nullptr) + { + erase_since(x->right); + auto y = x->left; + destroy_node(x->get_node_ptr()); + x = y; + } +} + +// 重载比较操作符 +template +bool operator==(const rb_tree& lhs, const rb_tree& rhs) +{ + return lhs.size() == rhs.size() && mystl::equal(lhs.begin(), lhs.end(), rhs.begin()); +} + +template +bool operator<(const rb_tree& lhs, const rb_tree& rhs) +{ + return mystl::lexicographical_compare(lhs.begin(), lhs.end(), rhs.begin(), rhs.end()); +} + +template +bool operator!=(const rb_tree& lhs, const rb_tree& rhs) +{ + return !(lhs == rhs); +} + +template +bool operator>(const rb_tree& lhs, const rb_tree& rhs) +{ + return rhs < lhs; +} + +template +bool operator<=(const rb_tree& lhs, const rb_tree& rhs) +{ + return !(rhs < lhs); +} + +template +bool operator>=(const rb_tree& lhs, const rb_tree& rhs) +{ + return !(lhs < rhs); +} + +// 重载 mystl 的 swap +template +void swap(rb_tree& lhs, rb_tree& rhs) noexcept +{ + lhs.swap(rhs); +} + +} // namespace mystl +#endif // !MYTINYSTL_RB_TREE_H_ + diff --git a/src/MyTinySTL-master/MyTinySTL-master/MyTinySTL/set.h b/src/MyTinySTL-master/MyTinySTL-master/MyTinySTL/set.h new file mode 100755 index 0000000..3aa8434 --- /dev/null +++ b/src/MyTinySTL-master/MyTinySTL-master/MyTinySTL/set.h @@ -0,0 +1,477 @@ +#ifndef MYTINYSTL_SET_H_ +#define MYTINYSTL_SET_H_ + +// 这个头文件包含两个模板类 set 和 multiset +// set : 集合,键值即实值,集合内元素会自动排序,键值不允许重复 +// multiset : 集合,键值即实值,集合内元素会自动排序,键值允许重复 + +// notes: +// +// 异常保证: +// mystl::set / mystl::multiset 满足基本异常保证,对以下等函数做强异常安全保证: +// * emplace +// * emplace_hint +// * insert + +#include "rb_tree.h" + +namespace mystl +{ + +// 模板类 set,键值不允许重复 +// 参数一代表键值类型,参数二代表键值比较方式,缺省使用 mystl::less +template > +class set +{ +public: + typedef Key key_type; + typedef Key value_type; + typedef Compare key_compare; + typedef Compare value_compare; + +private: + // 以 mystl::rb_tree 作为底层机制 + typedef mystl::rb_tree base_type; + base_type tree_; + +public: + // 使用 rb_tree 定义的型别 + typedef typename base_type::node_type node_type; + typedef typename base_type::const_pointer pointer; + typedef typename base_type::const_pointer const_pointer; + typedef typename base_type::const_reference reference; + typedef typename base_type::const_reference const_reference; + typedef typename base_type::const_iterator iterator; + typedef typename base_type::const_iterator const_iterator; + typedef typename base_type::const_reverse_iterator reverse_iterator; + typedef typename base_type::const_reverse_iterator const_reverse_iterator; + typedef typename base_type::size_type size_type; + typedef typename base_type::difference_type difference_type; + typedef typename base_type::allocator_type allocator_type; + +public: + // 构造、复制、移动函数 + set() = default; + + template + set(InputIterator first, InputIterator last) + :tree_() + { tree_.insert_unique(first, last); } + set(std::initializer_list ilist) + :tree_() + { tree_.insert_unique(ilist.begin(), ilist.end()); } + + set(const set& rhs) + :tree_(rhs.tree_) + { + } + set(set&& rhs) noexcept + :tree_(mystl::move(rhs.tree_)) + { + } + + set& operator=(const set& rhs) + { + tree_ = rhs.tree_; + return *this; + } + set& operator=(set&& rhs) + { + tree_ = mystl::move(rhs.tree_); + return *this; + } + set& operator=(std::initializer_list ilist) + { + tree_.clear(); + tree_.insert_unique(ilist.begin(), ilist.end()); + return *this; + } + + // 相关接口 + + key_compare key_comp() const { return tree_.key_comp(); } + value_compare value_comp() const { return tree_.key_comp(); } + allocator_type get_allocator() const { return tree_.get_allocator(); } + + // 迭代器相关 + + iterator begin() noexcept + { return tree_.begin(); } + const_iterator begin() const noexcept + { return tree_.begin(); } + iterator end() noexcept + { return tree_.end(); } + const_iterator end() const noexcept + { return tree_.end(); } + + reverse_iterator rbegin() noexcept + { return reverse_iterator(end()); } + const_reverse_iterator rbegin() const noexcept + { return const_reverse_iterator(end()); } + reverse_iterator rend() noexcept + { return reverse_iterator(begin()); } + const_reverse_iterator rend() const noexcept + { return const_reverse_iterator(begin()); } + + const_iterator cbegin() const noexcept + { return begin(); } + const_iterator cend() const noexcept + { return end(); } + const_reverse_iterator crbegin() const noexcept + { return rbegin(); } + const_reverse_iterator crend() const noexcept + { return rend(); } + + // 容量相关 + bool empty() const noexcept { return tree_.empty(); } + size_type size() const noexcept { return tree_.size(); } + size_type max_size() const noexcept { return tree_.max_size(); } + + // 插入删除操作 + + template + pair emplace(Args&& ...args) + { + return tree_.emplace_unique(mystl::forward(args)...); + } + + template + iterator emplace_hint(iterator hint, Args&& ...args) + { + return tree_.emplace_unique_use_hint(hint, mystl::forward(args)...); + } + + pair insert(const value_type& value) + { + return tree_.insert_unique(value); + } + pair insert(value_type&& value) + { + return tree_.insert_unique(mystl::move(value)); + } + + iterator insert(iterator hint, const value_type& value) + { + return tree_.insert_unique(hint, value); + } + iterator insert(iterator hint, value_type&& value) + { + return tree_.insert_unique(hint, mystl::move(value)); + } + + template + void insert(InputIterator first, InputIterator last) + { + tree_.insert_unique(first, last); + } + + void erase(iterator position) { tree_.erase(position); } + size_type erase(const key_type& key) { return tree_.erase_unique(key); } + void erase(iterator first, iterator last) { tree_.erase(first, last); } + + void clear() { tree_.clear(); } + + // set 相关操作 + + iterator find(const key_type& key) { return tree_.find(key); } + const_iterator find(const key_type& key) const { return tree_.find(key); } + + size_type count(const key_type& key) const { return tree_.count_unique(key); } + + iterator lower_bound(const key_type& key) { return tree_.lower_bound(key); } + const_iterator lower_bound(const key_type& key) const { return tree_.lower_bound(key); } + + iterator upper_bound(const key_type& key) { return tree_.upper_bound(key); } + const_iterator upper_bound(const key_type& key) const { return tree_.upper_bound(key); } + + pair + equal_range(const key_type& key) + { return tree_.equal_range_unique(key); } + + pair + equal_range(const key_type& key) const + { return tree_.equal_range_unique(key); } + + void swap(set& rhs) noexcept + { tree_.swap(rhs.tree_); } + +public: + friend bool operator==(const set& lhs, const set& rhs) { return lhs.tree_ == rhs.tree_; } + friend bool operator< (const set& lhs, const set& rhs) { return lhs.tree_ < rhs.tree_; } +}; + +// 重载比较操作符 +template +bool operator==(const set& lhs, const set& rhs) +{ + return lhs == rhs; +} + +template +bool operator<(const set& lhs, const set& rhs) +{ + return lhs < rhs; +} + +template +bool operator!=(const set& lhs, const set& rhs) +{ + return !(lhs == rhs); +} + +template +bool operator>(const set& lhs, const set& rhs) +{ + return rhs < lhs; +} + +template +bool operator<=(const set& lhs, const set& rhs) +{ + return !(rhs < lhs); +} + +template +bool operator>=(const set& lhs, const set& rhs) +{ + return !(lhs < rhs); +} + +// 重载 mystl 的 swap +template +void swap(set& lhs, set& rhs) noexcept +{ + lhs.swap(rhs); +} + +/*****************************************************************************************/ + +// 模板类 multiset,键值允许重复 +// 参数一代表键值类型,参数二代表键值比较方式,缺省使用 mystl::less +template > +class multiset +{ +public: + typedef Key key_type; + typedef Key value_type; + typedef Compare key_compare; + typedef Compare value_compare; + +private: + // 以 mystl::rb_tree 作为底层机制 + typedef mystl::rb_tree base_type; + base_type tree_; // 以 rb_tree 表现 multiset + +public: + // 使用 rb_tree 定义的型别 + typedef typename base_type::node_type node_type; + typedef typename base_type::const_pointer pointer; + typedef typename base_type::const_pointer const_pointer; + typedef typename base_type::const_reference reference; + typedef typename base_type::const_reference const_reference; + typedef typename base_type::const_iterator iterator; + typedef typename base_type::const_iterator const_iterator; + typedef typename base_type::const_reverse_iterator reverse_iterator; + typedef typename base_type::const_reverse_iterator const_reverse_iterator; + typedef typename base_type::size_type size_type; + typedef typename base_type::difference_type difference_type; + typedef typename base_type::allocator_type allocator_type; + +public: + // 构造、复制、移动函数 + multiset() = default; + + template + multiset(InputIterator first, InputIterator last) + :tree_() + { tree_.insert_multi(first, last); } + multiset(std::initializer_list ilist) + :tree_() + { tree_.insert_multi(ilist.begin(), ilist.end()); } + + multiset(const multiset& rhs) + :tree_(rhs.tree_) + { + } + multiset(multiset&& rhs) noexcept + :tree_(mystl::move(rhs.tree_)) + { + } + + multiset& operator=(const multiset& rhs) + { + tree_ = rhs.tree_; + return *this; + } + multiset& operator=(multiset&& rhs) + { + tree_ = mystl::move(rhs.tree_); + return *this; + } + multiset& operator=(std::initializer_list ilist) + { + tree_.clear(); + tree_.insert_multi(ilist.begin(), ilist.end()); + return *this; + } + + // 相关接口 + + key_compare key_comp() const { return tree_.key_comp(); } + value_compare value_comp() const { return tree_.key_comp(); } + allocator_type get_allocator() const { return tree_.get_allocator(); } + + // 迭代器相关 + + iterator begin() noexcept + { return tree_.begin(); } + const_iterator begin() const noexcept + { return tree_.begin(); } + iterator end() noexcept + { return tree_.end(); } + const_iterator end() const noexcept + { return tree_.end(); } + + reverse_iterator rbegin() noexcept + { return reverse_iterator(end()); } + const_reverse_iterator rbegin() const noexcept + { return const_reverse_iterator(end()); } + reverse_iterator rend() noexcept + { return reverse_iterator(begin()); } + const_reverse_iterator rend() const noexcept + { return const_reverse_iterator(begin()); } + + const_iterator cbegin() const noexcept + { return begin(); } + const_iterator cend() const noexcept + { return end(); } + const_reverse_iterator crbegin() const noexcept + { return rbegin(); } + const_reverse_iterator crend() const noexcept + { return rend(); } + + // 容量相关 + bool empty() const noexcept { return tree_.empty(); } + size_type size() const noexcept { return tree_.size(); } + size_type max_size() const noexcept { return tree_.max_size(); } + + // 插入删除操作 + + template + iterator emplace(Args&& ...args) + { + return tree_.emplace_multi(mystl::forward(args)...); + } + + template + iterator emplace_hint(iterator hint, Args&& ...args) + { + return tree_.emplace_multi_use_hint(hint, mystl::forward(args)...); + } + + iterator insert(const value_type& value) + { + return tree_.insert_multi(value); + } + iterator insert(value_type&& value) + { + return tree_.insert_multi(mystl::move(value)); + } + + iterator insert(iterator hint, const value_type& value) + { + return tree_.insert_multi(hint, value); + } + iterator insert(iterator hint, value_type&& value) + { + return tree_.insert_multi(hint, mystl::move(value)); + } + + template + void insert(InputIterator first, InputIterator last) + { + tree_.insert_multi(first, last); + } + + void erase(iterator position) { tree_.erase(position); } + size_type erase(const key_type& key) { return tree_.erase_multi(key); } + void erase(iterator first, iterator last) { tree_.erase(first, last); } + + void clear() { tree_.clear(); } + + // multiset 相关操作 + + iterator find(const key_type& key) { return tree_.find(key); } + const_iterator find(const key_type& key) const { return tree_.find(key); } + + size_type count(const key_type& key) const { return tree_.count_multi(key); } + + iterator lower_bound(const key_type& key) { return tree_.lower_bound(key); } + const_iterator lower_bound(const key_type& key) const { return tree_.lower_bound(key); } + + iterator upper_bound(const key_type& key) { return tree_.upper_bound(key); } + const_iterator upper_bound(const key_type& key) const { return tree_.upper_bound(key); } + + pair + equal_range(const key_type& key) + { return tree_.equal_range_multi(key); } + + pair + equal_range(const key_type& key) const + { return tree_.equal_range_multi(key); } + + void swap(multiset& rhs) noexcept + { tree_.swap(rhs.tree_); } + +public: + friend bool operator==(const multiset& lhs, const multiset& rhs) { return lhs.tree_ == rhs.tree_; } + friend bool operator< (const multiset& lhs, const multiset& rhs) { return lhs.tree_ < rhs.tree_; } +}; + +// 重载比较操作符 +template +bool operator==(const multiset& lhs, const multiset& rhs) +{ + return lhs == rhs; +} + +template +bool operator<(const multiset& lhs, const multiset& rhs) +{ + return lhs < rhs; +} + +template +bool operator!=(const multiset& lhs, const multiset& rhs) +{ + return !(lhs == rhs); +} + +template +bool operator>(const multiset& lhs, const multiset& rhs) +{ + return rhs < lhs; +} + +template +bool operator<=(const multiset& lhs, const multiset& rhs) +{ + return !(rhs < lhs); +} + +template +bool operator>=(const multiset& lhs, const multiset& rhs) +{ + return !(lhs < rhs); +} + +// 重载 mystl 的 swap +template +void swap(multiset& lhs, multiset& rhs) noexcept +{ + lhs.swap(rhs); +} + +} // namespace mystl +#endif // !MYTINYSTL_SET_H_ + diff --git a/src/MyTinySTL-master/MyTinySTL-master/MyTinySTL/set_algo.h b/src/MyTinySTL-master/MyTinySTL-master/MyTinySTL/set_algo.h new file mode 100755 index 0000000..8abc16d --- /dev/null +++ b/src/MyTinySTL-master/MyTinySTL-master/MyTinySTL/set_algo.h @@ -0,0 +1,253 @@ +#ifndef MYTINYSTL_SET_ALGO_H_ +#define MYTINYSTL_SET_ALGO_H_ + +// 这个头文件包含 set 的四种算法: union, intersection, difference, symmetric_difference +// 所有函数都要求序列有序 + +#include "algobase.h" +#include "iterator.h" + +namespace mystl +{ + +/*****************************************************************************************/ +// set_union +// 计算 S1∪S2 的结果并保存到 result 中,返回一个迭代器指向输出结果的尾部 +/*****************************************************************************************/ +template +OutputIter set_union(InputIter1 first1, InputIter1 last1, + InputIter2 first2, InputIter2 last2, + OutputIter result) +{ + while (first1 != last1 && first2 != last2) + { + if (*first1 < *first2) + { + *result = *first1; + ++first1; + } + else if (*first2 < *first1) + { + *result = *first2; + ++first2; + } + else + { + *result = *first1; + ++first1; + ++first2; + } + ++result; + } + // 将剩余元素拷贝到 result + return mystl::copy(first2, last2, mystl::copy(first1, last1, result)); +} + +// 重载版本使用函数对象 comp 代替比较操作 +template +OutputIter set_union(InputIter1 first1, InputIter1 last1, + InputIter2 first2, InputIter2 last2, + OutputIter result, Compared comp) +{ + while (first1 != last1 && first2 != last2) + { + if (comp(*first1, *first2)) + { + *result = *first1; + ++first1; + } + else if (comp(*first2, *first1)) + { + *result = *first2; + ++first2; + } + else + { + *result = *first1; + ++first1; + ++first2; + } + ++result; + } + // 将剩余元素拷贝到 result + return mystl::copy(first2, last2, mystl::copy(first1, last1, result)); +} + +/*****************************************************************************************/ +// set_intersection +// 计算 S1∩S2 的结果并保存到 result 中,返回一个迭代器指向输出结果的尾部 +/*****************************************************************************************/ +template +OutputIter set_intersection(InputIter1 first1, InputIter1 last1, + InputIter2 first2, InputIter2 last2, + OutputIter result) +{ + while (first1 != last1 && first2 != last2) + { + if (*first1 < *first2) + { + ++first1; + } + else if (*first2 < *first1) + { + ++first2; + } + else + { + *result = *first1; + ++first1; + ++first2; + ++result; + } + } + return result; +} + +// 重载版本使用函数对象 comp 代替比较操作 +template +OutputIter set_intersection(InputIter1 first1, InputIter1 last1, + InputIter2 first2, InputIter2 last2, + OutputIter result, Compared comp) +{ + while (first1 != last1 && first2 != last2) + { + if (comp(*first1, *first2)) + { + ++first1; + } + else if (comp(*first2, *first1)) + { + ++first2; + } + else + { + *result = *first1; + ++first1; + ++first2; + ++result; + } + } + return result; +} + +/*****************************************************************************************/ +// set_difference +// 计算 S1-S2 的结果并保存到 result 中,返回一个迭代器指向输出结果的尾部 +/*****************************************************************************************/ +template +OutputIter set_difference(InputIter1 first1, InputIter1 last1, + InputIter2 first2, InputIter2 last2, + OutputIter result) +{ + while (first1 != last1 && first2 != last2) + { + if (*first1 < *first2) + { + *result = *first1; + ++first1; + ++result; + } + else if (*first2 < *first1) + { + ++first2; + } + else + { + ++first1; + ++first2; + } + } + return mystl::copy(first1, last1, result); +} + +// 重载版本使用函数对象 comp 代替比较操作 +template +OutputIter set_difference(InputIter1 first1, InputIter1 last1, + InputIter2 first2, InputIter2 last2, + OutputIter result, Compared comp) +{ + while (first1 != last1 && first2 != last2) + { + if (comp(*first1, *first2)) + { + *result = *first1; + ++first1; + ++result; + } + else if (comp(*first2, *first1)) + { + ++first2; + } + else + { + ++first1; + ++first2; + } + } + return mystl::copy(first1, last1, result); +} + +/*****************************************************************************************/ +// set_symmetric_difference +// 计算 (S1-S2)∪(S2-S1) 的结果并保存到 result 中,返回一个迭代器指向输出结果的尾部 +/*****************************************************************************************/ +template +OutputIter set_symmetric_difference(InputIter1 first1, InputIter1 last1, + InputIter2 first2, InputIter2 last2, + OutputIter result) +{ + while (first1 != last1 && first2 != last2) + { + if (*first1 < *first2) + { + *result = *first1; + ++first1; + ++result; + } + else if (*first2 < *first1) + { + *result = *first2; + ++first2; + ++result; + } + else + { + ++first1; + ++first2; + } + } + return mystl::copy(first2, last2, mystl::copy(first1, last1, result)); +} + +// 重载版本使用函数对象 comp 代替比较操作 +template +OutputIter set_symmetric_difference(InputIter1 first1, InputIter1 last1, + InputIter2 first2, InputIter2 last2, + OutputIter result, Compared comp) +{ + while (first1 != last1 && first2 != last2) + { + if (comp(*first1, *first2)) + { + *result = *first1; + ++first1; + ++result; + } + else if (comp(*first2, *first1)) + { + *result = *first2; + ++first2; + ++result; + } + else + { + ++first1; + ++first2; + } + } + return mystl::copy(first2, last2, mystl::copy(first1, last1, result)); +} + +} // namespace mystl +#endif // !MYTINYSTL_SET_ALGO_H_ + diff --git a/src/MyTinySTL-master/MyTinySTL-master/MyTinySTL/stack.h b/src/MyTinySTL-master/MyTinySTL-master/MyTinySTL/stack.h new file mode 100755 index 0000000..1cbabca --- /dev/null +++ b/src/MyTinySTL-master/MyTinySTL-master/MyTinySTL/stack.h @@ -0,0 +1,173 @@ +#ifndef MYTINYSTL_STACK_H_ +#define MYTINYSTL_STACK_H_ + +// 这个头文件包含了一个模板类 stack +// stack : 栈 + +#include "deque.h" + +namespace mystl +{ + +// 模板类 stack +// 参数一代表数据类型,参数二代表底层容器类型,缺省使用 mystl::deque 作为底层容器 +template > +class stack +{ +public: + typedef Container container_type; + // 使用底层容器的型别 + typedef typename Container::value_type value_type; + typedef typename Container::size_type size_type; + typedef typename Container::reference reference; + typedef typename Container::const_reference const_reference; + + static_assert(std::is_same::value, + "the value_type of Container should be same with T"); +private: + container_type c_; // 用底层容器表现 stack + +public: + // 构造、复制、移动函数 + stack() = default; + + explicit stack(size_type n) + :c_(n) + { + } + stack(size_type n, const value_type& value) + :c_(n, value) + { + } + + template + stack(IIter first, IIter last) + : c_(first, last) + { + } + + stack(std::initializer_list ilist) + :c_(ilist.begin(), ilist.end()) + { + } + + stack(const Container& c) + :c_(c) + { + } + stack(Container&& c) noexcept(std::is_nothrow_move_constructible::value) + :c_(mystl::move(c)) + { + } + + stack(const stack& rhs) + :c_(rhs.c_) + { + } + stack(stack&& rhs) noexcept(std::is_nothrow_move_constructible::value) + :c_(mystl::move(rhs.c_)) + { + } + + stack& operator=(const stack& rhs) + { + c_ = rhs.c_; + return *this; + } + stack& operator=(stack&& rhs) noexcept(std::is_nothrow_move_assignable::value) + { + c_ = mystl::move(rhs.c_); + return *this; + } + + stack& operator=(std::initializer_list ilist) + { + c_ = ilist; + return *this; + } + + ~stack() = default; + + // 访问元素相关操作 + reference top() { return c_.back(); } + const_reference top() const { return c_.back(); } + + // 容量相关操作 + bool empty() const noexcept { return c_.empty(); } + size_type size() const noexcept { return c_.size(); } + + // 修改容器相关操作 + + template + void emplace(Args&& ...args) + { c_.emplace_back(mystl::forward(args)...); } + + void push(const value_type& value) + { c_.push_back(value); } + void push(value_type&& value) + { c_.push_back(mystl::move(value)); } + + void pop() + { c_.pop_back(); } + + void clear() + { + while (!empty()) + pop(); + } + + void swap(stack& rhs) noexcept(noexcept(mystl::swap(c_, rhs.c_))) + { mystl::swap(c_, rhs.c_); } + +public: + friend bool operator==(const stack& lhs, const stack& rhs) { return lhs.c_ == rhs.c_; } + friend bool operator< (const stack& lhs, const stack& rhs) { return lhs.c_ < rhs.c_; } +}; + +// 重载比较操作符 +template +bool operator==(const stack& lhs, const stack& rhs) +{ + return lhs == rhs; +} + +template +bool operator<(const stack& lhs, const stack& rhs) +{ + return lhs < rhs; +} + +template +bool operator!=(const stack& lhs, const stack& rhs) +{ + return !(lhs == rhs); +} + +template +bool operator>(const stack& lhs, const stack& rhs) +{ + return rhs < lhs; +} + +template +bool operator<=(const stack& lhs, const stack& rhs) +{ + return !(rhs < lhs); +} + +template +bool operator>=(const stack& lhs, const stack& rhs) +{ + return !(lhs < rhs); +} + +// 重载 mystl 的 swap +template +void swap(stack& lhs, stack& rhs) noexcept(noexcept(lhs.swap(rhs))) +{ + lhs.swap(rhs); +} + +} // namespace mystl +#endif // !MYTINYSTL_STACK_H_ + diff --git a/src/MyTinySTL-master/MyTinySTL-master/MyTinySTL/type_traits.h b/src/MyTinySTL-master/MyTinySTL-master/MyTinySTL/type_traits.h new file mode 100755 index 0000000..69d35ec --- /dev/null +++ b/src/MyTinySTL-master/MyTinySTL-master/MyTinySTL/type_traits.h @@ -0,0 +1,45 @@ +#ifndef MYTINYSTL_TYPE_TRAITS_H_ +#define MYTINYSTL_TYPE_TRAITS_H_ + +// 这个头文件用于提取类型信息 + +// use standard header for type_traits +#include + +namespace mystl +{ + +// helper struct + +template +struct m_integral_constant +{ + static constexpr T value = v; +}; + +template +using m_bool_constant = m_integral_constant; + +typedef m_bool_constant m_true_type; +typedef m_bool_constant m_false_type; + +/*****************************************************************************************/ +// type traits + +// is_pair + +// --- forward declaration begin +template +struct pair; +// --- forward declaration end + +template +struct is_pair : mystl::m_false_type {}; + +template +struct is_pair> : mystl::m_true_type {}; + +} // namespace mystl + +#endif // !MYTINYSTL_TYPE_TRAITS_H_ + diff --git a/src/MyTinySTL-master/MyTinySTL-master/MyTinySTL/uninitialized.h b/src/MyTinySTL-master/MyTinySTL-master/MyTinySTL/uninitialized.h new file mode 100755 index 0000000..910196e --- /dev/null +++ b/src/MyTinySTL-master/MyTinySTL-master/MyTinySTL/uninitialized.h @@ -0,0 +1,256 @@ +#ifndef MYTINYSTL_UNINITIALIZED_H_ +#define MYTINYSTL_UNINITIALIZED_H_ + +// 这个头文件用于对未初始化空间构造元素 + +#include "algobase.h" +#include "construct.h" +#include "iterator.h" +#include "type_traits.h" +#include "util.h" + +namespace mystl +{ + +/*****************************************************************************************/ +// uninitialized_copy +// 把 [first, last) 上的内容复制到以 result 为起始处的空间,返回复制结束的位置 +/*****************************************************************************************/ +template +ForwardIter +unchecked_uninit_copy(InputIter first, InputIter last, ForwardIter result, std::true_type) +{ + return mystl::copy(first, last, result); +} + +template +ForwardIter +unchecked_uninit_copy(InputIter first, InputIter last, ForwardIter result, std::false_type) +{ + auto cur = result; + try + { + for (; first != last; ++first, ++cur) + { + mystl::construct(&*cur, *first); + } + } + catch (...) + { + for (; result != cur; --cur) + mystl::destroy(&*cur); + } + return cur; +} + +template +ForwardIter uninitialized_copy(InputIter first, InputIter last, ForwardIter result) +{ + return mystl::unchecked_uninit_copy(first, last, result, + std::is_trivially_copy_assignable< + typename iterator_traits:: + value_type>{}); +} + +/*****************************************************************************************/ +// uninitialized_copy_n +// 把 [first, first + n) 上的内容复制到以 result 为起始处的空间,返回复制结束的位置 +/*****************************************************************************************/ +template +ForwardIter +unchecked_uninit_copy_n(InputIter first, Size n, ForwardIter result, std::true_type) +{ + return mystl::copy_n(first, n, result).second; +} + +template +ForwardIter +unchecked_uninit_copy_n(InputIter first, Size n, ForwardIter result, std::false_type) +{ + auto cur = result; + try + { + for (; n > 0; --n, ++cur, ++first) + { + mystl::construct(&*cur, *first); + } + } + catch (...) + { + for (; result != cur; --cur) + mystl::destroy(&*cur); + } + return cur; +} + +template +ForwardIter uninitialized_copy_n(InputIter first, Size n, ForwardIter result) +{ + return mystl::unchecked_uninit_copy_n(first, n, result, + std::is_trivially_copy_assignable< + typename iterator_traits:: + value_type>{}); +} + +/*****************************************************************************************/ +// uninitialized_fill +// 在 [first, last) 区间内填充元素值 +/*****************************************************************************************/ +template +void +unchecked_uninit_fill(ForwardIter first, ForwardIter last, const T& value, std::true_type) +{ + mystl::fill(first, last, value); +} + +template +void +unchecked_uninit_fill(ForwardIter first, ForwardIter last, const T& value, std::false_type) +{ + auto cur = first; + try + { + for (; cur != last; ++cur) + { + mystl::construct(&*cur, value); + } + } + catch (...) + { + for (;first != cur; ++first) + mystl::destroy(&*first); + } +} + +template +void uninitialized_fill(ForwardIter first, ForwardIter last, const T& value) +{ + mystl::unchecked_uninit_fill(first, last, value, + std::is_trivially_copy_assignable< + typename iterator_traits:: + value_type>{}); +} + +/*****************************************************************************************/ +// uninitialized_fill_n +// 从 first 位置开始,填充 n 个元素值,返回填充结束的位置 +/*****************************************************************************************/ +template +ForwardIter +unchecked_uninit_fill_n(ForwardIter first, Size n, const T& value, std::true_type) +{ + return mystl::fill_n(first, n, value); +} + +template +ForwardIter +unchecked_uninit_fill_n(ForwardIter first, Size n, const T& value, std::false_type) +{ + auto cur = first; + try + { + for (; n > 0; --n, ++cur) + { + mystl::construct(&*cur, value); + } + } + catch (...) + { + for (; first != cur; ++first) + mystl::destroy(&*first); + } + return cur; +} + +template +ForwardIter uninitialized_fill_n(ForwardIter first, Size n, const T& value) +{ + return mystl::unchecked_uninit_fill_n(first, n, value, + std::is_trivially_copy_assignable< + typename iterator_traits:: + value_type>{}); +} + +/*****************************************************************************************/ +// uninitialized_move +// 把[first, last)上的内容移动到以 result 为起始处的空间,返回移动结束的位置 +/*****************************************************************************************/ +template +ForwardIter +unchecked_uninit_move(InputIter first, InputIter last, ForwardIter result, std::true_type) +{ + return mystl::move(first, last, result); +} + +template +ForwardIter +unchecked_uninit_move(InputIter first, InputIter last, ForwardIter result, std::false_type) +{ + ForwardIter cur = result; + try + { + for (; first != last; ++first, ++cur) + { + mystl::construct(&*cur, mystl::move(*first)); + } + } + catch (...) + { + mystl::destroy(result, cur); + } + return cur; +} + +template +ForwardIter uninitialized_move(InputIter first, InputIter last, ForwardIter result) +{ + return mystl::unchecked_uninit_move(first, last, result, + std::is_trivially_move_assignable< + typename iterator_traits:: + value_type>{}); +} + +/*****************************************************************************************/ +// uninitialized_move_n +// 把[first, first + n)上的内容移动到以 result 为起始处的空间,返回移动结束的位置 +/*****************************************************************************************/ +template +ForwardIter +unchecked_uninit_move_n(InputIter first, Size n, ForwardIter result, std::true_type) +{ + return mystl::move(first, first + n, result); +} + +template +ForwardIter +unchecked_uninit_move_n(InputIter first, Size n, ForwardIter result, std::false_type) +{ + auto cur = result; + try + { + for (; n > 0; --n, ++first, ++cur) + { + mystl::construct(&*cur, mystl::move(*first)); + } + } + catch (...) + { + for (; result != cur; ++result) + mystl::destroy(&*result); + throw; + } + return cur; +} + +template +ForwardIter uninitialized_move_n(InputIter first, Size n, ForwardIter result) +{ + return mystl::unchecked_uninit_move_n(first, n, result, + std::is_trivially_move_assignable< + typename iterator_traits:: + value_type>{}); +} + +} // namespace mystl +#endif // !MYTINYSTL_UNINITIALIZED_H_ + diff --git a/src/MyTinySTL-master/MyTinySTL-master/MyTinySTL/unordered_map.h b/src/MyTinySTL-master/MyTinySTL-master/MyTinySTL/unordered_map.h new file mode 100755 index 0000000..5838a21 --- /dev/null +++ b/src/MyTinySTL-master/MyTinySTL-master/MyTinySTL/unordered_map.h @@ -0,0 +1,563 @@ +#ifndef MYTINYSTL_UNORDERED_MAP_H_ +#define MYTINYSTL_UNORDERED_MAP_H_ + +// 这个头文件包含两个模板类 unordered_map 和 unordered_multimap +// 功能与用法与 map 和 multimap 类似,不同的是使用 hashtable 作为底层实现机制,容器内的元素不会自动排序 + +// notes: +// +// 异常保证: +// mystl::unordered_map / mystl::unordered_multimap 满足基本异常保证,对以下等函数做强异常安全保证: +// * emplace +// * emplace_hint +// * insert + +#include "hashtable.h" + +namespace mystl +{ + +// 模板类 unordered_map,键值不允许重复 +// 参数一代表键值类型,参数二代表实值类型,参数三代表哈希函数,缺省使用 mystl::hash +// 参数四代表键值比较方式,缺省使用 mystl::equal_to +template , class KeyEqual = mystl::equal_to> +class unordered_map +{ +private: + // 使用 hashtable 作为底层机制 + typedef hashtable, Hash, KeyEqual> base_type; + base_type ht_; + +public: + // 使用 hashtable 的型别 + + typedef typename base_type::allocator_type allocator_type; + typedef typename base_type::key_type key_type; + typedef typename base_type::mapped_type mapped_type; + typedef typename base_type::value_type value_type; + typedef typename base_type::hasher hasher; + typedef typename base_type::key_equal key_equal; + + typedef typename base_type::size_type size_type; + typedef typename base_type::difference_type difference_type; + typedef typename base_type::pointer pointer; + typedef typename base_type::const_pointer const_pointer; + typedef typename base_type::reference reference; + typedef typename base_type::const_reference const_reference; + + typedef typename base_type::iterator iterator; + typedef typename base_type::const_iterator const_iterator; + typedef typename base_type::local_iterator local_iterator; + typedef typename base_type::const_local_iterator const_local_iterator; + + allocator_type get_allocator() const { return ht_.get_allocator(); } + +public: + // 构造、复制、移动、析构函数 + + unordered_map() + :ht_(100, Hash(), KeyEqual()) + { + } + + explicit unordered_map(size_type bucket_count, + const Hash& hash = Hash(), + const KeyEqual& equal = KeyEqual()) + :ht_(bucket_count, hash, equal) + { + } + + template + unordered_map(InputIterator first, InputIterator last, + const size_type bucket_count = 100, + const Hash& hash = Hash(), + const KeyEqual& equal = KeyEqual()) + : ht_(mystl::max(bucket_count, static_cast(mystl::distance(first, last))), hash, equal) + { + for (; first != last; ++first) + ht_.insert_unique_noresize(*first); + } + + unordered_map(std::initializer_list ilist, + const size_type bucket_count = 100, + const Hash& hash = Hash(), + const KeyEqual& equal = KeyEqual()) + :ht_(mystl::max(bucket_count, static_cast(ilist.size())), hash, equal) + { + for (auto first = ilist.begin(), last = ilist.end(); first != last; ++first) + ht_.insert_unique_noresize(*first); + } + + unordered_map(const unordered_map& rhs) + :ht_(rhs.ht_) + { + } + unordered_map(unordered_map&& rhs) noexcept + :ht_(mystl::move(rhs.ht_)) + { + } + + unordered_map& operator=(const unordered_map& rhs) + { + ht_ = rhs.ht_; + return *this; + } + unordered_map& operator=(unordered_map&& rhs) + { + ht_ = mystl::move(rhs.ht_); + return *this; + } + + unordered_map& operator=(std::initializer_list ilist) + { + ht_.clear(); + ht_.reserve(ilist.size()); + for (auto first = ilist.begin(), last = ilist.end(); first != last; ++first) + ht_.insert_unique_noresize(*first); + return *this; + } + + ~unordered_map() = default; + + // 迭代器相关 + + iterator begin() noexcept + { return ht_.begin(); } + const_iterator begin() const noexcept + { return ht_.begin(); } + iterator end() noexcept + { return ht_.end(); } + const_iterator end() const noexcept + { return ht_.end(); } + + const_iterator cbegin() const noexcept + { return ht_.cbegin(); } + const_iterator cend() const noexcept + { return ht_.cend(); } + + // 容量相关 + + bool empty() const noexcept { return ht_.empty(); } + size_type size() const noexcept { return ht_.size(); } + size_type max_size() const noexcept { return ht_.max_size(); } + + // 修改容器操作 + + // empalce / empalce_hint + + template + pair emplace(Args&& ...args) + { return ht_.emplace_unique(mystl::forward(args)...); } + + template + iterator emplace_hint(const_iterator hint, Args&& ...args) + { return ht_.emplace_unique_use_hint(hint, mystl::forward(args)...); } + + // insert + + pair insert(const value_type& value) + { return ht_.insert_unique(value); } + pair insert(value_type&& value) + { return ht_.emplace_unique(mystl::move(value)); } + + iterator insert(const_iterator hint, const value_type& value) + { return ht_.insert_unique_use_hint(hint, value); } + iterator insert(const_iterator hint, value_type&& value) + { return ht_.emplace_unique_use_hint(hint, mystl::move(value)); } + + template + void insert(InputIterator first, InputIterator last) + { ht_.insert_unique(first, last); } + + // erase / clear + + void erase(iterator it) + { ht_.erase(it); } + void erase(iterator first, iterator last) + { ht_.erase(first, last); } + + size_type erase(const key_type& key) + { return ht_.erase_unique(key); } + + void clear() + { ht_.clear(); } + + void swap(unordered_map& other) noexcept + { ht_.swap(other.ht_); } + + // 查找相关 + + mapped_type& at(const key_type& key) + { + iterator it = ht_.find(key); + THROW_OUT_OF_RANGE_IF(it.node == nullptr, "unordered_map no such element exists"); + return it->second; + } + const mapped_type& at(const key_type& key) const + { + iterator it = ht_.find(key); + THROW_OUT_OF_RANGE_IF(it.node == nullptr, "unordered_map no such element exists"); + return it->second; + } + + mapped_type& operator[](const key_type& key) + { + iterator it = ht_.find(key); + if (it.node == nullptr) + it = ht_.emplace_unique(key, T{}).first; + return it->second; + } + mapped_type& operator[](key_type&& key) + { + iterator it = ht_.find(key); + if (it.node == nullptr) + it = ht_.emplace_unique(mystl::move(key), T{}).first; + return it->second; + } + + size_type count(const key_type& key) const + { return ht_.count(key); } + + iterator find(const key_type& key) + { return ht_.find(key); } + const_iterator find(const key_type& key) const + { return ht_.find(key); } + + pair equal_range(const key_type& key) + { return ht_.equal_range_unique(key); } + pair equal_range(const key_type& key) const + { return ht_.equal_range_unique(key); } + + // bucket interface + + local_iterator begin(size_type n) noexcept + { return ht_.begin(n); } + const_local_iterator begin(size_type n) const noexcept + { return ht_.begin(n); } + const_local_iterator cbegin(size_type n) const noexcept + { return ht_.cbegin(n); } + + local_iterator end(size_type n) noexcept + { return ht_.end(n); } + const_local_iterator end(size_type n) const noexcept + { return ht_.end(n); } + const_local_iterator cend(size_type n) const noexcept + { return ht_.cend(n); } + + size_type bucket_count() const noexcept + { return ht_.bucket_count(); } + size_type max_bucket_count() const noexcept + { return ht_.max_bucket_count(); } + + size_type bucket_size(size_type n) const noexcept + { return ht_.bucket_size(n); } + size_type bucket(const key_type& key) const + { return ht_.bucket(key); } + + // hash policy + + float load_factor() const noexcept { return ht_.load_factor(); } + + float max_load_factor() const noexcept { return ht_.max_load_factor(); } + void max_load_factor(float ml) { ht_.max_load_factor(ml); } + + void rehash(size_type count) { ht_.rehash(count); } + void reserve(size_type count) { ht_.reserve(count); } + + hasher hash_fcn() const { return ht_.hash_fcn(); } + key_equal key_eq() const { return ht_.key_eq(); } + +public: + friend bool operator==(const unordered_map& lhs, const unordered_map& rhs) + { + return lhs.ht_.equal_range_unique(rhs.ht_); + } + friend bool operator!=(const unordered_map& lhs, const unordered_map& rhs) + { + return !lhs.ht_.equal_range_unique(rhs.ht_); + } +}; + +// 重载比较操作符 +template +bool operator==(const unordered_map& lhs, + const unordered_map& rhs) +{ + return lhs == rhs; +} + +template +bool operator!=(const unordered_map& lhs, + const unordered_map& rhs) +{ + return lhs != rhs; +} + +// 重载 mystl 的 swap +template +void swap(unordered_map& lhs, + unordered_map& rhs) +{ + lhs.swap(rhs); +} + +/*****************************************************************************************/ + +// 模板类 unordered_multimap,键值允许重复 +// 参数一代表键值类型,参数二代表实值类型,参数三代表哈希函数,缺省使用 mystl::hash +// 参数四代表键值比较方式,缺省使用 mystl::equal_to +template , class KeyEqual = mystl::equal_to> +class unordered_multimap +{ +private: + // 使用 hashtable 作为底层机制 + typedef hashtable, Hash, KeyEqual> base_type; + base_type ht_; + +public: + // 使用 hashtable 的型别 + typedef typename base_type::allocator_type allocator_type; + typedef typename base_type::key_type key_type; + typedef typename base_type::mapped_type mapped_type; + typedef typename base_type::value_type value_type; + typedef typename base_type::hasher hasher; + typedef typename base_type::key_equal key_equal; + + typedef typename base_type::size_type size_type; + typedef typename base_type::difference_type difference_type; + typedef typename base_type::pointer pointer; + typedef typename base_type::const_pointer const_pointer; + typedef typename base_type::reference reference; + typedef typename base_type::const_reference const_reference; + + typedef typename base_type::iterator iterator; + typedef typename base_type::const_iterator const_iterator; + typedef typename base_type::local_iterator local_iterator; + typedef typename base_type::const_local_iterator const_local_iterator; + + allocator_type get_allocator() const { return ht_.get_allocator(); } + +public: + // 构造、复制、移动函数 + + unordered_multimap() + :ht_(100, Hash(), KeyEqual()) + { + } + + explicit unordered_multimap(size_type bucket_count, + const Hash& hash = Hash(), + const KeyEqual& equal = KeyEqual()) + :ht_(bucket_count, hash, equal) + { + } + + template + unordered_multimap(InputIterator first, InputIterator last, + const size_type bucket_count = 100, + const Hash& hash = Hash(), + const KeyEqual& equal = KeyEqual()) + :ht_(mystl::max(bucket_count, static_cast(mystl::distance(first, last))), hash, equal) + { + for (; first != last; ++first) + ht_.insert_multi_noresize(*first); + } + + unordered_multimap(std::initializer_list ilist, + const size_type bucket_count = 100, + const Hash& hash = Hash(), + const KeyEqual& equal = KeyEqual()) + :ht_(mystl::max(bucket_count, static_cast(ilist.size())), hash, equal) + { + for (auto first = ilist.begin(), last = ilist.end(); first != last; ++first) + ht_.insert_multi_noresize(*first); + } + + unordered_multimap(const unordered_multimap& rhs) + :ht_(rhs.ht_) + { + } + unordered_multimap(unordered_multimap&& rhs) noexcept + :ht_(mystl::move(rhs.ht_)) + { + } + + unordered_multimap& operator=(const unordered_multimap& rhs) + { + ht_ = rhs.ht_; + return *this; + } + unordered_multimap& operator=(unordered_multimap&& rhs) + { + ht_ = mystl::move(rhs.ht_); + return *this; + } + + unordered_multimap& operator=(std::initializer_list ilist) + { + ht_.clear(); + ht_.reserve(ilist.size()); + for (auto first = ilist.begin(), last = ilist.end(); first != last; ++first) + ht_.insert_multi_noresize(*first); + return *this; + } + + ~unordered_multimap() = default; + + // 迭代器相关 + + iterator begin() noexcept + { return ht_.begin(); } + const_iterator begin() const noexcept + { return ht_.begin(); } + iterator end() noexcept + { return ht_.end(); } + const_iterator end() const noexcept + { return ht_.end(); } + + const_iterator cbegin() const noexcept + { return ht_.cbegin(); } + const_iterator cend() const noexcept + { return ht_.cend(); } + + // 容量相关 + + bool empty() const noexcept { return ht_.empty(); } + size_type size() const noexcept { return ht_.size(); } + size_type max_size() const noexcept { return ht_.max_size(); } + + // 修改容器相关 + + // emplace / emplace_hint + + template + iterator emplace(Args&& ...args) + { return ht_.emplace_multi(mystl::forward(args)...); } + + template + iterator emplace_hint(const_iterator hint, Args&& ...args) + { return ht_.emplace_multi_use_hint(hint, mystl::forward(args)...); } + + // insert + + iterator insert(const value_type& value) + { return ht_.insert_multi(value); } + iterator insert(value_type&& value) + { return ht_.emplace_multi(mystl::move(value)); } + + iterator insert(const_iterator hint, const value_type& value) + { return ht_.insert_multi_use_hint(hint, value); } + iterator insert(const_iterator hint, value_type&& value) + { return ht_.emplace_multi_use_hint(hint, mystl::move(value)); } + + template + void insert(InputIterator first, InputIterator last) + { ht_.insert_multi(first, last); } + + // erase / clear + + void erase(iterator it) + { ht_.erase(it); } + void erase(iterator first, iterator last) + { ht_.erase(first, last); } + + size_type erase(const key_type& key) + { return ht_.erase_multi(key); } + + void clear() + { ht_.clear(); } + + void swap(unordered_multimap& other) noexcept + { ht_.swap(other.ht_); } + + // 查找相关 + + size_type count(const key_type& key) const + { return ht_.count(key); } + + iterator find(const key_type& key) + { return ht_.find(key); } + const_iterator find(const key_type& key) const + { return ht_.find(key); } + + pair equal_range(const key_type& key) + { return ht_.equal_range_multi(key); } + pair equal_range(const key_type& key) const + { return ht_.equal_range_multi(key); } + + // bucket interface + + local_iterator begin(size_type n) noexcept + { return ht_.begin(n); } + const_local_iterator begin(size_type n) const noexcept + { return ht_.begin(n); } + const_local_iterator cbegin(size_type n) const noexcept + { return ht_.cbegin(n); } + + local_iterator end(size_type n) noexcept + { return ht_.end(n); } + const_local_iterator end(size_type n) const noexcept + { return ht_.end(n); } + const_local_iterator cend(size_type n) const noexcept + { return ht_.cend(n); } + + size_type bucket_count() const noexcept + { return ht_.bucket_count(); } + size_type max_bucket_count() const noexcept + { return ht_.max_bucket_count(); } + + size_type bucket_size(size_type n) const noexcept + { return ht_.bucket_size(n); } + size_type bucket(const key_type& key) const + { return ht_.bucket(key); } + + // hash policy + + float load_factor() const noexcept { return ht_.load_factor(); } + + float max_load_factor() const noexcept { return ht_.max_load_factor(); } + void max_load_factor(float ml) { ht_.max_load_factor(ml); } + + void rehash(size_type count) { ht_.rehash(count); } + void reserve(size_type count) { ht_.reserve(count); } + + hasher hash_fcn() const { return ht_.hash_fcn(); } + key_equal key_eq() const { return ht_.key_eq(); } + +public: + friend bool operator==(const unordered_multimap& lhs, const unordered_multimap& rhs) + { + return lhs.ht_.equal_range_multi(rhs.ht_); + } + friend bool operator!=(const unordered_multimap& lhs, const unordered_multimap& rhs) + { + return !lhs.ht_.equal_range_multi(rhs.ht_); + } +}; + +// 重载比较操作符 +template +bool operator==(const unordered_multimap& lhs, + const unordered_multimap& rhs) +{ + return lhs == rhs; +} + +template +bool operator!=(const unordered_multimap& lhs, + const unordered_multimap& rhs) +{ + return lhs != rhs; +} + +// 重载 mystl 的 swap +template +void swap(unordered_multimap& lhs, + unordered_multimap& rhs) +{ + lhs.swap(rhs); +} + +} // namespace mystl +#endif // !MYTINYSTL_UNORDERED_MAP_H_ + diff --git a/src/MyTinySTL-master/MyTinySTL-master/MyTinySTL/unordered_set.h b/src/MyTinySTL-master/MyTinySTL-master/MyTinySTL/unordered_set.h new file mode 100755 index 0000000..eb60589 --- /dev/null +++ b/src/MyTinySTL-master/MyTinySTL-master/MyTinySTL/unordered_set.h @@ -0,0 +1,534 @@ +#ifndef MYTINYSTL_UNORDERED_SET_H_ +#define MYTINYSTL_UNORDERED_SET_H_ + +// 这个头文件包含两个模板类 unordered_set 和 unordered_multiset +// 功能与用法与 set 和 multiset 类似,不同的是使用 hashtable 作为底层实现机制,容器中的元素不会自动排序 + +// notes: +// +// 异常保证: +// mystl::unordered_set / mystl::unordered_multiset 满足基本异常保证,对以下等函数做强异常安全保证: +// * emplace +// * emplace_hint +// * insert + +#include "hashtable.h" + +namespace mystl +{ + +// 模板类 unordered_set,键值不允许重复 +// 参数一代表键值类型,参数二代表哈希函数,缺省使用 mystl::hash, +// 参数三代表键值比较方式,缺省使用 mystl::equal_to +template , class KeyEqual = mystl::equal_to> +class unordered_set +{ +private: + // 使用 hashtable 作为底层机制 + typedef hashtable base_type; + base_type ht_; + +public: + // 使用 hashtable 的型别 + typedef typename base_type::allocator_type allocator_type; + typedef typename base_type::key_type key_type; + typedef typename base_type::value_type value_type; + typedef typename base_type::hasher hasher; + typedef typename base_type::key_equal key_equal; + + typedef typename base_type::size_type size_type; + typedef typename base_type::difference_type difference_type; + typedef typename base_type::pointer pointer; + typedef typename base_type::const_pointer const_pointer; + typedef typename base_type::reference reference; + typedef typename base_type::const_reference const_reference; + + typedef typename base_type::const_iterator iterator; + typedef typename base_type::const_iterator const_iterator; + typedef typename base_type::const_local_iterator local_iterator; + typedef typename base_type::const_local_iterator const_local_iterator; + + allocator_type get_allocator() const { return ht_.get_allocator(); } + +public: + // 构造、复制、移动函数 + + unordered_set() + :ht_(100, Hash(), KeyEqual()) + { + } + + explicit unordered_set(size_type bucket_count, + const Hash& hash = Hash(), + const KeyEqual& equal = KeyEqual()) + :ht_(bucket_count, hash, equal) + { + } + + template + unordered_set(InputIterator first, InputIterator last, + const size_type bucket_count = 100, + const Hash& hash = Hash(), + const KeyEqual& equal = KeyEqual()) + : ht_(mystl::max(bucket_count, static_cast(mystl::distance(first, last))), hash, equal) + { + for (; first != last; ++first) + ht_.insert_unique_noresize(*first); + } + + unordered_set(std::initializer_list ilist, + const size_type bucket_count = 100, + const Hash& hash = Hash(), + const KeyEqual& equal = KeyEqual()) + :ht_(mystl::max(bucket_count, static_cast(ilist.size())), hash, equal) + { + for (auto first = ilist.begin(), last = ilist.end(); first != last; ++first) + ht_.insert_unique_noresize(*first); + } + + unordered_set(const unordered_set& rhs) + :ht_(rhs.ht_) + { + } + unordered_set(unordered_set&& rhs) noexcept + : ht_(mystl::move(rhs.ht_)) + { + } + + unordered_set& operator=(const unordered_set& rhs) + { + ht_ = rhs.ht_; + return *this; + } + unordered_set& operator=(unordered_set&& rhs) + { + ht_ = mystl::move(rhs.ht_); + return *this; + } + + unordered_set& operator=(std::initializer_list ilist) + { + ht_.clear(); + ht_.reserve(ilist.size()); + for (auto first = ilist.begin(), last = ilist.end(); first != last; ++first) + ht_.insert_unique_noresize(*first); + return *this; + } + + ~unordered_set() = default; + + // 迭代器相关 + + iterator begin() noexcept + { return ht_.begin(); } + const_iterator begin() const noexcept + { return ht_.begin(); } + iterator end() noexcept + { return ht_.end(); } + const_iterator end() const noexcept + { return ht_.end(); } + + const_iterator cbegin() const noexcept + { return ht_.cbegin(); } + const_iterator cend() const noexcept + { return ht_.cend(); } + + // 容量相关 + + bool empty() const noexcept { return ht_.empty(); } + size_type size() const noexcept { return ht_.size(); } + size_type max_size() const noexcept { return ht_.max_size(); } + + // 修改容器操作 + + // empalce / empalce_hint + + template + pair emplace(Args&& ...args) + { return ht_.emplace_unique(mystl::forward(args)...); } + + template + iterator emplace_hint(const_iterator hint, Args&& ...args) + { return ht_.emplace_unique_use_hint(hint, mystl::forward(args)...); } + + // insert + + pair insert(const value_type& value) + { return ht_.insert_unique(value); } + pair insert(value_type&& value) + { return ht_.emplace_unique(mystl::move(value)); } + + iterator insert(const_iterator hint, const value_type& value) + { return ht_.insert_unique_use_hint(hint, value); } + iterator insert(const_iterator hint, value_type&& value) + { return ht_.emplace_unique_use_hint(hint, mystl::move(value)); } + + template + void insert(InputIterator first, InputIterator last) + { ht_.insert_unique(first, last); } + + // erase / clear + + void erase(iterator it) + { ht_.erase(it); } + void erase(iterator first, iterator last) + { ht_.erase(first, last); } + + size_type erase(const key_type& key) + { return ht_.erase_unique(key); } + + void clear() + { ht_.clear(); } + + void swap(unordered_set& other) noexcept + { ht_.swap(other.ht_); } + + // 查找相关 + + size_type count(const key_type& key) const + { return ht_.count(key); } + + iterator find(const key_type& key) + { return ht_.find(key); } + const_iterator find(const key_type& key) const + { return ht_.find(key); } + + pair equal_range(const key_type& key) + { return ht_.equal_range_unique(key); } + pair equal_range(const key_type& key) const + { return ht_.equal_range_unique(key); } + + // bucket interface + + local_iterator begin(size_type n) noexcept + { return ht_.begin(n); } + const_local_iterator begin(size_type n) const noexcept + { return ht_.begin(n); } + const_local_iterator cbegin(size_type n) const noexcept + { return ht_.cbegin(n); } + + local_iterator end(size_type n) noexcept + { return ht_.end(n); } + const_local_iterator end(size_type n) const noexcept + { return ht_.end(n); } + const_local_iterator cend(size_type n) const noexcept + { return ht_.cend(n); } + + size_type bucket_count() const noexcept + { return ht_.bucket_count(); } + size_type max_bucket_count() const noexcept + { return ht_.max_bucket_count(); } + + size_type bucket_size(size_type n) const noexcept + { return ht_.bucket_size(n); } + size_type bucket(const key_type& key) const + { return ht_.bucket(key); } + + // hash policy + + float load_factor() const noexcept { return ht_.load_factor(); } + + float max_load_factor() const noexcept { return ht_.max_load_factor(); } + void max_load_factor(float ml) { ht_.max_load_factor(ml); } + + void rehash(size_type count) { ht_.rehash(count); } + void reserve(size_type count) { ht_.reserve(count); } + + hasher hash_fcn() const { return ht_.hash_fcn(); } + key_equal key_eq() const { return ht_.key_eq(); } + + +public: + friend bool operator==(const unordered_set& lhs, const unordered_set& rhs) + { + return lhs.ht_.equal_range_unique(rhs.ht_); + } + friend bool operator!=(const unordered_set& lhs, const unordered_set& rhs) + { + return !lhs.ht_.equal_range_unique(rhs.ht_); + } +}; + +// 重载比较操作符 +template +bool operator==(const unordered_set& lhs, + const unordered_set& rhs) +{ + return lhs == rhs; +} + +template +bool operator!=(const unordered_set& lhs, + const unordered_set& rhs) +{ + return lhs != rhs; +} + +// 重载 mystl 的 swap +template +void swap(unordered_set& lhs, + unordered_set& rhs) +{ + lhs.swap(rhs); +} + +/*****************************************************************************************/ + +// 模板类 unordered_multiset,键值允许重复 +// 参数一代表键值类型,参数二代表哈希函数,缺省使用 mystl::hash, +// 参数三代表键值比较方式,缺省使用 mystl::equal_to +template , class KeyEqual = mystl::equal_to> +class unordered_multiset +{ +private: + // 使用 hashtable 作为底层机制 + typedef hashtable base_type; + base_type ht_; + +public: + // 使用 hashtable 的型别 + typedef typename base_type::allocator_type allocator_type; + typedef typename base_type::key_type key_type; + typedef typename base_type::value_type value_type; + typedef typename base_type::hasher hasher; + typedef typename base_type::key_equal key_equal; + + typedef typename base_type::size_type size_type; + typedef typename base_type::difference_type difference_type; + typedef typename base_type::pointer pointer; + typedef typename base_type::const_pointer const_pointer; + typedef typename base_type::reference reference; + typedef typename base_type::const_reference const_reference; + + typedef typename base_type::const_iterator iterator; + typedef typename base_type::const_iterator const_iterator; + typedef typename base_type::const_local_iterator local_iterator; + typedef typename base_type::const_local_iterator const_local_iterator; + + allocator_type get_allocator() const { return ht_.get_allocator(); } + +public: + // 构造、复制、移动函数 + + unordered_multiset() + :ht_(100, Hash(), KeyEqual()) + { + } + + explicit unordered_multiset(size_type bucket_count, + const Hash& hash = Hash(), + const KeyEqual& equal = KeyEqual()) + :ht_(bucket_count, hash, equal) + { + } + + template + unordered_multiset(InputIterator first, InputIterator last, + const size_type bucket_count = 100, + const Hash& hash = Hash(), + const KeyEqual& equal = KeyEqual()) + : ht_(mystl::max(bucket_count, static_cast(mystl::distance(first, last))), hash, equal) + { + for (; first != last; ++first) + ht_.insert_multi_noresize(*first); + } + + unordered_multiset(std::initializer_list ilist, + const size_type bucket_count = 100, + const Hash& hash = Hash(), + const KeyEqual& equal = KeyEqual()) + :ht_(mystl::max(bucket_count, static_cast(ilist.size())), hash, equal) + { + for (auto first = ilist.begin(), last = ilist.end(); first != last; ++first) + ht_.insert_multi_noresize(*first); + } + + unordered_multiset(const unordered_multiset& rhs) + :ht_(rhs.ht_) + { + } + unordered_multiset(unordered_multiset&& rhs) noexcept + : ht_(mystl::move(rhs.ht_)) + { + } + + unordered_multiset& operator=(const unordered_multiset& rhs) + { + ht_ = rhs.ht_; + return *this; + } + unordered_multiset& operator=(unordered_multiset&& rhs) + { + ht_ = mystl::move(rhs.ht_); + return *this; + } + + unordered_multiset& operator=(std::initializer_list ilist) + { + ht_.clear(); + ht_.reserve(ilist.size()); + for (auto first = ilist.begin(), last = ilist.end(); first != last; ++first) + ht_.insert_multi_noresize(*first); + return *this; + } + + ~unordered_multiset() = default; + + + // 迭代器相关 + + iterator begin() noexcept + { return ht_.begin(); } + const_iterator begin() const noexcept + { return ht_.begin(); } + iterator end() noexcept + { return ht_.end(); } + const_iterator end() const noexcept + { return ht_.end(); } + + const_iterator cbegin() const noexcept + { return ht_.cbegin(); } + const_iterator cend() const noexcept + { return ht_.cend(); } + + // 容量相关 + + bool empty() const noexcept { return ht_.empty(); } + size_type size() const noexcept { return ht_.size(); } + size_type max_size() const noexcept { return ht_.max_size(); } + + // 修改容器相关 + + // emplace / emplace_hint + + template + iterator emplace(Args&& ...args) + { return ht_.emplace_multi(mystl::forward(args)...); } + + template + iterator emplace_hint(const_iterator hint, Args&& ...args) + { return ht_.emplace_multi_use_hint(hint, mystl::forward(args)...); } + + // insert + + iterator insert(const value_type& value) + { return ht_.insert_multi(value); } + iterator insert(value_type&& value) + { return ht_.emplace_multi(mystl::move(value)); } + + iterator insert(const_iterator hint, const value_type& value) + { return ht_.insert_multi_use_hint(hint, value); } + iterator insert(const_iterator hint, value_type&& value) + { return ht_.emplace_multi_use_hint(hint, mystl::move(value)); } + + template + void insert(InputIterator first, InputIterator last) + { ht_.insert_multi(first, last); } + + // erase / clear + + void erase(iterator it) + { ht_.erase(it); } + void erase(iterator first, iterator last) + { ht_.erase(first, last); } + + size_type erase(const key_type& key) + { return ht_.erase_multi(key); } + + void clear() + { ht_.clear(); } + + void swap(unordered_multiset& other) noexcept + { ht_.swap(other.ht_); } + + // 查找相关 + + size_type count(const key_type& key) const + { return ht_.count(key); } + + iterator find(const key_type& key) + { return ht_.find(key); } + const_iterator find(const key_type& key) const + { return ht_.find(key); } + + pair equal_range(const key_type& key) + { return ht_.equal_range_multi(key); } + pair equal_range(const key_type& key) const + { return ht_.equal_range_multi(key); } + + // bucket interface + + local_iterator begin(size_type n) noexcept + { return ht_.begin(n); } + const_local_iterator begin(size_type n) const noexcept + { return ht_.begin(n); } + const_local_iterator cbegin(size_type n) const noexcept + { return ht_.cbegin(n); } + + local_iterator end(size_type n) noexcept + { return ht_.end(n); } + const_local_iterator end(size_type n) const noexcept + { return ht_.end(n); } + const_local_iterator cend(size_type n) const noexcept + { return ht_.cend(n); } + + size_type bucket_count() const noexcept + { return ht_.bucket_count(); } + size_type max_bucket_count() const noexcept + { return ht_.max_bucket_count(); } + + size_type bucket_size(size_type n) const noexcept + { return ht_.bucket_size(n); } + size_type bucket(const key_type& key) const + { return ht_.bucket(key); } + + // hash policy + + float load_factor() const noexcept { return ht_.load_factor(); } + + float max_load_factor() const noexcept { return ht_.max_load_factor(); } + void max_load_factor(float ml) { ht_.max_load_factor(ml); } + + void rehash(size_type count) { ht_.rehash(count); } + void reserve(size_type count) { ht_.reserve(count); } + + hasher hash_fcn() const { return ht_.hash_fcn(); } + key_equal key_eq() const { return ht_.key_eq(); } + +public: + friend bool operator==(const unordered_multiset& lhs, const unordered_multiset& rhs) + { + return lhs.ht_.equal_range_multi(rhs.ht_); + } + friend bool operator!=(const unordered_multiset& lhs, const unordered_multiset& rhs) + { + return !lhs.ht_.equal_range_multi(rhs.ht_); + } +}; + +// 重载比较操作符 +template +bool operator==(const unordered_multiset& lhs, + const unordered_multiset& rhs) +{ + return lhs == rhs; +} + +template +bool operator!=(const unordered_multiset& lhs, + const unordered_multiset& rhs) +{ + return lhs != rhs; +} + +// 重载 mystl 的 swap +template +void swap(unordered_multiset& lhs, + unordered_multiset& rhs) +{ + lhs.swap(rhs); +} + +} // namespace mystl +#endif // !MYTINYSTL_UNORDERED_SET_H_ + diff --git a/src/MyTinySTL-master/MyTinySTL-master/MyTinySTL/util.h b/src/MyTinySTL-master/MyTinySTL-master/MyTinySTL/util.h new file mode 100755 index 0000000..df6d583 --- /dev/null +++ b/src/MyTinySTL-master/MyTinySTL-master/MyTinySTL/util.h @@ -0,0 +1,297 @@ +#ifndef MYTINYSTL_UTIL_H_ +#define MYTINYSTL_UTIL_H_ + +// 这个文件包含一些通用工具,包括 move, forward, swap 等函数,以及 pair 等 + +#include + +#include "type_traits.h" + +namespace mystl +{ + +// move + +template +typename std::remove_reference::type&& move(T&& arg) noexcept +{ + return static_cast::type&&>(arg); +} + +// forward + +template +T&& forward(typename std::remove_reference::type& arg) noexcept +{ + return static_cast(arg); +} + +template +T&& forward(typename std::remove_reference::type&& arg) noexcept +{ + static_assert(!std::is_lvalue_reference::value, "bad forward"); + return static_cast(arg); +} + +// swap + +template +void swap(Tp& lhs, Tp& rhs) +{ + auto tmp(mystl::move(lhs)); + lhs = mystl::move(rhs); + rhs = mystl::move(tmp); +} + +template +ForwardIter2 swap_range(ForwardIter1 first1, ForwardIter1 last1, ForwardIter2 first2) +{ + for (; first1 != last1; ++first1, (void) ++first2) + mystl::swap(*first1, *first2); + return first2; +} + +template +void swap(Tp(&a)[N], Tp(&b)[N]) +{ + mystl::swap_range(a, a + N, b); +} + +// -------------------------------------------------------------------------------------- +// pair + +// 结构体模板 : pair +// 两个模板参数分别表示两个数据的类型 +// 用 first 和 second 来分别取出第一个数据和第二个数据 +template +struct pair +{ + typedef Ty1 first_type; + typedef Ty2 second_type; + + first_type first; // 保存第一个数据 + second_type second; // 保存第二个数据 + + // default constructiable + template ::value && + std::is_default_constructible::value, void>::type> + constexpr pair() + : first(), second() + { + } + + // implicit constructiable for this type + template ::value && + std::is_copy_constructible::value && + std::is_convertible::value && + std::is_convertible::value, int>::type = 0> + constexpr pair(const Ty1& a, const Ty2& b) + : first(a), second(b) + { + } + + // explicit constructible for this type + template ::value && + std::is_copy_constructible::value && + (!std::is_convertible::value || + !std::is_convertible::value), int>::type = 0> + explicit constexpr pair(const Ty1& a, const Ty2& b) + : first(a), second(b) + { + } + + pair(const pair& rhs) = default; + pair(pair&& rhs) = default; + + // implicit constructiable for other type + template ::value && + std::is_constructible::value && + std::is_convertible::value && + std::is_convertible::value, int>::type = 0> + constexpr pair(Other1&& a, Other2&& b) + : first(mystl::forward(a)), + second(mystl::forward(b)) + { + } + + // explicit constructiable for other type + template ::value && + std::is_constructible::value && + (!std::is_convertible::value || + !std::is_convertible::value), int>::type = 0> + explicit constexpr pair(Other1&& a, Other2&& b) + : first(mystl::forward(a)), + second(mystl::forward(b)) + { + } + + // implicit constructiable for other pair + template ::value && + std::is_constructible::value && + std::is_convertible::value && + std::is_convertible::value, int>::type = 0> + constexpr pair(const pair& other) + : first(other.first), + second(other.second) + { + } + + // explicit constructiable for other pair + template ::value && + std::is_constructible::value && + (!std::is_convertible::value || + !std::is_convertible::value), int>::type = 0> + explicit constexpr pair(const pair& other) + : first(other.first), + second(other.second) + { + } + + // implicit constructiable for other pair + template ::value && + std::is_constructible::value && + std::is_convertible::value && + std::is_convertible::value, int>::type = 0> + constexpr pair(pair&& other) + : first(mystl::forward(other.first)), + second(mystl::forward(other.second)) + { + } + + // explicit constructiable for other pair + template ::value && + std::is_constructible::value && + (!std::is_convertible::value || + !std::is_convertible::value), int>::type = 0> + explicit constexpr pair(pair&& other) + : first(mystl::forward(other.first)), + second(mystl::forward(other.second)) + { + } + + // copy assign for this pair + pair& operator=(const pair& rhs) + { + if (this != &rhs) + { + first = rhs.first; + second = rhs.second; + } + return *this; + } + + // move assign for this pair + pair& operator=(pair&& rhs) + { + if (this != &rhs) + { + first = mystl::move(rhs.first); + second = mystl::move(rhs.second); + } + return *this; + } + + // copy assign for other pair + template + pair& operator=(const pair& other) + { + first = other.first; + second = other.second; + return *this; + } + + // move assign for other pair + template + pair& operator=(pair&& other) + { + first = mystl::forward(other.first); + second = mystl::forward(other.second); + return *this; + } + + ~pair() = default; + + void swap(pair& other) + { + if (this != &other) + { + mystl::swap(first, other.first); + mystl::swap(second, other.second); + } + } + +}; + +// 重载比较操作符 +template +bool operator==(const pair& lhs, const pair& rhs) +{ + return lhs.first == rhs.first && lhs.second == rhs.second; +} + +template +bool operator<(const pair& lhs, const pair& rhs) +{ + return lhs.first < rhs.first || (lhs.first == rhs.first && lhs.second < rhs.second); +} + +template +bool operator!=(const pair& lhs, const pair& rhs) +{ + return !(lhs == rhs); +} + +template +bool operator>(const pair& lhs, const pair& rhs) +{ + return rhs < lhs; +} + +template +bool operator<=(const pair& lhs, const pair& rhs) +{ + return !(rhs < lhs); +} + +template +bool operator>=(const pair& lhs, const pair& rhs) +{ + return !(lhs < rhs); +} + +// 重载 mystl 的 swap +template +void swap(pair& lhs, pair& rhs) +{ + lhs.swap(rhs); +} + +// 全局函数,让两个数据成为一个 pair +template +pair make_pair(Ty1&& first, Ty2&& second) +{ + return pair(mystl::forward(first), mystl::forward(second)); +} + +} + +#endif // !MYTINYSTL_UTIL_H_ + diff --git a/src/MyTinySTL-master/MyTinySTL-master/MyTinySTL/vector.h b/src/MyTinySTL-master/MyTinySTL-master/MyTinySTL/vector.h new file mode 100755 index 0000000..5192761 --- /dev/null +++ b/src/MyTinySTL-master/MyTinySTL-master/MyTinySTL/vector.h @@ -0,0 +1,936 @@ +#ifndef MYTINYSTL_VECTOR_H_ +#define MYTINYSTL_VECTOR_H_ + +// 这个头文件包含一个模板类 vector +// vector : 向量 + +// notes: +// +// 异常保证: +// mystl::vecotr 满足基本异常保证,部分函数无异常保证,并对以下函数做强异常安全保证: +// * emplace +// * emplace_back +// * push_back +// 当 std::is_nothrow_move_assignable::value == true 时,以下函数也满足强异常保证: +// * reserve +// * resize +// * insert + +#include + +#include "iterator.h" +#include "memory.h" +#include "util.h" +#include "exceptdef.h" +#include "algo.h" + +namespace mystl +{ + +#ifdef max +#pragma message("#undefing marco max") +#undef max +#endif // max + +#ifdef min +#pragma message("#undefing marco min") +#undef min +#endif // min + +// 模板类: vector +// 模板参数 T 代表类型 +template +class vector +{ + static_assert(!std::is_same::value, "vector is abandoned in mystl"); +public: + // vector 的嵌套型别定义 + typedef mystl::allocator allocator_type; + typedef mystl::allocator data_allocator; + + typedef typename allocator_type::value_type value_type; + typedef typename allocator_type::pointer pointer; + typedef typename allocator_type::const_pointer const_pointer; + typedef typename allocator_type::reference reference; + typedef typename allocator_type::const_reference const_reference; + typedef typename allocator_type::size_type size_type; + typedef typename allocator_type::difference_type difference_type; + + typedef value_type* iterator; + typedef const value_type* const_iterator; + typedef mystl::reverse_iterator reverse_iterator; + typedef mystl::reverse_iterator const_reverse_iterator; + + allocator_type get_allocator() { return data_allocator(); } + +private: + iterator begin_; // 表示目前使用空间的头部 + iterator end_; // 表示目前使用空间的尾部 + iterator cap_; // 表示目前储存空间的尾部 + +public: + // 构造、复制、移动、析构函数 + vector() noexcept + { try_init(); } + + explicit vector(size_type n) + { fill_init(n, value_type()); } + + vector(size_type n, const value_type& value) + { fill_init(n, value); } + + template ::value, int>::type = 0> + vector(Iter first, Iter last) + { + MYSTL_DEBUG(!(last < first)); + range_init(first, last); + } + + vector(const vector& rhs) + { + range_init(rhs.begin_, rhs.end_); + } + + vector(vector&& rhs) noexcept + :begin_(rhs.begin_), + end_(rhs.end_), + cap_(rhs.cap_) + { + rhs.begin_ = nullptr; + rhs.end_ = nullptr; + rhs.cap_ = nullptr; + } + + vector(std::initializer_list ilist) + { + range_init(ilist.begin(), ilist.end()); + } + + vector& operator=(const vector& rhs); + vector& operator=(vector&& rhs) noexcept; + + vector& operator=(std::initializer_list ilist) + { + vector tmp(ilist.begin(), ilist.end()); + swap(tmp); + return *this; + } + + ~vector() + { + destroy_and_recover(begin_, end_, cap_ - begin_); + begin_ = end_ = cap_ = nullptr; + } + +public: + + // 迭代器相关操作 + iterator begin() noexcept + { return begin_; } + const_iterator begin() const noexcept + { return begin_; } + iterator end() noexcept + { return end_; } + const_iterator end() const noexcept + { return end_; } + + reverse_iterator rbegin() noexcept + { return reverse_iterator(end()); } + const_reverse_iterator rbegin() const noexcept + { return const_reverse_iterator(end()); } + reverse_iterator rend() noexcept + { return reverse_iterator(begin()); } + const_reverse_iterator rend() const noexcept + { return const_reverse_iterator(begin()); } + + const_iterator cbegin() const noexcept + { return begin(); } + const_iterator cend() const noexcept + { return end(); } + const_reverse_iterator crbegin() const noexcept + { return rbegin(); } + const_reverse_iterator crend() const noexcept + { return rend(); } + + // 容量相关操作 + bool empty() const noexcept + { return begin_ == end_; } + size_type size() const noexcept + { return static_cast(end_ - begin_); } + size_type max_size() const noexcept + { return static_cast(-1) / sizeof(T); } + size_type capacity() const noexcept + { return static_cast(cap_ - begin_); } + void reserve(size_type n); + void shrink_to_fit(); + + // 访问元素相关操作 + reference operator[](size_type n) + { + MYSTL_DEBUG(n < size()); + return *(begin_ + n); + } + const_reference operator[](size_type n) const + { + MYSTL_DEBUG(n < size()); + return *(begin_ + n); + } + reference at(size_type n) + { + THROW_OUT_OF_RANGE_IF(!(n < size()), "vector::at() subscript out of range"); + return (*this)[n]; + } + const_reference at(size_type n) const + { + THROW_OUT_OF_RANGE_IF(!(n < size()), "vector::at() subscript out of range"); + return (*this)[n]; + } + + reference front() + { + MYSTL_DEBUG(!empty()); + return *begin_; + } + const_reference front() const + { + MYSTL_DEBUG(!empty()); + return *begin_; + } + reference back() + { + MYSTL_DEBUG(!empty()); + return *(end_ - 1); + } + const_reference back() const + { + MYSTL_DEBUG(!empty()); + return *(end_ - 1); + } + + pointer data() noexcept { return begin_; } + const_pointer data() const noexcept { return begin_; } + + // 修改容器相关操作 + + // assign + + void assign(size_type n, const value_type& value) + { fill_assign(n, value); } + + template ::value, int>::type = 0> + void assign(Iter first, Iter last) + { + MYSTL_DEBUG(!(last < first)); + copy_assign(first, last, iterator_category(first)); + } + + void assign(std::initializer_list il) + { copy_assign(il.begin(), il.end(), mystl::forward_iterator_tag{}); } + + // emplace / emplace_back + + template + iterator emplace(const_iterator pos, Args&& ...args); + + template + void emplace_back(Args&& ...args); + + // push_back / pop_back + + void push_back(const value_type& value); + void push_back(value_type&& value) + { emplace_back(mystl::move(value)); } + + void pop_back(); + + // insert + + iterator insert(const_iterator pos, const value_type& value); + iterator insert(const_iterator pos, value_type&& value) + { return emplace(pos, mystl::move(value)); } + + iterator insert(const_iterator pos, size_type n, const value_type& value) + { + MYSTL_DEBUG(pos >= begin() && pos <= end()); + return fill_insert(const_cast(pos), n, value); + } + + template ::value, int>::type = 0> + void insert(const_iterator pos, Iter first, Iter last) + { + MYSTL_DEBUG(pos >= begin() && pos <= end() && !(last < first)); + copy_insert(const_cast(pos), first, last); + } + + // erase / clear + iterator erase(const_iterator pos); + iterator erase(const_iterator first, const_iterator last); + void clear() { erase(begin(), end()); } + + // resize / reverse + void resize(size_type new_size) { return resize(new_size, value_type()); } + void resize(size_type new_size, const value_type& value); + + void reverse() { mystl::reverse(begin(), end()); } + + // swap + void swap(vector& rhs) noexcept; + +private: + // helper functions + + // initialize / destroy + void try_init() noexcept; + + void init_space(size_type size, size_type cap); + + void fill_init(size_type n, const value_type& value); + template + void range_init(Iter first, Iter last); + + void destroy_and_recover(iterator first, iterator last, size_type n); + + // calculate the growth size + size_type get_new_cap(size_type add_size); + + // assign + + void fill_assign(size_type n, const value_type& value); + + template + void copy_assign(IIter first, IIter last, input_iterator_tag); + + template + void copy_assign(FIter first, FIter last, forward_iterator_tag); + + // reallocate + + template + void reallocate_emplace(iterator pos, Args&& ...args); + void reallocate_insert(iterator pos, const value_type& value); + + // insert + + iterator fill_insert(iterator pos, size_type n, const value_type& value); + template + void copy_insert(iterator pos, IIter first, IIter last); + + // shrink_to_fit + + void reinsert(size_type size); +}; + +/*****************************************************************************************/ + +// 复制赋值操作符 +template +vector& vector::operator=(const vector& rhs) +{ + if (this != &rhs) + { + const auto len = rhs.size(); + if (len > capacity()) + { + vector tmp(rhs.begin(), rhs.end()); + swap(tmp); + } + else if (size() >= len) + { + auto i = mystl::copy(rhs.begin(), rhs.end(), begin()); + data_allocator::destroy(i, end_); + end_ = begin_ + len; + } + else + { + mystl::copy(rhs.begin(), rhs.begin() + size(), begin_); + mystl::uninitialized_copy(rhs.begin() + size(), rhs.end(), end_); + cap_ = end_ = begin_ + len; + } + } + return *this; +} + +// 移动赋值操作符 +template +vector& vector::operator=(vector&& rhs) noexcept +{ + destroy_and_recover(begin_, end_, cap_ - begin_); + begin_ = rhs.begin_; + end_ = rhs.end_; + cap_ = rhs.cap_; + rhs.begin_ = nullptr; + rhs.end_ = nullptr; + rhs.cap_ = nullptr; + return *this; +} + +// 预留空间大小,当原容量小于要求大小时,才会重新分配 +template +void vector::reserve(size_type n) +{ + if (capacity() < n) + { + THROW_LENGTH_ERROR_IF(n > max_size(), + "n can not larger than max_size() in vector::reserve(n)"); + const auto old_size = size(); + auto tmp = data_allocator::allocate(n); + mystl::uninitialized_move(begin_, end_, tmp); + data_allocator::deallocate(begin_, cap_ - begin_); + begin_ = tmp; + end_ = tmp + old_size; + cap_ = begin_ + n; + } +} + +// 放弃多余的容量 +template +void vector::shrink_to_fit() +{ + if (end_ < cap_) + { + reinsert(size()); + } +} + +// 在 pos 位置就地构造元素,避免额外的复制或移动开销 +template +template +typename vector::iterator +vector::emplace(const_iterator pos, Args&& ...args) +{ + MYSTL_DEBUG(pos >= begin() && pos <= end()); + iterator xpos = const_cast(pos); + const size_type n = xpos - begin_; + if (end_ != cap_ && xpos == end_) + { + data_allocator::construct(mystl::address_of(*end_), mystl::forward(args)...); + ++end_; + } + else if (end_ != cap_) + { + auto new_end = end_; + data_allocator::construct(mystl::address_of(*end_), *(end_ - 1)); + ++new_end; + mystl::copy_backward(xpos, end_ - 1, end_); + *xpos = value_type(mystl::forward(args)...); + end_ = new_end; + } + else + { + reallocate_emplace(xpos, mystl::forward(args)...); + } + return begin() + n; +} + +// 在尾部就地构造元素,避免额外的复制或移动开销 +template +template +void vector::emplace_back(Args&& ...args) +{ + if (end_ < cap_) + { + data_allocator::construct(mystl::address_of(*end_), mystl::forward(args)...); + ++end_; + } + else + { + reallocate_emplace(end_, mystl::forward(args)...); + } +} + +// 在尾部插入元素 +template +void vector::push_back(const value_type& value) +{ + if (end_ != cap_) + { + data_allocator::construct(mystl::address_of(*end_), value); + ++end_; + } + else + { + reallocate_insert(end_, value); + } +} + +// 弹出尾部元素 +template +void vector::pop_back() +{ + MYSTL_DEBUG(!empty()); + data_allocator::destroy(end_ - 1); + --end_; +} + +// 在 pos 处插入元素 +template +typename vector::iterator +vector::insert(const_iterator pos, const value_type& value) +{ + MYSTL_DEBUG(pos >= begin() && pos <= end()); + iterator xpos = const_cast(pos); + const size_type n = pos - begin_; + if (end_ != cap_ && xpos == end_) + { + data_allocator::construct(mystl::address_of(*end_), value); + ++end_; + } + else if (end_ != cap_) + { + auto new_end = end_; + data_allocator::construct(mystl::address_of(*end_), *(end_ - 1)); + ++new_end; + auto value_copy = value; // 避免元素因以下复制操作而被改变 + mystl::copy_backward(xpos, end_ - 1, end_); + *xpos = mystl::move(value_copy); + end_ = new_end; + } + else + { + reallocate_insert(xpos, value); + } + return begin_ + n; +} + +// 删除 pos 位置上的元素 +template +typename vector::iterator +vector::erase(const_iterator pos) +{ + MYSTL_DEBUG(pos >= begin() && pos < end()); + iterator xpos = begin_ + (pos - begin()); + mystl::move(xpos + 1, end_, xpos); + data_allocator::destroy(end_ - 1); + --end_; + return xpos; +} + +// 删除[first, last)上的元素 +template +typename vector::iterator +vector::erase(const_iterator first, const_iterator last) +{ + MYSTL_DEBUG(first >= begin() && last <= end() && !(last < first)); + const auto n = first - begin(); + iterator r = begin_ + (first - begin()); + data_allocator::destroy(mystl::move(r + (last - first), end_, r), end_); + end_ = end_ - (last - first); + return begin_ + n; +} + +// 重置容器大小 +template +void vector::resize(size_type new_size, const value_type& value) +{ + if (new_size < size()) + { + erase(begin() + new_size, end()); + } + else + { + insert(end(), new_size - size(), value); + } +} + +// 与另一个 vector 交换 +template +void vector::swap(vector& rhs) noexcept +{ + if (this != &rhs) + { + mystl::swap(begin_, rhs.begin_); + mystl::swap(end_, rhs.end_); + mystl::swap(cap_, rhs.cap_); + } +} + +/*****************************************************************************************/ +// helper function + +// try_init 函数,若分配失败则忽略,不抛出异常 +template +void vector::try_init() noexcept +{ + try + { + begin_ = data_allocator::allocate(16); + end_ = begin_; + cap_ = begin_ + 16; + } + catch (...) + { + begin_ = nullptr; + end_ = nullptr; + cap_ = nullptr; + } +} + +// init_space 函数 +template +void vector::init_space(size_type size, size_type cap) +{ + try + { + begin_ = data_allocator::allocate(cap); + end_ = begin_ + size; + cap_ = begin_ + cap; + } + catch (...) + { + begin_ = nullptr; + end_ = nullptr; + cap_ = nullptr; + throw; + } +} + +// fill_init 函数 +template +void vector:: +fill_init(size_type n, const value_type& value) +{ + const size_type init_size = mystl::max(static_cast(16), n); + init_space(n, init_size); + mystl::uninitialized_fill_n(begin_, n, value); +} + +// range_init 函数 +template +template +void vector:: +range_init(Iter first, Iter last) +{ + const size_type len = mystl::distance(first, last); + const size_type init_size = mystl::max(len, static_cast(16)); + init_space(len, init_size); + mystl::uninitialized_copy(first, last, begin_); +} + +// destroy_and_recover 函数 +template +void vector:: +destroy_and_recover(iterator first, iterator last, size_type n) +{ + data_allocator::destroy(first, last); + data_allocator::deallocate(first, n); +} + +// get_new_cap 函数 +template +typename vector::size_type +vector:: +get_new_cap(size_type add_size) +{ + const auto old_size = capacity(); + THROW_LENGTH_ERROR_IF(old_size > max_size() - add_size, + "vector's size too big"); + if (old_size > max_size() - old_size / 2) + { + return old_size + add_size > max_size() - 16 + ? old_size + add_size : old_size + add_size + 16; + } + const size_type new_size = old_size == 0 + ? mystl::max(add_size, static_cast(16)) + : mystl::max(old_size + old_size / 2, old_size + add_size); + return new_size; +} + +// fill_assign 函数 +template +void vector:: +fill_assign(size_type n, const value_type& value) +{ + if (n > capacity()) + { + vector tmp(n, value); + swap(tmp); + } + else if (n > size()) + { + mystl::fill(begin(), end(), value); + end_ = mystl::uninitialized_fill_n(end_, n - size(), value); + } + else + { + erase(mystl::fill_n(begin_, n, value), end_); + } +} + +// copy_assign 函数 +template +template +void vector:: +copy_assign(IIter first, IIter last, input_iterator_tag) +{ + auto cur = begin_; + for (; first != last && cur != end_; ++first, ++cur) + { + *cur = *first; + } + if (first == last) + { + erase(cur, end_); + } + else + { + insert(end_, first, last); + } +} + +// 用 [first, last) 为容器赋值 +template +template +void vector:: +copy_assign(FIter first, FIter last, forward_iterator_tag) +{ + const size_type len = mystl::distance(first, last); + if (len > capacity()) + { + vector tmp(first, last); + swap(tmp); + } + else if (size() >= len) + { + auto new_end = mystl::copy(first, last, begin_); + data_allocator::destroy(new_end, end_); + end_ = new_end; + } + else + { + auto mid = first; + mystl::advance(mid, size()); + mystl::copy(first, mid, begin_); + auto new_end = mystl::uninitialized_copy(mid, last, end_); + end_ = new_end; + } +} + +// 重新分配空间并在 pos 处就地构造元素 +template +template +void vector:: +reallocate_emplace(iterator pos, Args&& ...args) +{ + const auto new_size = get_new_cap(1); + auto new_begin = data_allocator::allocate(new_size); + auto new_end = new_begin; + try + { + new_end = mystl::uninitialized_move(begin_, pos, new_begin); + data_allocator::construct(mystl::address_of(*new_end), mystl::forward(args)...); + ++new_end; + new_end = mystl::uninitialized_move(pos, end_, new_end); + } + catch (...) + { + data_allocator::deallocate(new_begin, new_size); + throw; + } + destroy_and_recover(begin_, end_, cap_ - begin_); + begin_ = new_begin; + end_ = new_end; + cap_ = new_begin + new_size; +} + +// 重新分配空间并在 pos 处插入元素 +template +void vector::reallocate_insert(iterator pos, const value_type& value) +{ + const auto new_size = get_new_cap(1); + auto new_begin = data_allocator::allocate(new_size); + auto new_end = new_begin; + const value_type& value_copy = value; + try + { + new_end = mystl::uninitialized_move(begin_, pos, new_begin); + data_allocator::construct(mystl::address_of(*new_end), value_copy); + ++new_end; + new_end = mystl::uninitialized_move(pos, end_, new_end); + } + catch (...) + { + data_allocator::deallocate(new_begin, new_size); + throw; + } + destroy_and_recover(begin_, end_, cap_ - begin_); + begin_ = new_begin; + end_ = new_end; + cap_ = new_begin + new_size; +} + +// fill_insert 函数 +template +typename vector::iterator +vector:: +fill_insert(iterator pos, size_type n, const value_type& value) +{ + if (n == 0) + return pos; + const size_type xpos = pos - begin_; + const value_type value_copy = value; // 避免被覆盖 + if (static_cast(cap_ - end_) >= n) + { // 如果备用空间大于等于增加的空间 + const size_type after_elems = end_ - pos; + auto old_end = end_; + if (after_elems > n) + { + mystl::uninitialized_copy(end_ - n, end_, end_); + end_ += n; + mystl::move_backward(pos, old_end - n, old_end); + mystl::uninitialized_fill_n(pos, n, value_copy); + } + else + { + end_ = mystl::uninitialized_fill_n(end_, n - after_elems, value_copy); + end_ = mystl::uninitialized_move(pos, old_end, end_); + mystl::uninitialized_fill_n(pos, after_elems, value_copy); + } + } + else + { // 如果备用空间不足 + const auto new_size = get_new_cap(n); + auto new_begin = data_allocator::allocate(new_size); + auto new_end = new_begin; + try + { + new_end = mystl::uninitialized_move(begin_, pos, new_begin); + new_end = mystl::uninitialized_fill_n(new_end, n, value); + new_end = mystl::uninitialized_move(pos, end_, new_end); + } + catch (...) + { + destroy_and_recover(new_begin, new_end, new_size); + throw; + } + data_allocator::deallocate(begin_, cap_ - begin_); + begin_ = new_begin; + end_ = new_end; + cap_ = begin_ + new_size; + } + return begin_ + xpos; +} + +// copy_insert 函数 +template +template +void vector:: +copy_insert(iterator pos, IIter first, IIter last) +{ + if (first == last) + return; + const auto n = mystl::distance(first, last); + if ((cap_ - end_) >= n) + { // 如果备用空间大小足够 + const auto after_elems = end_ - pos; + auto old_end = end_; + if (after_elems > n) + { + end_ = mystl::uninitialized_copy(end_ - n, end_, end_); + mystl::move_backward(pos, old_end - n, old_end); + mystl::uninitialized_copy(first, last, pos); + } + else + { + auto mid = first; + mystl::advance(mid, after_elems); + end_ = mystl::uninitialized_copy(mid, last, end_); + end_ = mystl::uninitialized_move(pos, old_end, end_); + mystl::uninitialized_copy(first, mid, pos); + } + } + else + { // 备用空间不足 + const auto new_size = get_new_cap(n); + auto new_begin = data_allocator::allocate(new_size); + auto new_end = new_begin; + try + { + new_end = mystl::uninitialized_move(begin_, pos, new_begin); + new_end = mystl::uninitialized_copy(first, last, new_end); + new_end = mystl::uninitialized_move(pos, end_, new_end); + } + catch (...) + { + destroy_and_recover(new_begin, new_end, new_size); + throw; + } + data_allocator::deallocate(begin_, cap_ - begin_); + begin_ = new_begin; + end_ = new_end; + cap_ = begin_ + new_size; + } +} + +// reinsert 函数 +template +void vector::reinsert(size_type size) +{ + auto new_begin = data_allocator::allocate(size); + try + { + mystl::uninitialized_move(begin_, end_, new_begin); + } + catch (...) + { + data_allocator::deallocate(new_begin, size); + throw; + } + data_allocator::deallocate(begin_, cap_ - begin_); + begin_ = new_begin; + end_ = begin_ + size; + cap_ = begin_ + size; +} + +/*****************************************************************************************/ +// 重载比较操作符 + +template +bool operator==(const vector& lhs, const vector& rhs) +{ + return lhs.size() == rhs.size() && + mystl::equal(lhs.begin(), lhs.end(), rhs.begin()); +} + +template +bool operator<(const vector& lhs, const vector& rhs) +{ + return mystl::lexicographical_compare(lhs.begin(), lhs.end(), rhs.begin(), rhs.end()); +} + +template +bool operator!=(const vector& lhs, const vector& rhs) +{ + return !(lhs == rhs); +} + +template +bool operator>(const vector& lhs, const vector& rhs) +{ + return rhs < lhs; +} + +template +bool operator<=(const vector& lhs, const vector& rhs) +{ + return !(rhs < lhs); +} + +template +bool operator>=(const vector& lhs, const vector& rhs) +{ + return !(lhs < rhs); +} + +// 重载 mystl 的 swap +template +void swap(vector& lhs, vector& rhs) +{ + lhs.swap(rhs); +} + +} // namespace mystl +#endif // !MYTINYSTL_VECTOR_H_ + diff --git a/src/MyTinySTL-master/MyTinySTL-master/README.md b/src/MyTinySTL-master/MyTinySTL-master/README.md new file mode 100755 index 0000000..333ec43 --- /dev/null +++ b/src/MyTinySTL-master/MyTinySTL-master/README.md @@ -0,0 +1,101 @@ +MyTinySTL +===== +[![Build Status](https://travis-ci.org/Alinshans/MyTinySTL.svg?branch=master)](https://travis-ci.org/Alinshans/MyTinySTL) [![Build Status](https://ci.appveyor.com/api/projects/status/github/Alinshans/MyTinySTL?branch=master&svg=true)](https://ci.appveyor.com/project/Alinshans/mytinystl) [![Release](https://img.shields.io/github/release/Alinshans/MyTinySTL.svg)](https://github.com/Alinshans/MyTinySTL/releases) [![License](https://img.shields.io/badge/License-MIT%20License-blue.svg)](https://opensource.org/licenses/MIT) [![Chat](https://img.shields.io/badge/chat-on%20gitter-FF6EB4.svg)](https://gitter.im/alinshans/MyTinySTL) + +## 简介 + 基于 `C++11` 的 `tinySTL`,这是我的第一个项目,使用了中文文档与中文注释,有不规范或不当的地方还请海涵。刚开始是作为新手练习用途,直到现在已经发布了 `2.x.x` 版本。实现了大部分 STL 中的容器与函数,但仍存在许多不足与 bug 。从 `2.x.x` 版本开始,本项目会进入长期维护的阶段,即基本不会增加新的内容,只修复发现的 bug。如发现错误,还请在 [`Issues`](https://github.com/Alinshans/MyTinySTL/issues) 中指出,欢迎 `Fork` 和 [`Pull requests`](https://github.com/Alinshans/MyTinySTL/pulls) 改善代码,谢谢! + +## 支持 + +* 操作系统 + * linux + * windows + * osx +* 编译器 + * g++ 5.4 或以上 + * clang++ 3.5 或以上 + * msvc 14.0 或以上 + +## 需要 + * 使用 cmake 2.8 来构建项目(**可选**) + +## 运行 + +如果你想要运行测试,请先阅读 [这个](https://github.com/Alinshans/MyTinySTL/blob/master/Test/README.md) 。 + + * gcc/clang on linux/osx + 1. 克隆仓库 +```bash +$ git clone git@github.com:Alinshans/MyTinySTL.git +$ cd MyTinySTL +``` + 2. 构建并运行 +```bash +$ mkdir build && cd build +$ cmake .. +$ make +$ cd ../bin && ./stltest +``` + + * msvc on windows + 1. 克隆仓库或 [Download ZIP](https://github.com/Alinshans/MyTinySTL/archive/master.zip) + 2. 使用 `vs2015`(或 `vs2017`)打开 `MSVC/MyTinySTL_VS2015.sln`,配置成 `Release` 模式,(Ctrl + F5)开始执行。 + +## 文档 + 见 [Wiki](https://github.com/Alinshans/MyTinySTL/wiki)。 + +## 测试 + 见 [Test](https://github.com/Alinshans/MyTinySTL/tree/master/Test)。 + +--- + +## Introduction + +This is a `tinySTL` based on `C++11`, which is my first project for practice. I use the Chinese documents and annotations for convenience, maybe there will be an English version later, but now I have no time to do that yet. Now I have released version `2.0.0`. I have achieved the vast majority of the containers and functions of `STL`, and there may be some deficiencies and bugs. From the version `2.x.x`, the project will enter the stage of long-term maintenance, i.e., I probably will not add new content but only fix bugs found. If you find any bugs, please point out that in [`Issues`](https://github.com/Alinshans/MyTinySTL/issues), or make a [`Pull requests`](https://github.com/Alinshans/MyTinySTL/pulls) to improve it, thanks! + +## Supported + +* os + * linux + * windows + * osx +* complier + * g++ 5.4 or later + * clang++ 3.5 or later + * msvc 14.0 or later + +## Required + +* Use cmake 2.8 to build this project (**Optional**) + +## Run test + +If you want to run the test, please read [this](https://github.com/Alinshans/MyTinySTL/blob/master/Test/README.md) first. + +* gcc/clang on linux/osx + +1. git clone +```bash +$ git clone git@github.com:Alinshans/MyTinySTL.git +$ cd MyTinySTL +``` +2. build and run +```bash +$ mkdir build && cd build +$ cmake .. +$ make +$ cd ../bin && ./stltest +``` + +* msvc on windows + +1. git clone or [Download ZIP](https://github.com/Alinshans/MyTinySTL/archive/master.zip) +2. use `vs2015`(or `vs2017`) open the file `MSVC/MyTinySTL_VS2015.sln`, configured in `Release`, run this project(Ctrl + F5). + +## Documents + +See [Wiki](https://github.com/Alinshans/MyTinySTL/wiki). + +## Test + +See [Test](https://github.com/Alinshans/MyTinySTL/tree/master/Test). diff --git a/src/MyTinySTL-master/MyTinySTL-master/Test/CMakeLists.txt b/src/MyTinySTL-master/MyTinySTL-master/Test/CMakeLists.txt new file mode 100755 index 0000000..aa01d4e --- /dev/null +++ b/src/MyTinySTL-master/MyTinySTL-master/Test/CMakeLists.txt @@ -0,0 +1,4 @@ +include_directories(${PROJECT_SOURCE_DIR}/MyTinySTL) +set(APP_SRC test.cpp) +set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin) +add_executable(stltest ${APP_SRC}) \ No newline at end of file diff --git a/src/MyTinySTL-master/MyTinySTL-master/Test/Lib/redbud/io/color.h b/src/MyTinySTL-master/MyTinySTL-master/Test/Lib/redbud/io/color.h new file mode 100755 index 0000000..e414bf7 --- /dev/null +++ b/src/MyTinySTL-master/MyTinySTL-master/Test/Lib/redbud/io/color.h @@ -0,0 +1,351 @@ +// ============================================================================ +// Copyright (c) 2017 Alinshans. All rights reserved. +// Licensed under the MIT License. See LICENSE for details. +// +// Header File : redbud/io/color.h +// +// This file is used to control font format and color in the terminal, which +// refers to a project on github, see https://github.com/agauniyal/rang . +// ============================================================================ + +#ifndef ALINSHANS_REDBUD_IO_COLOR_H_ +#define ALINSHANS_REDBUD_IO_COLOR_H_ + +#include "../platform.h" + +#if defined(REDBUD_LINUX) || defined(REDBUD_OSX) + #include // getenv + #include // strstr +#elif defined(REDBUD_WIN) + #include + #include +#endif + +#include +#include +#include + +namespace redbud +{ +namespace io +{ + +// ============================================================================ +// Enumerates the ANSI escape code corresponding to the font attributes. +// See https://en.wikipedia.org/wiki/ANSI_escape_code for details. +// +// Example: +// using namespace redbud::io; +// std::cout << fg::red << "This text has a red foreground color\n"; +// std::cout << bg::green << "This text has a green background color\n" +// ============================================================================ + +// Sets the text format, some of them is not widely supported. +enum class format +{ + reset = 0, // All attributes off. + bold = 1, // Bold or increased intensity. + faint = 2, // Faint (decreased intensity). + italic = 3, // Italian font. + underline = 4, // Underline. + blinkslow = 5, // Blink slowly. + blinkrapid = 6, // Blink quickly. + inverse = 7, // Swap foreground and background. + conceal = 8, // Hide the text. + strikeline = 9 // Characters legible, but marked for deletion. +}; + +// Sets the foreground color. +enum class fg +{ + black = 30, + red = 31, + green = 32, + yellow = 33, + blue = 34, + purple = 35, + cyan = 36, + white = 37, + reserve = 38, + reset = 39 +}; + +// Sets the background color. +enum class bg +{ + black = 40, + red = 41, + green = 42, + yellow = 43, + blue = 44, + purple = 45, + cyan = 46, + white = 47, + reserve = 38, + reset = 39 +}; + +// Sets the highlight foreground color. +enum class hfg +{ + black = 90, + red = 91, + green = 92, + yellow = 93, + blue = 94, + purple = 95, + cyan = 96, + white = 97 +}; + +// Sets the highlight background color. +enum class hbg +{ + black = 100, + red = 101, + green = 102, + yellow = 103, + blue = 104, + purple = 105, + cyan = 106, + white = 107 +}; + +// Sets the control state. +enum class state +{ + automatic = 0, // Automatic control. + manual = 1 // Manual control. +}; + +// ---------------------------------------------------------------------------- +// Details +namespace details +{ + +// Manages associated stream buffer. +inline const std::streambuf*& get_coutbuf() +{ + static const std::streambuf* pout = std::cout.rdbuf(); + return pout; +} + +inline const std::streambuf*& get_cerrbuf() +{ + static const std::streambuf* perr = std::cerr.rdbuf(); + return perr; +} + +inline const std::streambuf*& get_clogbuf() +{ + static const std::streambuf* plog = std::clog.rdbuf(); + return plog; +} + +// Gets an unique integer to use as index to iword() +inline int get_iword() +{ + static int i = std::ios_base::xalloc(); + return i; +} + +// Determines whether the terminal color of this system can be modified. +inline bool is_modifiable() +{ +#if defined(REDBUD_LINUX) || defined(REDBUD_OSX) + static constexpr const char* terms[] = { + "ansi", "color", "console", "cygwin", "gnome", "konsole", "kterm", + "linux", "msys", "putty", "rxvt", "screen", "vt100", "xterm" + }; + const char *penv = std::getenv("TERM"); + if (penv == nullptr) + { + return false; + } + bool result = false; + for (const auto& t : terms) + { + if (std::strstr(penv, t) != nullptr) + { + result = true; + break; + } + } + +#elif defined(REDBUD_WIN) + static constexpr bool result = true; +#endif + return result; +} + +/// Determines whether the buffer stream reaches the end. +inline bool is_terminal(const std::streambuf* buf) +{ + if (buf == get_coutbuf()) + { +#if defined(REDBUD_LINUX) || defined(REDBUD_OSX) + return isatty(fileno(stdout)) ? true : false; +#elif defined(REDBUD_WIN) + return _isatty(_fileno(stdout)) ? true : false; +#endif + } + + if (buf == get_cerrbuf() || buf == get_clogbuf()) + { +#if defined(REDBUD_LINUX) || defined(REDBUD_OSX) + return isatty(fileno(stderr)) ? true : false; +#elif defined(REDBUD_WIN) + return _isatty(_fileno(stderr)) ? true : false; +#endif + } + return false; +} + +// For overloading standard output stream. +template +using color_return_t = typename std::enable_if< + std::is_same::value || + std::is_same::value || + std::is_same::value || + std::is_same::value || + std::is_same::value, + std::ostream&>::type; + +template +using state_return_t = typename std::enable_if< + std::is_same::value, + std::ostream&>::type; + +// Sets the format and color of the text. +#if defined(REDBUD_LINUX) || defined(REDBUD_OSX) +template +inline color_return_t set_color(std::ostream& os, const T& value) +{ + return os << "\033[" << static_cast(value) << "m"; +} + +#elif defined(REDBUD_WIN) + +static constexpr WORD default_state = (FOREGROUND_BLUE | + FOREGROUND_GREEN | + FOREGROUND_RED); + +// Gets the corresponding RGB value on Windows. +inline WORD get_rgb(WORD rgb) +{ + static constexpr WORD cor[8] = { 0, 4, 2, 6, 1, 5, 3, 7 }; + return cor[rgb]; +} + +// Sets font attributes on Windows. +inline void set_attributes(redbud::io::fg color, WORD& state) +{ + if (color == redbud::io::fg::reserve) + { + return; + } + state &= 0xFFF0; + if (color == redbud::io::fg::reset) + { + state |= default_state; + return; + } + state |= get_rgb(static_cast(color) - 30); +} + +inline void set_attributes(redbud::io::bg color, WORD& state) +{ + if (color == redbud::io::bg::reserve) + { + return; + } + state &= 0xFF0F; + if (color == redbud::io::bg::reset) + { + return; + } + state |= get_rgb(static_cast(color) - 40) << 4; +} + +inline void set_attributes(redbud::io::hfg color, WORD& state) +{ + state &= 0xFFF0; + state |= (static_cast(0x8) | + get_rgb(static_cast(color) - 90)); +} + +inline void set_attributes(redbud::io::hbg color, WORD& state) +{ + state &= 0xFF0F; + state |= (static_cast(0x80) | + get_rgb(static_cast(color) - 100) << 4); +} + +inline void set_attributes(redbud::io::format format, WORD& state) +{ + if (format == redbud::io::format::reset) + { + state = default_state; + } +} + +inline WORD& current_state() +{ + static WORD state = default_state; + return state; +} + +inline HANDLE get_console_handle() +{ + static HANDLE h = GetStdHandle(STD_OUTPUT_HANDLE); + return h; +} + +template +inline color_return_t set_color(std::ostream& os, const T& value) +{ + HANDLE h = get_console_handle(); + if (h && is_terminal(os.rdbuf())) + { + set_attributes(value, current_state()); + SetConsoleTextAttribute(h, current_state()); + return os; + } + return os; +} +#endif + +} // namespace details + +// ---------------------------------------------------------------------------- +// Overloads standard output stream to control the color of text. + +template +inline details::color_return_t +operator<<(std::ostream& os, const T& value) +{ + return (os.iword(details::get_iword()) || + (details::is_modifiable() && + details::is_terminal(os.rdbuf()))) + ? details::set_color(os, value) + : os; +} + +template +inline details::state_return_t +operator<<(std::ostream& os, const T& value) +{ + if (value == redbud::io::state::automatic) + { + os.iword(details::get_iword()) = 0; + } + else if (value == redbud::io::state::manual) + { + os.iword(details::get_iword()) = 1; + } + return os; +} + +} // namespace io +} // namespace redbud +#endif // !ALINSHANS_REDBUD_IO_COLOR_H_ diff --git a/src/MyTinySTL-master/MyTinySTL-master/Test/Lib/redbud/platform.h b/src/MyTinySTL-master/MyTinySTL-master/Test/Lib/redbud/platform.h new file mode 100755 index 0000000..0a09b44 --- /dev/null +++ b/src/MyTinySTL-master/MyTinySTL-master/Test/Lib/redbud/platform.h @@ -0,0 +1,108 @@ +// ============================================================================ +// Copyright (c) 2017 Alinshans. All rights reserved. +// Licensed under the MIT License. See LICENSE for details. +// +// Header File : redbud/platform.h +// +// This file contains some preprocessing macros related to the platform. +// ============================================================================ + +#ifndef ALINSHANS_REDBUD_PLATFORM_H_ +#define ALINSHANS_REDBUD_PLATFORM_H_ + +// ---------------------------------------------------------------------------- +// os + +#if defined(WIN32) || defined(_WIN32) || defined(_WIN64) + #define REDBUD_WIN 1 +#elif defined(__unix__) || defined(__unix) || defined(__linux__) + #define REDBUD_LINUX 1 +#elif defined(__APPLE__) || defined(__MACH__) + #define REDBUD_OSX 1 +#else + #error "System that is not supported yet." +#endif + +// ---------------------------------------------------------------------------- +// complier + +#if defined(__clang__) + #define REDBUD_CLANG __clang__ +#elif defined(__GNUC__) + #define REDBUD_GNUC __GNUC__ +#elif defined(_MSC_VER) + #define REDBUD_MSVC _MSC_VER +#else + #error "Complier that is not supported yet." +#endif + +// ---------------------------------------------------------------------------- +// stringify + +#define REDBUD_TO_STRING(x) #x +#define REDBUD_STRING(x) REDBUD_TO_STRING(x) + +// ---------------------------------------------------------------------------- +// join + +#define REDBUD_DO_JOIN(x ,y) x##y +#define REDBUD_JOIN(x, y) REDBUD_DO_JOIN(x, y) + +// ---------------------------------------------------------------------------- +// version + +#define REDBUD_MAJOR 1 +#define REDBUD_MINOR 0 +#define REDBUD_PATCH 0 +#define REDBUD_VERSION \ + REDBUD_STRING(REDBUD_MAJOR.REDBUD_MINOR.REDBUD_PATCH) + +#define _VERSION_CODE(x,y,z) \ + (((x)*100000) + ((y)*100) + (z)) + +#define GNUC_VERSION \ + _VERSION_CODE(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__) + +#define CLANG_VERSION \ + _VERSION_CODE(__clang_major__, __clang_minor__, __clang_patchlevel__) + +// ---------------------------------------------------------------------------- +// redbud API + +#ifndef _REDBUD_API + #define _REDBUD_API ::redbud:: +#endif + +// ---------------------------------------------------------------------------- +// C++11 required + +#ifndef REDBUD_HAS_CXX11 + #if defined(REDBUD_MSVC) && (REDBUD_MSVC >= 1900) + #define REDBUD_HAS_CXX11 1 + #elif defined(REDBUD_GNUC) && (GNUC_VERSION >= _VERSION_CODE(4,8,0)) && \ + defined(__GXX_EXPERIMENTAL_CXX0X__) + #define REDBUD_HAS_CXX11 1 + #elif defined(REDBUD_CLANG) && (CLANG_VERSION >= _VERSION_CODE(3,3,0)) + #define REDBUD_HAS_CXX11 1 + #else + #define REDBUD_HAS_CXX11 0 + #endif +#endif // !REDBUD_HAS_CXX11 + +#if REDBUD_HAS_CXX11 == 0 + #error "C++11 required." +#endif + +// ---------------------------------------------------------------------------- +// Undefines macro min and max in MSVC. + +namespace redbud +{ + +#if REDBUD_MSVC + #define NOMINMAX +#endif + +} + +#endif // !ALINSHANS_REDBUD_PLATFORM_H_ diff --git a/src/MyTinySTL-master/MyTinySTL-master/Test/README.md b/src/MyTinySTL-master/MyTinySTL-master/Test/README.md new file mode 100755 index 0000000..1c6a1b5 --- /dev/null +++ b/src/MyTinySTL-master/MyTinySTL-master/Test/README.md @@ -0,0 +1,51 @@ +单元测试 (Unit test) +===== +## 测试环境 (Test environment) + 测试直接在 `Travis CI` 和 `AppVeyor` 上构建并运行,已在以下环境中做过测试: + + Tests were built and run directly on `Tracis CI` and `AppVeyor` and had been tested in the following environments: + + * linux, ubuntu 14.04, gcc5/6/7 + * osx, xcode5/6/7/8 + * windows, VS2015/VS2017, [x64|x86], [Release|Debug] + +## 测试框架 (Test frame) + 在 [test.h](https://github.com/Alinshans/MyTinySTL/blob/master/Test/test.h) 中,用了两个类实现了一个简单的测试框架,并定义了大量宏来封装测试过程。
+ In this file [test.h](https://github.com/Alinshans/MyTinySTL/blob/master/Test/test.h), I used two class to implement a simple test framework, and defined a lot of macros to package testing process. + +## 测试内容 (Test content) + 在 [test.h](https://github.com/Alinshans/MyTinySTL/blob/master/Test/test.h) 中定义了两个宏,`PERFORMANCE_TEST_ON` 和 `LARGER_TEST_DATA_ON`。`PERFORMANCE_TEST_ON` 代表开启性能测试,默认定义为 `1`。`LARGER_TEST_DATA_ON` 代表增大测试数据,默认定义为 `0`。**如果你想把 `LARGER_TEST_DATA_ON` 设置为 `1`,建议电脑配置为:处理器 i5 或以上,内存 8G 以上。**
+ In this file [test.h](https://github.com/Alinshans/MyTinySTL/blob/master/Test/test.h), I defined two marcos: `PERFORMANCE_TEST_ON` and `LARGER_TEST_DATA_ON`. `PERFORMANCE_TEST_ON` means to run performance test, the default is defined as `1`. `LARGER_TEST_DATA_ON` means to increase the test data, the default is defined as `0`. **If you want to set `LARGER_TEST_DATA_ON` to `1`, the proposed computer configuration is: CPU i5 or above, memory 8G or more.** + + 测试案例如下:
+ The test cases are as follows: + + * [algorithm](https://github.com/Alinshans/MyTinySTL/blob/master/Test/algorithm_test.h) *(100%/100%)* + * [algorithm_performance](https://github.com/Alinshans/MyTinySTL/blob/master/Test/algorithm_performance_test.h) *(100%/100%)* + * [deque](https://github.com/Alinshans/MyTinySTL/blob/master/Test/deque_test.h) *(100%/100%)* + * [list](https://github.com/Alinshans/MyTinySTL/blob/master/Test/list_test.h) *(100%/100%)* + * [map](https://github.com/Alinshans/MyTinySTL/blob/master/Test/map_test.h) *(100%/100%)* + * map + * multimap + * [queue](https://github.com/Alinshans/MyTinySTL/blob/master/Test/queue_test.h) *(100%/100%)* + * queue + * priority_queue + * [set](https://github.com/Alinshans/MyTinySTL/blob/master/Test/set_test.h) *(100%/100%)* + * set + * multiset + * [stack](https://github.com/Alinshans/MyTinySTL/blob/master/Test/stack_test.h) *(100%/100%)* + * [string_test](https://github.com/Alinshans/MyTinySTL/blob/master/Test/string_test.h) *(100%/100%)* + * [unordered_map](https://github.com/Alinshans/MyTinySTL/blob/master/Test/unordered_map_test.h) *(100%/100%)* + * unordered_map + * unordered_multimap + * [unordered_set](https://github.com/Alinshans/MyTinySTL/blob/master/Test/unordered_set_test.h) *(100%/100%)* + * unordered_set + * unordered_multiset + * [vector](https://github.com/Alinshans/MyTinySTL/blob/master/Test/vector_test.h) *(100%/100%)* + + +## 测试结果 (Test result) + 见 [Travis CI](https://travis-ci.org/Alinshans/MyTinySTL) 和 [AppVeyor](https://ci.appveyor.com/project/Alinshans/mytinystl)。 + + See [Travis CI](https://travis-ci.org/Alinshans/MyTinySTL) and [AppVeyor](https://ci.appveyor.com/project/Alinshans/mytinystl). + diff --git a/src/MyTinySTL-master/MyTinySTL-master/Test/algorithm_performance_test.h b/src/MyTinySTL-master/MyTinySTL-master/Test/algorithm_performance_test.h new file mode 100755 index 0000000..675e5b2 --- /dev/null +++ b/src/MyTinySTL-master/MyTinySTL-master/Test/algorithm_performance_test.h @@ -0,0 +1,108 @@ +#ifndef MYTINYSTL_ALGORITHM_PERFORMANCE_TEST_H_ +#define MYTINYSTL_ALGORITHM_PERFORMANCE_TEST_H_ + +// 仅仅针对 sort, binary_search 做了性能测试 + +#include + +#include "../MyTinySTL/algorithm.h" +#include "test.h" + +namespace mystl +{ +namespace test +{ +namespace algorithm_performance_test +{ + +// 函数性能测试宏定义 +#define FUN_TEST1(mode, fun, count) do { \ + std::string fun_name = #fun; \ + srand((int)time(0)); \ + char buf[10]; \ + clock_t start, end; \ + int *arr = new int[count]; \ + for(size_t i = 0; i < count; ++i) *(arr + i) = rand(); \ + start = clock(); \ + mode::fun(arr, arr + count); \ + end = clock(); \ + int n = static_cast(static_cast(end - start) \ + / CLOCKS_PER_SEC * 1000); \ + std::snprintf(buf, sizeof(buf), "%d", n); \ + std::string t = buf; \ + t += "ms |"; \ + std::cout << std::setw(WIDE) << t; \ + delete []arr; \ +} while(0) + +#define FUN_TEST2(mode, fun, count) do { \ + std::string fun_name = #fun; \ + srand((int)time(0)); \ + char buf[10]; \ + clock_t start, end; \ + int *arr = new int[count]; \ + for(size_t i = 0; i < count; ++i) *(arr + i) = rand(); \ + start = clock(); \ + for(size_t i = 0; i < count; ++i) \ + mode::fun(arr, arr + count, rand()); \ + end = clock(); \ + int n = static_cast(static_cast(end - start) \ + / CLOCKS_PER_SEC * 1000); \ + std::snprintf(buf, sizeof(buf), "%d", n); \ + std::string t = buf; \ + t += "ms |"; \ + std::cout << std::setw(WIDE) << t; \ + delete []arr; \ +} while(0) + +void binary_search_test() +{ + std::cout << "[------------------- function : binary_search ------------------]" << std::endl; + std::cout << "| orders of magnitude |"; + TEST_LEN(LEN1, LEN2, LEN3, WIDE); + std::cout << "| std |"; + FUN_TEST2(std, binary_search, LEN1); + FUN_TEST2(std, binary_search, LEN2); + FUN_TEST2(std, binary_search, LEN3); + std::cout << std::endl << "| mystl |"; + FUN_TEST2(mystl, binary_search, LEN1); + FUN_TEST2(mystl, binary_search, LEN2); + FUN_TEST2(mystl, binary_search, LEN3); + std::cout << std::endl; +} + +void sort_test() +{ + std::cout << "[----------------------- function : sort -----------------------]" << std::endl; + std::cout << "| orders of magnitude |"; + TEST_LEN(LEN1, LEN2, LEN3, WIDE); + std::cout << "| std |"; + FUN_TEST1(std, sort, LEN1); + FUN_TEST1(std, sort, LEN2); + FUN_TEST1(std, sort, LEN3); + std::cout << std::endl << "| mystl |"; + FUN_TEST1(mystl, sort, LEN1); + FUN_TEST1(mystl, sort, LEN2); + FUN_TEST1(mystl, sort, LEN3); + std::cout << std::endl; +} + +void algorithm_performance_test() +{ + +#if PERFORMANCE_TEST_ON + std::cout << "[===============================================================]" << std::endl; + std::cout << "[--------------- Run algorithm performance test ----------------]" << std::endl; + sort_test(); + binary_search_test(); + std::cout << "[--------------- End algorithm performance test ----------------]" << std::endl; + std::cout << "[===============================================================]" << std::endl; +#endif // PERFORMANCE_TEST_ON + +} + +} // namespace algorithm_performance_test +} // namespace test +} // namespace mystl +#endif // !MYTINYSTL_ALGORITHM_PERFORMANCE_TEST_H_ + diff --git a/src/MyTinySTL-master/MyTinySTL-master/Test/algorithm_test.h b/src/MyTinySTL-master/MyTinySTL-master/Test/algorithm_test.h new file mode 100755 index 0000000..92eccdc --- /dev/null +++ b/src/MyTinySTL-master/MyTinySTL-master/Test/algorithm_test.h @@ -0,0 +1,1180 @@ +#ifndef MYTINYSTL_ALGORITHM_TEST_H_ +#define MYTINYSTL_ALGORITHM_TEST_H_ + +// 算法测试: 包含了 mystl 的 81 个算法测试 + +#include +#include +#include + +#include "../MyTinySTL/algorithm.h" +#include "../MyTinySTL/vector.h" +#include "test.h" + +namespace mystl +{ +namespace test +{ + +#ifdef max +#pragma message("#undefing marco max") +#undef max +#endif // max + +#ifdef min +#pragma message("#undefing marco min") +#undef min +#endif // min + +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable: 4389) +#endif // _MSC_VER + +namespace algorithm_test +{ + +// 一些可能会用到的辅助数据和函数 +int for_each_sum = 0; + +int gen() { return 5; } +int r(int i) { return (i * 5 + 1) % 9; } +bool is_odd(int i) { return i & 1; } +bool is_even(int i) { return !(i & 1); } +void arr_sum(int i) { for_each_sum += i; } +bool cmp(const int& a, const int& b) { return b < a; } +int unary_op(const int& x) { return x + 1; } +int binary_op(const int& x, const int& y) { return x + y; } + +// 以下为 80 个函数的简单测试 + +// algobase test: +TEST(copy_test) +{ + int arr1[] = { 1,2,3,4,5,6,7,8,9,10 }; + int exp[5], act[5]; + std::copy(arr1, arr1 + 5, exp); + mystl::copy(arr1, arr1 + 5, act); + EXPECT_CON_EQ(exp, act); + std::copy(arr1 + 5, arr1 + 10, exp); + mystl::copy(arr1 + 5, arr1 + 10, act); + EXPECT_CON_EQ(exp, act); +} + +TEST(copy_backward_test) +{ + int arr1[] = { 1,2,3,4,5 }; + std::vector exp{ 0,0,0,0,0,6,7,8,9,10 }; + int act[] = { 0,0,0,0,0,6,7,8,9,10 }; + std::copy_backward(arr1, arr1 + 5, exp.begin() + 5); + mystl::copy_backward(arr1, arr1 + 5, act + 5); + EXPECT_CON_EQ(exp, act); + std::copy_backward(exp.begin(), exp.begin() + 8, exp.begin() + 9); + mystl::copy_backward(act, act + 8, act + 9); + EXPECT_CON_EQ(exp, act); +} + +TEST(copy_if_test) +{ + int arr1[] = { 1,2,3,4,5,6,7,8,9,10 }; + int exp[5], act[5]; + std::copy_if(arr1, arr1 + 10, exp, is_odd); + mystl::copy_if(arr1, arr1 + 10, act, is_odd); + EXPECT_CON_EQ(exp, act); + std::copy_if(arr1, arr1 + 10, exp, is_even); + mystl::copy_if(arr1, arr1 + 10, act, is_even); + EXPECT_CON_EQ(exp, act); +} + +TEST(copy_n_test) +{ + int arr1[] = { 1,2,3,4,5,6,7,8,9,10 }; + int exp[10], act[10]; + std::copy_n(arr1, 10, exp); + mystl::copy_n(arr1, 10, act); + EXPECT_CON_EQ(exp, act); + std::copy_n(arr1 + 5, 5, exp); + mystl::copy_n(arr1 + 5, 5, act); + EXPECT_CON_EQ(exp, act); +} + +TEST(move_test) +{ + int arr1[] = { 1,2,3,4,5 }; + int arr2[] = { 1,2,3,4,5 }; + int exp[5], act[5]; + std::move(arr1, arr1 + 5, exp); + mystl::move(arr2, arr2 + 5, act); + EXPECT_CON_EQ(exp, act); + EXPECT_CON_EQ(arr1, arr2); +} + +TEST(move_backward_test) +{ + int arr1[] = { 1,2,3,4,5 }; + int arr2[] = { 1,2,3,4,5 }; + int exp[5], act[5]; + std::move_backward(arr1, arr1 + 5, exp + 5); + mystl::move_backward(arr2, arr2 + 5, act + 5); + EXPECT_CON_EQ(exp, act); + EXPECT_CON_EQ(arr1, arr2); +} + +TEST(equal_test) +{ + std::vector v1{ 1,2,3,4,5 }; + std::vector v2{ 1,2,3,4,5,6 }; + int arr1[] = { 1,2,3,4,5 }; + int arr2[] = { 1,2,3,4,6 }; + EXPECT_EQ(std::equal(v1.begin(), v1.end(), v2.begin()), + mystl::equal(v1.begin(), v1.end(), v2.begin())); + EXPECT_EQ(std::equal(arr1, arr1 + 5, arr2), + mystl::equal(arr1, arr1 + 5, arr2)); + EXPECT_EQ(std::equal(v1.begin(), v1.end(), arr1), + mystl::equal(v1.begin(), v1.end(), arr1)); + EXPECT_EQ(std::equal(v1.begin(), v1.end(), arr2, std::equal_to()), + mystl::equal(v1.begin(), v1.end(), arr2, std::equal_to())); +} + +TEST(fill_test) +{ + int exp[10], act[10]; + mystl::vector v1(10, 1); + mystl::vector v2(10, 2); + std::fill(exp, exp + 10, 1); + mystl::fill(act, act + 10, 1); + EXPECT_CON_EQ(exp, act); + std::fill(v1.begin(), v1.end(), 3); + mystl::fill(v2.begin(), v2.end(), 3); + EXPECT_CON_EQ(v1, v2); +} + +TEST(fill_n_test) +{ + int arr1[5]; + int arr2[5]; + std::fill_n(arr2, 5, 1); + mystl::fill_n(arr1, 5, 1); + EXPECT_CON_EQ(arr1, arr2); + std::fill_n(arr1 + 2, 3, 2); + mystl::fill_n(arr2 + 2, 3, 2); + EXPECT_CON_EQ(arr1, arr2); +} + +TEST(iter_swap_test) +{ + int a = 1; + int b = 2; + int *p1 = &a; + int *p2 = &b; + int *p3 = &a; + int *p4 = &b; + std::iter_swap(p1, p2); + mystl::iter_swap(p3, p4); + EXPECT_PTR_EQ(p1, p3); + EXPECT_PTR_EQ(p2, p4); + EXPECT_EQ(p1, p3); + EXPECT_EQ(p2, p4); +} + +TEST(lexicographical_compare_test) +{ + int arr1[] = { 1,2,3,4,5 }; + int arr2[] = { 0,2,4,6,8 }; + int arr3[] = { 1,2,3,4,5 }; + int arr4[] = { 1,2,3,4,5,6 }; + int arr5[] = { 2,3,4 }; + EXPECT_EQ(std::lexicographical_compare(arr1, arr1 + 5, arr2, arr2 + 5), + mystl::lexicographical_compare(arr1, arr1 + 5, arr2, arr2 + 5)); + EXPECT_EQ(std::lexicographical_compare(arr1, arr1 + 5, arr3, arr3 + 5), + mystl::lexicographical_compare(arr1, arr1 + 5, arr3, arr3 + 5)); + EXPECT_EQ(std::lexicographical_compare(arr1, arr1 + 5, arr4, arr4 + 6, std::less()), + mystl::lexicographical_compare(arr1, arr1 + 5, arr4, arr4 + 6, std::less())); + EXPECT_EQ(std::lexicographical_compare(arr1, arr1 + 5, arr5, arr5 + 3, std::less()), + mystl::lexicographical_compare(arr1, arr1 + 5, arr5, arr5 + 3, std::less())); +} + +TEST(max_test) +{ + int i1 = 1, i2 = 2; + double d1 = 1.1, d2 = 2.2; + char c1 = 'a', c2 = 'b'; + EXPECT_EQ(std::max(i1, i2), mystl::max(i1, i2)); + EXPECT_EQ(std::max(d1, d2), mystl::max(d1, d2)); + EXPECT_EQ(std::max(c1, c2), mystl::max(c1, c2)); +} + +TEST(min_test) +{ + int i1 = 1, i2 = 2; + double d1 = 1.1, d2 = 2.2; + char c1 = 'a', c2 = 'b'; + EXPECT_EQ(std::min(i1, i2), mystl::min(i1, i2)); + EXPECT_EQ(std::min(d1, d2), mystl::min(d1, d2)); + EXPECT_EQ(std::min(c1, c2), mystl::min(c1, c2)); +} + +TEST(mismatch_test) +{ + int arr1[] = { 1,1,2,2,3,4,5 }; + int arr2[] = { 1,1,2,2,3,3,3 }; + int arr3[] = { 0,1,2,2,3,4,5 }; + int arr4[] = { 1,1,2,2,3,4,5 }; + auto p1 = std::mismatch(arr1, arr1 + 7, arr2); + auto p2 = mystl::mismatch(arr1, arr1 + 7, arr2); + auto p3 = std::mismatch(arr1, arr1 + 7, arr3); + auto p4 = mystl::mismatch(arr1, arr1 + 7, arr3); + auto p5 = std::mismatch(arr1, arr1 + 7, arr4, std::equal_to()); + auto p6 = mystl::mismatch(arr1, arr1 + 7, arr4, std::equal_to()); + EXPECT_EQ(p1.first, p2.first); + EXPECT_EQ(p1.second, p2.second); + EXPECT_EQ(p3.first, p4.first); + EXPECT_EQ(p3.second, p4.second); + EXPECT_EQ(p5.first, p6.first); + EXPECT_EQ(p5.second, p6.second); +} + +// heap_algo test +TEST(make_heap_test) +{ + int arr1[] = { 1,2,3,4,5,6,7,8,9 }; + int arr2[] = { 1,2,3,4,5,6,7,8,9 }; + int arr3[] = { 2,1,6,5,4,9,8,7,6 }; + int arr4[] = { 2,1,6,5,4,9,8,7,6 }; + int arr5[] = { 1,1,2,2,3,3,4,4,5,5 }; + int arr6[] = { 1,1,2,2,3,3,4,4,5,5 }; + std::make_heap(arr1, arr1 + 9); + mystl::make_heap(arr2, arr2 + 9); + std::make_heap(arr3, arr3 + 9); + mystl::make_heap(arr4, arr4 + 9); + std::make_heap(arr5, arr5 + 10, std::greater()); + mystl::make_heap(arr6, arr6 + 10, std::greater()); + EXPECT_CON_EQ(arr1, arr2); + EXPECT_CON_EQ(arr3, arr4); + EXPECT_CON_EQ(arr5, arr6); +} + +TEST(pop_heap_test) +{ + int arr1[] = { 1,2,3,4,5,6,7,8,9 }; + int arr2[] = { 1,2,3,4,5,6,7,8,9 }; + std::make_heap(arr1, arr1 + 9); + std::make_heap(arr2, arr2 + 9); + for (int i = 9; i > 0; --i) + { + std::pop_heap(arr1, arr1 + i); + mystl::pop_heap(arr2, arr2 + i); + EXPECT_CON_EQ(arr1, arr2); + } + int arr3[] = { 1,2,3,4,5,6,7,8,9 }; + int arr4[] = { 1,2,3,4,5,6,7,8,9 }; + std::make_heap(arr3, arr3 + 9, std::greater()); + std::make_heap(arr4, arr4 + 9, std::greater()); + std::pop_heap(arr3, arr3 + 9, std::greater()); + mystl::pop_heap(arr4, arr4 + 9, std::greater()); + EXPECT_CON_EQ(arr3, arr4); +} + +TEST(push_heap_test) +{ + int arr1[] = { 1,2,3,4,5,6,7,8,9 }; + int arr2[] = { 1,2,3,4,5,6,7,8,9 }; + std::make_heap(arr1, arr1 + 4); + std::make_heap(arr2, arr2 + 4); + for (int i = 4; i <= 9; ++i) + { + std::push_heap(arr1, arr1 + i); + mystl::push_heap(arr2, arr2 + i); + EXPECT_CON_EQ(arr1, arr2); + } + int arr3[] = { 1,2,3,4,5,6,7,8,9 }; + int arr4[] = { 1,2,3,4,5,6,7,8,9 }; + std::make_heap(arr3, arr3 + 9, std::greater()); + std::make_heap(arr4, arr4 + 9, std::greater()); + std::push_heap(arr3, arr3 + 9, std::greater()); + mystl::push_heap(arr4, arr4 + 9, std::greater()); + EXPECT_CON_EQ(arr3, arr4); +} + +TEST(sort_heap_test) +{ + int arr1[] = { 1,2,3,4,5,6,7,8,9 }; + int arr2[] = { 1,2,3,4,5,6,7,8,9 }; + int arr3[] = { 1,2,3,4,5,6,7,8,9 }; + int arr4[] = { 1,2,3,4,5,6,7,8,9 }; + std::make_heap(arr1, arr1 + 9); + std::make_heap(arr2, arr2 + 9); + std::make_heap(arr3, arr3 + 9, std::greater()); + std::make_heap(arr4, arr4 + 9, std::greater()); + std::sort_heap(arr1, arr1 + 9); + mystl::sort_heap(arr2, arr2 + 9); + std::sort_heap(arr3, arr3 + 9, std::greater()); + mystl::sort_heap(arr4, arr4 + 9, std::greater()); + EXPECT_CON_EQ(arr1, arr2); + EXPECT_CON_EQ(arr3, arr4); +} + +// set_algo test +TEST(set_difference_test) +{ + int arr1[] = { 1,2,3,4,5,6,7,8,9 }; + int arr2[] = { 1,2,3,4,5,6 }; + int arr3[] = { 1,2,3 }; + int exp[6] = { 0 }, act[6] = { 0 }; + std::set_difference(arr1, arr1 + 9, arr2, arr2 + 6, exp); + mystl::set_difference(arr1, arr1 + 9, arr2, arr2 + 6, act); + EXPECT_CON_EQ(exp, act); + std::set_difference(arr2, arr2 + 6, arr3, arr3 + 3, exp); + mystl::set_difference(arr2, arr2 + 6, arr3, arr3 + 3, act); + EXPECT_CON_EQ(exp, act); + std::set_difference(arr1, arr1 + 9, arr3, arr3 + 3, exp, std::less()); + mystl::set_difference(arr1, arr1 + 9, arr3, arr3 + 3, act, std::less()); + EXPECT_CON_EQ(exp, act); +} + +TEST(set_intersection_test) +{ + int arr1[] = { 1,2,3,4,5,6,7,8,9 }; + int arr2[] = { 1,2,3,4,5,6 }; + int arr3[] = { 1,2,3 }; + int exp[9] = { 0 }, act[9] = { 0 }; + std::set_intersection(arr1, arr1 + 9, arr2, arr2 + 6, exp); + mystl::set_intersection(arr1, arr1 + 9, arr2, arr2 + 6, act); + EXPECT_CON_EQ(exp, act); + std::set_intersection(arr2, arr2 + 6, arr3, arr3 + 3, exp); + mystl::set_intersection(arr2, arr2 + 6, arr3, arr3 + 3, act); + EXPECT_CON_EQ(exp, act); + std::set_intersection(arr1, arr1 + 9, arr3, arr3 + 3, exp, std::less()); + mystl::set_intersection(arr1, arr1 + 9, arr3, arr3 + 3, act, std::less()); + EXPECT_CON_EQ(exp, act); +} + +TEST(set_symmetric_difference_test) +{ + int arr1[] = { 1,2,3,4,5 }; + int arr2[] = { 1,3,5,7,9 }; + int arr3[] = { 2,4,6,8,10 }; + int exp[10] = { 0 }, act[10] = { 0 }; + std::set_symmetric_difference(arr1, arr1 + 5, arr2, arr2 + 5, exp); + mystl::set_symmetric_difference(arr1, arr1 + 5, arr2, arr2 + 5, act); + EXPECT_CON_EQ(exp, act); + std::set_symmetric_difference(arr1, arr1 + 5, arr3, arr3 + 5, exp); + mystl::set_symmetric_difference(arr1, arr1 + 5, arr3, arr3 + 5, act); + EXPECT_CON_EQ(exp, act); + std::set_symmetric_difference(arr2, arr2 + 5, arr3, arr3 + 5, exp, std::less()); + mystl::set_symmetric_difference(arr2, arr2 + 5, arr3, arr3 + 5, act, std::less()); + EXPECT_CON_EQ(exp, act); +} + +TEST(set_union_test) +{ + int arr1[] = { 1,2,3,4,5 }; + int arr2[] = { 1,3,5,7,9 }; + int arr3[] = { 2,4,6,8,10 }; + int exp[10] = { 0 }, act[10] = { 0 }; + std::set_union(arr1, arr1 + 5, arr2, arr2 + 5, exp); + mystl::set_union(arr1, arr1 + 5, arr2, arr2 + 5, act); + EXPECT_CON_EQ(exp, act); + std::set_union(arr1, arr1 + 5, arr3, arr3 + 5, exp); + mystl::set_union(arr1, arr1 + 5, arr3, arr3 + 5, act); + EXPECT_CON_EQ(exp, act); + std::set_union(arr2, arr2 + 5, arr3, arr3 + 5, exp, std::less()); + mystl::set_union(arr2, arr2 + 5, arr3, arr3 + 5, act, std::less()); + EXPECT_CON_EQ(exp, act); +} + +// numeric test +TEST(accumulate_test) +{ + int arr1[] = { 1,2,3,4,5 }; + EXPECT_EQ(std::accumulate(arr1, arr1 + 5, 0), + mystl::accumulate(arr1, arr1 + 5, 0)); + EXPECT_EQ(std::accumulate(arr1, arr1 + 5, 5), + mystl::accumulate(arr1, arr1 + 5, 5)); + EXPECT_EQ(std::accumulate(arr1, arr1 + 5, 0, std::minus()), + mystl::accumulate(arr1, arr1 + 5, 0, std::minus())); +} + +TEST(adjacent_difference_test) +{ + int arr1[] = { 1,2,3,4,5 }; + int arr2[] = { 1,1,1,1,1 }; + int exp[5], act[5]; + std::adjacent_difference(arr1, arr1 + 5, exp); + mystl::adjacent_difference(arr1, arr1 + 5, act); + EXPECT_CON_EQ(exp, act); + std::adjacent_difference(arr2, arr2 + 5, exp, std::minus()); + mystl::adjacent_difference(arr2, arr2 + 5, act, std::minus()); + EXPECT_CON_EQ(exp, act); +} + +TEST(inner_product_test) +{ + int arr1[] = { 1,1,1,1,1 }; + int arr2[] = { 2,2,2,2,2 }; + int arr3[] = { 1,2,3,4,5 }; + EXPECT_EQ(std::inner_product(arr1, arr1 + 5, arr3, 0), + mystl::inner_product(arr1, arr1 + 5, arr3, 0)); + EXPECT_EQ(std::inner_product(arr2, arr2 + 5, arr3, 0, std::minus(), std::multiplies()), + mystl::inner_product(arr2, arr2 + 5, arr3, 0, std::minus(), std::multiplies())); +} + +TEST(iota_test) +{ + int arr1[10]; + int arr2[10]; + std::iota(arr1, arr1 + 10, 1); + mystl::iota(arr2, arr2 + 10, 1); + EXPECT_CON_EQ(arr1, arr2); + std::iota(arr1, arr1 + 10, -1); + mystl::iota(arr2, arr2 + 10, -1); + EXPECT_CON_EQ(arr1, arr2); +} + +TEST(partial_sum_test) +{ + int arr1[] = { 1,2,3,4,5,6,7,8,9 }; + int exp1[5], act1[5]; + int exp2[9], act2[9]; + std::partial_sum(arr1, arr1 + 5, exp1); + mystl::partial_sum(arr1, arr1 + 5, act1); + std::partial_sum(arr1, arr1 + 9, exp2); + mystl::partial_sum(arr1, arr1 + 9, act2); + EXPECT_CON_EQ(exp1, act1); + EXPECT_CON_EQ(exp2, act2); + std::partial_sum(arr1, arr1 + 9, exp2, std::multiplies()); + mystl::partial_sum(arr1, arr1 + 9, act2, std::multiplies()); + EXPECT_CON_EQ(exp2, act2); +} + +// algo test +TEST(adjacent_find_test) +{ + int arr1[] = { 1,2,3,3,4 }; + int arr2[] = { 1,2,3,4,5 }; + EXPECT_EQ(std::adjacent_find(arr1, arr1 + 5), + mystl::adjacent_find(arr1, arr1 + 5)); + EXPECT_EQ(std::adjacent_find(arr2, arr2 + 5), + mystl::adjacent_find(arr2, arr2 + 5)); + EXPECT_EQ(std::adjacent_find(arr1, arr1 + 5, std::greater()), + mystl::adjacent_find(arr1, arr1 + 5, std::greater())); +} + +TEST(all_of_test) +{ + int arr1[] = { 1,3,5,7,9 }; + int arr2[] = { 1,3,5,7,8 }; + EXPECT_EQ(std::all_of(arr1, arr1 + 5, is_odd), + mystl::all_of(arr1, arr1 + 5, is_odd)); + EXPECT_EQ(std::all_of(arr2, arr2 + 5, is_odd), + mystl::all_of(arr2, arr2 + 5, is_odd)); +} + +TEST(any_of_test) +{ + int arr1[] = { 1,2,4,6,8 }; + int arr2[] = { 2,4,6,8,10 }; + EXPECT_EQ(std::any_of(arr1, arr1 + 5, is_odd), + mystl::any_of(arr1, arr1 + 5, is_odd)); + EXPECT_EQ(std::any_of(arr2, arr2 + 5, is_odd), + mystl::any_of(arr2, arr2 + 5, is_odd)); +} + +TEST(binary_search_test) +{ + int arr1[] = { 1,2,3,4,5 }; + EXPECT_EQ(std::binary_search(arr1, arr1 + 5, 1), + mystl::binary_search(arr1, arr1 + 5, 1)); + EXPECT_EQ(std::binary_search(arr1, arr1 + 5, 6), + mystl::binary_search(arr1, arr1 + 5, 6)); +} + +TEST(count_test) +{ + int arr1[] = { 1,2,2,3,3,3,4,5,8 }; + EXPECT_EQ(std::count(arr1, arr1 + 9, 2), + mystl::count(arr1, arr1 + 9, 2)); + EXPECT_EQ(std::count(arr1, arr1 + 9, 3), + mystl::count(arr1, arr1 + 9, 3)); + EXPECT_EQ(std::count(arr1, arr1 + 9, 6), + mystl::count(arr1, arr1 + 9, 6)); +} + +TEST(count_if_test) +{ + int arr1[] = { 1,2,2,3,3,3,4,5,8 }; + EXPECT_EQ(std::count_if(arr1, arr1 + 9, is_odd), + mystl::count_if(arr1, arr1 + 9, is_odd)); + EXPECT_EQ(std::count_if(arr1, arr1 + 9, is_even), + mystl::count_if(arr1, arr1 + 9, is_even)); +} + +TEST(equal_range_test) +{ + int arr1[] = { 1,2,3,3,3,4,5 }; + auto p1 = mystl::equal_range(arr1, arr1 + 7, 3); + auto p2 = std::equal_range(arr1, arr1 + 7, 3); + auto p3 = mystl::equal_range(arr1, arr1 + 7, 6, std::equal_to()); + auto p4 = std::equal_range(arr1, arr1 + 7, 6, std::equal_to()); + EXPECT_EQ(p2.first, p1.first); + EXPECT_EQ(p2.second, p1.second); + EXPECT_EQ(p4.first, p3.first); + EXPECT_EQ(p4.second, p3.second); +} + +TEST(find_test) +{ + int arr1[] = { 1,2,3,4,5 }; + EXPECT_EQ(std::find(arr1, arr1 + 5, 3), mystl::find(arr1, arr1 + 5, 3)); + EXPECT_EQ(std::find(arr1, arr1 + 5, 6), mystl::find(arr1, arr1 + 5, 6)); +} + +TEST(find_end_test) +{ + int arr1[] = { 1,2,3,2,2,3,4,5 }; + int arr2[] = { 2,3 }; + int arr3[] = { 4,5,6 }; + EXPECT_EQ(std::find_end(arr1, arr1 + 8, arr2, arr2 + 1), + mystl::find_end(arr1, arr1 + 8, arr2, arr2 + 1)); + EXPECT_EQ(std::find_end(arr1, arr1 + 8, arr3, arr3 + 2), + mystl::find_end(arr1, arr1 + 8, arr3, arr3 + 2)); + EXPECT_EQ(std::find_end(arr1, arr1 + 8, arr3, arr3 + 2), + mystl::find_end(arr1, arr1 + 8, arr3, arr3 + 2)); + EXPECT_EQ(std::find_end(arr1, arr1 + 8, arr3, arr3, std::less()), + mystl::find_end(arr1, arr1 + 8, arr3, arr3, std::less())); +} + +TEST(find_first_of_test) +{ + int arr1[] = { 1,2,3,4,5 }; + int arr2[] = { 2,3,4 }; + int arr3[] = { 6,7,8 }; + EXPECT_EQ(std::find_first_of(arr1, arr1 + 5, arr2, arr2 + 3), + mystl::find_first_of(arr1, arr1 + 5, arr2, arr2 + 3)); + EXPECT_EQ(std::find_first_of(arr1, arr1 + 5, arr3, arr3 + 3, std::equal_to()), + mystl::find_first_of(arr1, arr1 + 5, arr3, arr3 + 3, std::equal_to())); +} + +TEST(find_if_test) +{ + int arr1[] = { 1,2,3,4,5 }; + EXPECT_EQ(std::find_if(arr1, arr1 + 5, is_odd), + mystl::find_if(arr1, arr1 + 5, is_odd)); + EXPECT_EQ(std::find_if(arr1, arr1 + 5, is_even), + mystl::find_if(arr1, arr1 + 5, is_even)); +} + +TEST(find_if_not_test) +{ + int arr1[] = { 1,2,3,4,5 }; + EXPECT_EQ(std::find_if_not(arr1, arr1 + 5, is_odd), + mystl::find_if_not(arr1, arr1 + 5, is_odd)); + EXPECT_EQ(std::find_if_not(arr1, arr1 + 5, is_even), + mystl::find_if_not(arr1, arr1 + 5, is_even)); +} + +TEST(for_each_test) +{ + std::vector v1{ 1,2,3,4,5 }; + std::for_each(v1.begin(), v1.end(), arr_sum); + EXPECT_EQ(15, for_each_sum); + mystl::for_each(v1.begin(), v1.end(), arr_sum); + EXPECT_EQ(30, for_each_sum); +} + +TEST(generate_test) +{ + int arr1[5]; + int arr2[5]; + std::generate(arr1, arr1 + 5, gen); + mystl::generate(arr2, arr2 + 5, gen); + EXPECT_CON_EQ(arr1, arr2); +} + +TEST(generate_n_test) +{ + int arr1[] = { 1,1,1,1,1,6,7,8,9,10 }; + int arr2[] = { 2,2,2,2,2,6,7,8,9,10 }; + std::generate_n(arr1, 5, gen); + mystl::generate_n(arr2, 5, gen); + EXPECT_CON_EQ(arr1, arr2); +} + +TEST(includes_test) +{ + std::vector v1{ 1,2,3,4,5,6,7,8,9 }; + std::vector v2{ 2,3,5,6,9 }; + std::vector v3{ 0,1,2,3,4 }; + std::vector v4{ 1,2,5,7,10 }; + std::vector v5; + EXPECT_EQ(std::includes(v1.begin(), v1.end(), v2.begin(), v2.end()), + mystl::includes(v1.begin(), v1.end(), v2.begin(), v2.end())); + EXPECT_EQ(std::includes(v1.begin(), v1.end(), v3.begin(), v3.end()), + mystl::includes(v1.begin(), v1.end(), v3.begin(), v3.end())); + EXPECT_EQ(std::includes(v1.begin(), v1.end(), v4.begin(), v4.end()), + mystl::includes(v1.begin(), v1.end(), v4.begin(), v4.end())); + EXPECT_EQ(std::includes(v1.begin(), v1.end(), v5.begin(), v5.end(), std::less()), + mystl::includes(v1.begin(), v1.end(), v5.begin(), v5.end(), std::less())); +} + +TEST(inplace_merge_test) +{ + int arr1[] = { 1,3,5,7,9,2,4,6,8,10 }; + int arr2[] = { 1,3,5,7,9,2,4,6,8,10 }; + int arr3[] = { 1,2,3,1,2,3,4,5 }; + int arr4[] = { 1,2,3,1,2,3,4,5 }; + std::inplace_merge(arr1, arr1 + 5, arr1 + 10); + mystl::inplace_merge(arr2, arr2 + 5, arr2 + 10); + std::inplace_merge(arr3, arr3 + 3, arr3 + 8, std::less()); + mystl::inplace_merge(arr4, arr4 + 3, arr4 + 8, std::less()); + EXPECT_CON_EQ(arr1, arr2); + EXPECT_CON_EQ(arr3, arr4); +} + +TEST(is_heap_test) +{ + int arr1[] = { 0,1,2,3,4,5,6,7,8,9 }; + int arr2[] = { 9,8,7,6,5,4,3,2,1,0 }; + int arr3[] = { 1,3,5,7,9,0,2,4,6,8 }; + int arr4[] = { 0,1,2,3,4,5,6,7,8,9 }; + std::make_heap(arr4, arr4 + 10); + EXPECT_EQ(std::is_heap(arr1, arr1 + 10), mystl::is_heap(arr1, arr1 + 10)); + EXPECT_EQ(std::is_heap(arr2, arr2 + 10, std::less()), + mystl::is_heap(arr2, arr2 + 10, std::less())); + EXPECT_EQ(std::is_heap(arr3, arr3 + 10), mystl::is_heap(arr3, arr3 + 10)); + EXPECT_EQ(std::is_heap(arr4, arr4 + 10), mystl::is_heap(arr4, arr4 + 10)); +} + +TEST(is_sorted_test) +{ + int arr1[] = { 1,2,3,4,5 }; + int arr2[] = { 1,2,3,5,4 }; + int arr3[] = { 5,4,3,2,1 }; + int arr4[] = { 1,2,5,4,3 }; + EXPECT_EQ(std::is_sorted(arr1, arr1 + 5), mystl::is_sorted(arr1, arr1 + 5)); + EXPECT_EQ(std::is_sorted(arr2, arr2 + 5), mystl::is_sorted(arr2, arr2 + 5)); + EXPECT_EQ(std::is_sorted(arr3, arr3 + 5, std::less()), + mystl::is_sorted(arr3, arr3 + 5, std::less())); + EXPECT_EQ(std::is_sorted(arr4, arr4 + 5, std::less()), + mystl::is_sorted(arr4, arr4 + 5, std::less())); +} + +TEST(lower_bound_test) +{ + int arr1[] = { 1,2,3,3,3,4,5 }; + EXPECT_EQ(std::lower_bound(arr1, arr1 + 7, 1), + mystl::lower_bound(arr1, arr1 + 7, 1)); + EXPECT_EQ(std::lower_bound(arr1, arr1 + 7, 2), + mystl::lower_bound(arr1, arr1 + 7, 2)); + EXPECT_EQ(std::lower_bound(arr1, arr1 + 7, 3), + mystl::lower_bound(arr1, arr1 + 7, 3)); + EXPECT_EQ(std::lower_bound(arr1, arr1 + 7, 5, std::less()), + mystl::lower_bound(arr1, arr1 + 7, 5, std::less())); +} + +TEST(max_elememt_test) +{ + int arr1[] = { 1,2,3,4,5,4,3,2,1 }; + double arr2[] = { 1.0,2.2,6.6,8.8,8.81,2.4 }; + EXPECT_PTR_EQ(std::max_element(arr1, arr1 + 9), + mystl::max_element(arr1, arr1 + 9)); + EXPECT_PTR_EQ(std::max_element(arr2, arr2 + 6, std::less()), + mystl::max_element(arr2, arr2 + 6, std::less())); +} + +TEST(median_test) +{ + int ia = 2, ib = 1, ic = 3; + double da = 3.1, db = 3.0, dc = 3.2; + EXPECT_EQ(2, mystl::median(ia, ib, ic)); + EXPECT_EQ(3.1, mystl::median(da, db, dc, std::greater())); +} + +TEST(merge_test) +{ + int arr1[] = { 1,2,5,9,10 }; + int arr2[] = { 3,7,8,8,9 }; + int arr3[] = { 1,2,5,9,10 }; + int arr4[] = { 3,7,8,8,9 }; + int exp[10], act[10]; + std::merge(arr1, arr1 + 5, arr2, arr2 + 5, exp); + mystl::merge(arr3, arr3 + 5, arr4, arr4 + 5, act); + EXPECT_CON_EQ(exp, act); + std::merge(arr1, arr1 + 5, arr2, arr2 + 5, exp, std::less()); + mystl::merge(arr3, arr3 + 5, arr4, arr4 + 5, act, std::less()); + EXPECT_CON_EQ(exp, act); +} + +TEST(min_elememt_test) +{ + int arr1[] = { 2,4,8,1,6,5,8,9,3 }; + double arr2[] = { 1.5,2.2,1.4,1.33,1.333,2.33 }; + EXPECT_PTR_EQ(std::max_element(arr1, arr1 + 9), + mystl::max_element(arr1, arr1 + 9)); + EXPECT_PTR_EQ(std::max_element(arr2, arr2 + 6, std::less()), + mystl::max_element(arr2, arr2 + 6, std::less())); +} + +TEST(is_permutation_test) +{ + int arr1[] = { 1,2,3,4,5 }; + int arr2[] = { 3,4,5,2,1 }; + int arr3[] = { 1,2,3,4,6 }; + // 因为提供的是 C++11 的支持,std::is_permutation 可能没有 C++14 的接口 + EXPECT_EQ(std::is_permutation(arr1, arr1 + 5, arr2), + mystl::is_permutation(arr1, arr1 + 5, arr2, arr2 + 5)); + EXPECT_EQ(std::is_permutation(arr1, arr1 + 5, arr3), + mystl::is_permutation(arr1, arr1 + 5, arr3, arr3 + 5)); + EXPECT_EQ(std::is_permutation(arr1, arr1 + 5, arr2, std::equal_to()), + mystl::is_permutation(arr1, arr1 + 5, arr2, arr2 + 5, std::equal_to())); + EXPECT_EQ(std::is_permutation(arr1, arr1 + 5, arr3, std::equal_to()), + mystl::is_permutation(arr1, arr1 + 5, arr3, arr3 + 5, std::equal_to())); +} + +TEST(next_permutation_test) +{ + int arr1[] = { 1,2,3,3 }; + int arr2[] = { 1,2,3,3 }; + int n1 = 0, n2 = 0; + while (std::next_permutation(arr1, arr1 + 4)) n1++; + while (mystl::next_permutation(arr1, arr1 + 4)) n2++; + EXPECT_EQ(n1, n2); + for (; n1 > 0; n1--) + { + std::next_permutation(arr1, arr1 + 4); + mystl::next_permutation(arr2, arr2 + 4); + EXPECT_CON_EQ(arr1, arr2); + } + std::next_permutation(arr1, arr1 + 4, std::greater()); + mystl::next_permutation(arr2, arr2 + 4, std::greater()); + EXPECT_CON_EQ(arr1, arr2); +} + +TEST(none_of_test) +{ + int arr1[] = { 1,3,5,7,9 }; + int arr2[] = { 1,3,5,7,8 }; + int arr3[] = { 2,4,6,8,10 }; + EXPECT_EQ(std::none_of(arr1, arr1 + 5, is_even), + mystl::none_of(arr1, arr1 + 5, is_even)); + EXPECT_EQ(std::none_of(arr2, arr2 + 5, is_even), + mystl::none_of(arr2, arr2 + 5, is_even)); + EXPECT_EQ(std::none_of(arr3, arr3 + 5, is_even), + mystl::none_of(arr3, arr3 + 5, is_even)); +} + +TEST(nth_element_test) +{ + int arr1[] = { 9,8,7,6,5,4,3,2,1 }; + int arr2[] = { 1,2,3,4,5,6,3,2,1 }; + int arr3[] = { 1,2,8,9,6,5,3,4,7 }; + int arr4[] = { 1,5,1,5,8,4,9,6,8,4,10,13,20,4,2,1 }; + mystl::nth_element(arr1, arr1 + 4, arr1 + 9); + mystl::nth_element(arr2, arr2 + 2, arr2 + 9); + mystl::nth_element(arr3, arr3 + 8, arr3 + 9, std::less()); + mystl::nth_element(arr4, arr4 + 3, arr4 + 16, std::less()); + bool arr1_left_less = true, arr1_right_greater = true; + bool arr2_left_less = true, arr2_right_greater = true; + bool arr3_left_less = true, arr3_right_greater = true; + bool arr4_left_less = true, arr4_right_greater = true; + for (int i = 0; i < 9; ++i) + { + if (i < 4 && arr1[i] > arr1[4]) arr1_left_less = false; + else if (i > 4 && arr1[i] < arr1[4]) arr1_right_greater = false; + } + for (int i = 0; i < 9; ++i) + { + if (i < 2 && arr2[i] > arr2[2]) arr2_left_less = false; + else if (i > 2 && arr2[i] < arr2[2]) arr2_right_greater = false; + } + for (int i = 0; i < 9; ++i) + { + if (i < 8 && arr3[i] > arr3[8]) arr3_left_less = false; + } + for (int i = 0; i < 16; ++i) + { + if (i < 3 && arr4[i] > arr4[3]) arr4_left_less = false; + else if (i > 3 && arr4[i] < arr4[3]) arr4_right_greater = false; + } + EXPECT_TRUE(arr1_left_less); + EXPECT_TRUE(arr1_right_greater); + EXPECT_TRUE(arr2_left_less); + EXPECT_TRUE(arr2_right_greater); + EXPECT_TRUE(arr3_left_less); + EXPECT_TRUE(arr3_right_greater); + EXPECT_TRUE(arr4_left_less); + EXPECT_TRUE(arr4_right_greater); +} + +TEST(partial_sort_test) +{ + int arr1[] = { 3,2,1,9,8,7,6,5,4 }; + int arr2[] = { 3,2,1,9,8,7,6,5,4 }; + int arr3[] = { 5,1,5,8,6,4,8,4,1,3,5,8,4 }; + int arr4[] = { 5,1,5,8,6,4,8,4,1,3,5,8,4 }; + std::partial_sort(arr1, arr1 + 2, arr1 + 9); + mystl::partial_sort(arr2, arr2 + 2, arr2 + 9); + std::partial_sort(arr3, arr3 + 5, arr3 + 13, std::greater()); + mystl::partial_sort(arr4, arr4 + 5, arr4 + 13, std::greater()); + EXPECT_CON_EQ(arr1, arr2); + EXPECT_CON_EQ(arr3, arr4); +} + +TEST(partial_sort_copy_test) +{ + int arr1[] = { 3,2,1,9,8,7,6,5,4 }; + int arr2[] = { 1,2,3,4,5,6,7,8,9 }; + int arr3[] = { 1,6,8,4,2,1,6,8,4,7,6,2,1,3,6 }; + int exp[5], act[5]; + std::partial_sort_copy(arr1, arr1 + 9, exp, exp + 5); + mystl::partial_sort_copy(arr1, arr1 + 9, act, act + 5); + EXPECT_CON_EQ(exp, act); + std::partial_sort_copy(arr2, arr2 + 9, exp, exp + 5); + mystl::partial_sort_copy(arr2, arr2 + 9, act, act + 5); + EXPECT_CON_EQ(exp, act); + std::partial_sort_copy(arr3, arr3 + 15, exp, exp + 5, std::greater()); + mystl::partial_sort_copy(arr3, arr3 + 15, act, act + 5, std::greater()); + EXPECT_CON_EQ(exp, act); +} + +TEST(partition_test) +{ + int arr1[] = { 1,2,3,4,5,6,7,8,9 }; + int arr2[] = { 1,2,3,4,5,6,7,8,9 }; + std::partition(arr1, arr1 + 9, is_odd); + mystl::partition(arr2, arr2 + 9, is_odd); + EXPECT_CON_EQ(arr1, arr2); + std::partition(arr1, arr1 + 9, is_even); + mystl::partition(arr2, arr2 + 9, is_even); + EXPECT_CON_EQ(arr1, arr2); +} + +TEST(partition_copy_test) +{ + int arr1[] = { 1,2,3,4,5,6,7,8,9,10 }; + int exp_true[5], exp_false[5]; + int act_true[5], act_false[5]; + std::partition_copy(arr1, arr1 + 10, exp_true, exp_false, is_odd); + mystl::partition_copy(arr1, arr1 + 10, act_true, act_false, is_odd); + EXPECT_CON_EQ(exp_true, act_true); + EXPECT_CON_EQ(exp_false, act_false); +} + +TEST(prev_permutation_test) +{ + int arr1[] = { 3,2,1,1 }; + int arr2[] = { 3,2,1,1 }; + int n1 = 0, n2 = 0; + while (std::prev_permutation(arr1, arr1 + 4)) n1++; + while (mystl::prev_permutation(arr1, arr1 + 4)) n2++; + EXPECT_EQ(n1, n2); + for (; n1 > 0; n1--) + { + std::prev_permutation(arr1, arr1 + 4); + mystl::prev_permutation(arr2, arr2 + 4); + EXPECT_CON_EQ(arr1, arr2); + } + std::prev_permutation(arr1, arr1 + 4, std::greater()); + mystl::prev_permutation(arr2, arr2 + 4, std::greater()); + EXPECT_CON_EQ(arr1, arr2); +} + +TEST(random_shuffle_test) +{ + int arr1[] = { 1,2,3,4,5,6,7,8,9 }; + int arr2[9]; + for (int i = 0; i < 9; ++i) + { + std::copy(arr1, arr1 + 9, arr2); + mystl::random_shuffle(arr1, arr1 + 9); + EXPECT_CON_NE(arr1, arr2); + } + std::copy(arr1, arr1 + 9, arr2); + mystl::random_shuffle(arr1, arr1 + 9, r); + EXPECT_CON_NE(arr1, arr2); +} + +TEST(remove_test) +{ + std::vector v1{ 1,2,3,4,5,6,6,6 }; + std::vector v2(v1); + std::remove(v1.begin(), v1.end(), 3); + mystl::remove(v2.begin(), v2.end(), 3); + EXPECT_CON_EQ(v1, v2); + std::remove(v1.begin(), v1.end(), 6); + mystl::remove(v2.begin(), v2.end(), 6); + EXPECT_CON_EQ(v1, v2); +} + +TEST(remove_copy_test) +{ + int arr1[] = { 1,2,3,4,5,6,6,6 }; + int arr2[] = { 1,2,3,4,5,6,6,6 }; + int exp[5], act[5]; + std::remove_copy(arr1, arr1 + 8, exp, 6); + mystl::remove_copy(arr2, arr2 + 8, act, 6); + EXPECT_CON_EQ(exp, act); + std::remove_copy(arr1, arr1 + 5, exp, 3); + mystl::remove_copy(arr2, arr2 + 5, act, 3); + EXPECT_CON_EQ(exp, act); +} + +TEST(remove_copy_if_test) +{ + int arr1[] = { 1,2,3,4,5,6,7,8,9,10 }; + int exp[5], act[5]; + std::remove_copy_if(arr1, arr1 + 10, exp, is_odd); + mystl::remove_copy_if(arr1, arr1 + 10, act, is_odd); + EXPECT_CON_EQ(exp, act); + std::remove_copy_if(arr1, arr1 + 10, exp, is_even); + mystl::remove_copy_if(arr1, arr1 + 10, act, is_even); + EXPECT_CON_EQ(exp, act); +} + +TEST(remove_if_test) +{ + std::vector v1{ 1,2,3,4,5,6,7,8,9,10 }; + std::vector v2(v1); + std::remove_if(v1.begin(), v1.end(), is_odd); + mystl::remove_if(v2.begin(), v2.end(), is_odd); + EXPECT_CON_EQ(v1, v2); +} + +TEST(replace_test) +{ + int arr1[] = { 1,1,1,2,2,2,3,3,3 }; + int arr2[] = { 1,1,1,2,2,2,3,3,3 }; + std::replace(arr1, arr1 + 9, 1, 4); + mystl::replace(arr2, arr2 + 9, 1, 4); + EXPECT_CON_EQ(arr1, arr2); + std::replace(arr1, arr1 + 9, 2, 5); + mystl::replace(arr2, arr2 + 9, 2, 5); + EXPECT_CON_EQ(arr1, arr2); + std::replace(arr1, arr1 + 9, 3, 6); + mystl::replace(arr2, arr2 + 9, 3, 6); + EXPECT_CON_EQ(arr1, arr2); +} + +TEST(replace_copy_test) +{ + int arr1[] = { 1,1,1,2,2,2,3,3,3 }; + int exp[9], act[9]; + std::replace_copy(arr1, arr1 + 9, exp, 1, 4); + mystl::replace_copy(arr1, arr1 + 9, act, 1, 4); + EXPECT_CON_EQ(exp, act); + std::replace_copy(arr1, arr1 + 9, exp, 2, 5); + mystl::replace_copy(arr1, arr1 + 9, act, 2, 5); + EXPECT_CON_EQ(exp, act); + std::replace_copy(arr1, arr1 + 9, exp, 3, 6); + mystl::replace_copy(arr1, arr1 + 9, act, 3, 6); + EXPECT_CON_EQ(exp, act); +} + +TEST(replace_copy_if_test) +{ + int arr1[] = { 1,2,3,4,5,6,7,8,9,10 }; + int exp[10] = { 0 }, act[10] = { 0 }; + std::replace_copy_if(arr1, arr1 + 10, exp, is_odd, 1); + mystl::replace_copy_if(arr1, arr1 + 10, act, is_odd, 1); + EXPECT_CON_EQ(exp, act); + std::replace_copy_if(arr1, arr1 + 10, exp, is_even, 2); + mystl::replace_copy_if(arr1, arr1 + 10, act, is_even, 2); + EXPECT_CON_EQ(exp, act); +} + +TEST(replace_if_test) +{ + std::vector v1{ 1,2,3,4,5,6,7,8,9,10 }; + std::vector v2(v1); + std::replace_if(v1.begin(), v1.end(), is_odd, 1); + mystl::replace_if(v2.begin(), v2.end(), is_odd, 1); + EXPECT_CON_EQ(v1, v2); + std::replace_if(v1.begin(), v1.end(), is_even, 2); + mystl::replace_if(v2.begin(), v2.end(), is_even, 2); + EXPECT_CON_EQ(v1, v2); +} + +TEST(reverse_test) +{ + int arr1[] = { 1,2,3,4,5,6,7,8,9 }; + int arr2[] = { 1,2,3,4,5,6,7,8,9 }; + std::reverse(arr1, arr1 + 9); + mystl::reverse(arr2, arr2 + 9); + EXPECT_CON_EQ(arr1, arr2); + std::reverse(arr1, arr1 + 5); + mystl::reverse(arr2, arr2 + 5); + EXPECT_CON_EQ(arr1, arr2); +} + +TEST(reverse_copy_test) +{ + int arr1[] = { 1,2,3,4,5,6,7,8,9 }; + int exp[5], act[5]; + std::reverse_copy(arr1, arr1 + 5, exp); + mystl::reverse_copy(arr1, arr1 + 5, act); + EXPECT_CON_EQ(exp, act); + std::reverse_copy(arr1 + 4, arr1 + 9, exp); + mystl::reverse_copy(arr1 + 4, arr1 + 9, act); + EXPECT_CON_EQ(exp, act); +} + +TEST(rotate_test) +{ + int arr1[] = { 1,2,3,4,5,6,7,8,9 }; + int arr2[] = { 1,2,3,4,5,6,7,8,9 }; + std::rotate(arr1, arr1 + 3, arr1 + 9); + mystl::rotate(arr2, arr2 + 3, arr2 + 9); + EXPECT_CON_EQ(arr1, arr2); + std::rotate(arr1 + 3, arr1 + 5, arr1 + 9); + mystl::rotate(arr2 + 3, arr2 + 5, arr2 + 9); + EXPECT_CON_EQ(arr1, arr2); + std::rotate(arr1, arr1 + 9, arr1 + 9); + mystl::rotate(arr2, arr2 + 9, arr2 + 9); + EXPECT_CON_EQ(arr1, arr2); +} + +TEST(rotate_copy_test) +{ + int arr1[] = { 1,2,3,4,5,6,7,8,9 }; + int exp[9], act[9]; + std::rotate_copy(arr1, arr1 + 5, arr1 + 9, exp); + mystl::rotate_copy(arr1, arr1 + 5, arr1 + 9, act); + EXPECT_CON_EQ(exp, act); + std::rotate_copy(arr1, arr1, arr1 + 9, exp); + mystl::rotate_copy(arr1, arr1, arr1 + 9, act); + EXPECT_CON_EQ(exp, act); + std::rotate_copy(arr1, arr1 + 9, arr1 + 9, exp); + mystl::rotate_copy(arr1, arr1 + 9, arr1 + 9, act); + EXPECT_CON_EQ(exp, act); +} + +TEST(search_test) +{ + int arr1[] = { 1,2,3,3,3,4,5,6,6, }; + int arr2[] = { 1 }; + int arr3[] = { 3,3 }; + int arr4[] = { 5,6,6,6 }; + EXPECT_EQ(std::search(arr1, arr1 + 9, arr2, arr2 + 1), + mystl::search(arr1, arr1 + 9, arr2, arr2 + 1)); + EXPECT_EQ(std::search(arr1, arr1 + 9, arr3, arr3 + 2), + mystl::search(arr1, arr1 + 9, arr3, arr3 + 2)); + EXPECT_EQ(std::search(arr1, arr1 + 9, arr4, arr4 + 3, std::less()), + mystl::search(arr1, arr1 + 9, arr4, arr4 + 3, std::less())); + EXPECT_EQ(std::search(arr1, arr1 + 9, arr4, arr4 + 4, std::less()), + mystl::search(arr1, arr1 + 9, arr4, arr4 + 4, std::less())); +} + +TEST(search_n_test) +{ + int arr1[] = { 1,2,2,3,3,3,6,6,9 }; + EXPECT_EQ(std::search_n(arr1, arr1 + 9, 1, 0), + mystl::search_n(arr1, arr1 + 9, 1, 0)); + EXPECT_EQ(std::search_n(arr1, arr1 + 9, 2, 2), + mystl::search_n(arr1, arr1 + 9, 2, 2)); + EXPECT_EQ(std::search_n(arr1, arr1 + 9, 1, 3), + mystl::search_n(arr1, arr1 + 9, 1, 3)); + EXPECT_EQ(std::search_n(arr1, arr1 + 9, 3, 6, std::less()), + mystl::search_n(arr1, arr1 + 9, 3, 6, std::less())); + EXPECT_EQ(std::search_n(arr1, arr1 + 9, 2, 10, std::less()), + mystl::search_n(arr1, arr1 + 9, 2, 10, std::less())); +} + +TEST(sort_test) +{ + int arr1[] = { 6,1,2,5,4,8,3,2,4,6,10,2,1,9 }; + int arr2[] = { 6,1,2,5,4,8,3,2,4,6,10,2,1,9 }; + int arr3[] = { 80,30,51,65,12,10,24,87,62,51,32,45,1,33,66,20,35,84,62,14 }; + int arr4[] = { 80,30,51,65,12,10,24,87,62,51,32,45,1,33,66,20,35,84,62,14 }; + int arr5[] = { 9,9,9,8,8,8,7,7,7 }; + int arr6[] = { 9,9,9,8,8,8,7,7,7 }; + std::sort(arr1, arr1 + 14); + mystl::sort(arr2, arr2 + 14); + std::sort(arr3, arr3 + 20); + mystl::sort(arr4, arr4 + 20); + std::sort(arr5, arr5 + 9, std::greater()); + mystl::sort(arr6, arr6 + 9, std::greater()); + EXPECT_CON_EQ(arr1, arr2); + EXPECT_CON_EQ(arr3, arr4); + EXPECT_CON_EQ(arr5, arr6); +} + +TEST(swap_ranges_test) +{ + int arr1[] = { 4,5,6,1,2,3 }; + int arr2[] = { 4,5,6,1,2,3 }; + int arr3[] = { 1,2,3,4,5,6 }; + int arr4[] = { 1,2,3,4,5,6 }; + int arr5[] = { 1,1,1 }; + int arr6[] = { 1,1,1 }; + std::swap_ranges(arr1, arr1 + 6, arr3); + mystl::swap_ranges(arr2, arr2 + 6, arr4); + std::swap_ranges(arr1, arr1 + 3, arr5); + mystl::swap_ranges(arr2, arr2 + 3, arr6); + EXPECT_CON_EQ(arr1, arr2); + EXPECT_CON_EQ(arr1, arr2); +} + +TEST(transform_test) +{ + int arr1[] = { 1,2,3,4,5,6,7,8,9 }; + int arr2[] = { 9,8,7,6,5,4,3,2,1 }; + int exp[9], act[9]; + std::transform(arr1, arr1 + 9, exp, unary_op); + mystl::transform(arr1, arr1 + 9, act, unary_op); + EXPECT_CON_EQ(exp, act); + std::transform(arr1, arr1 + 9, arr2, exp, binary_op); + mystl::transform(arr1, arr1 + 9, arr2, act, binary_op); + EXPECT_CON_EQ(exp, act); +} + +TEST(unique_test) +{ + int arr1[] = { 1,1,1,2,2,3,4,4,5,6 }; + int arr2[] = { 1,1,1,2,2,3,4,4,5,6 }; + int arr3[] = { 1,2,3,6,6,6,8,8,9 }; + int arr4[] = { 1,2,3,6,6,6,8,8,9 }; + std::unique(arr1, arr1 + 10); + mystl::unique(arr2, arr2 + 10); + std::unique(arr3, arr3 + 9, std::equal_to()); + mystl::unique(arr4, arr4 + 9, std::equal_to()); + EXPECT_CON_EQ(arr1, arr2); + EXPECT_CON_EQ(arr3, arr4); +} + +TEST(unique_copy_test) +{ + int arr1[] = { 1,1,1,2,2,3,4,4,5,6 }; + int arr2[] = { 1,2,3,6,6,6,8,8,9 }; + int exp[6], act[6]; + std::unique_copy(arr1, arr1 + 10, exp); + mystl::unique_copy(arr1, arr1 + 10, act); + EXPECT_CON_EQ(exp, act); + std::unique_copy(arr2, arr2 + 9, exp, std::equal_to()); + mystl::unique_copy(arr2, arr2 + 9, act, std::equal_to()); + EXPECT_CON_EQ(exp, act); +} + +TEST(upper_bound_test) +{ + int arr1[] = { 1,2,3,3,3,4,5,6,6 }; + EXPECT_EQ(std::upper_bound(arr1, arr1 + 9, 0), + mystl::upper_bound(arr1, arr1 + 9, 0)); + EXPECT_EQ(std::upper_bound(arr1, arr1 + 9, 1), + mystl::upper_bound(arr1, arr1 + 9, 1)); + EXPECT_EQ(std::upper_bound(arr1, arr1 + 9, 3), + mystl::upper_bound(arr1, arr1 + 9, 3)); + EXPECT_EQ(std::upper_bound(arr1, arr1 + 9, 6, std::less()), + mystl::upper_bound(arr1, arr1 + 9, 6, std::less())); + EXPECT_EQ(std::upper_bound(arr1, arr1 + 9, 7, std::less()), + mystl::upper_bound(arr1, arr1 + 9, 7, std::less())); +} + +} // namespace algorithm_test + +#ifdef _MSC_VER +#pragma warning(pop) +#endif // _MSC_VER + +} // namespace test +} // namespace mystl +#endif // !MYTINYSTL_ALGORITHM_TEST_H_ diff --git a/src/MyTinySTL-master/MyTinySTL-master/Test/deque_test.h b/src/MyTinySTL-master/MyTinySTL-master/Test/deque_test.h new file mode 100755 index 0000000..0793bf6 --- /dev/null +++ b/src/MyTinySTL-master/MyTinySTL-master/Test/deque_test.h @@ -0,0 +1,102 @@ +#ifndef MYTINYSTL_DEQUE_TEST_H_ +#define MYTINYSTL_DEQUE_TEST_H_ + +// deque test : 测试 deque 的接口和 push_front/push_back 的性能 + +#include + +#include "../MyTinySTL/deque.h" +#include "test.h" + +namespace mystl +{ +namespace test +{ +namespace deque_test +{ + +void deque_test() +{ + std::cout << "[===============================================================]" << std::endl; + std::cout << "[----------------- Run container test : deque ------------------]" << std::endl; + std::cout << "[-------------------------- API test ---------------------------]" << std::endl; + int a[] = { 1,2,3,4,5 }; + mystl::deque d1; + mystl::deque d2(5); + mystl::deque d3(5, 1); + mystl::deque d4(a, a + 5); + mystl::deque d5(d2); + mystl::deque d6(std::move(d2)); + mystl::deque d7; + d7 = d3; + mystl::deque d8; + d8 = std::move(d3); + mystl::deque d9{ 1,2,3,4,5,6,7,8,9 }; + mystl::deque d10; + d10 = { 1,2,3,4,5,6,7,8,9 }; + + FUN_AFTER(d1, d1.assign(5, 1)); + FUN_AFTER(d1, d1.assign(8, 8)); + FUN_AFTER(d1, d1.assign(a, a + 5)); + FUN_AFTER(d1, d1.assign({ 1,2,3,4,5 })); + FUN_AFTER(d1, d1.insert(d1.end(), 6)); + FUN_AFTER(d1, d1.insert(d1.end() - 1, 2, 7)); + FUN_AFTER(d1, d1.insert(d1.begin(), a, a + 5)); + FUN_AFTER(d1, d1.erase(d1.begin())); + FUN_AFTER(d1, d1.erase(d1.begin(), d1.begin() + 4)); + FUN_AFTER(d1, d1.emplace_back(8)); + FUN_AFTER(d1, d1.emplace_front(8)); + FUN_AFTER(d1, d1.emplace(d1.begin() + 1, 9)); + FUN_AFTER(d1, d1.push_front(1)); + FUN_AFTER(d1, d1.push_back(2)); + FUN_AFTER(d1, d1.pop_back()); + FUN_AFTER(d1, d1.pop_front()); + FUN_AFTER(d1, d1.shrink_to_fit()); + FUN_AFTER(d1, d1.resize(5)); + FUN_AFTER(d1, d1.resize(8, 8)); + FUN_AFTER(d1, d1.clear()); + FUN_AFTER(d1, d1.shrink_to_fit()); + FUN_AFTER(d1, d1.swap(d4)); + FUN_VALUE(*(d1.begin())); + FUN_VALUE(*(d1.end() - 1)); + FUN_VALUE(*(d1.rbegin())); + FUN_VALUE(*(d1.rend() - 1)); + FUN_VALUE(d1.front()); + FUN_VALUE(d1.back()); + FUN_VALUE(d1.at(1)); + FUN_VALUE(d1[2]); + std::cout << std::boolalpha; + FUN_VALUE(d1.empty()); + std::cout << std::noboolalpha; + FUN_VALUE(d1.size()); + FUN_VALUE(d1.max_size()); + PASSED; +#if PERFORMANCE_TEST_ON + std::cout << "[--------------------- Performance Testing ---------------------]" << std::endl; + std::cout << "|---------------------|-------------|-------------|-------------|" << std::endl; + std::cout << "| push_front |"; +#if LARGER_TEST_DATA_ON + CON_TEST_P1(deque, push_front, rand(), SCALE_LL(LEN1), SCALE_LL(LEN2), SCALE_LL(LEN3)); +#else + CON_TEST_P1(deque, push_front, rand(), SCALE_L(LEN1), SCALE_L(LEN2), SCALE_L(LEN3)); +#endif + std::cout << std::endl; + std::cout << "|---------------------|-------------|-------------|-------------|" << std::endl; + std::cout << "| push_back |"; +#if LARGER_TEST_DATA_ON + CON_TEST_P1(deque, push_back, rand(), SCALE_LL(LEN1), SCALE_LL(LEN2), SCALE_LL(LEN3)); +#else + CON_TEST_P1(deque, push_back, rand(), SCALE_L(LEN1), SCALE_L(LEN2), SCALE_L(LEN3)); +#endif + std::cout << std::endl; + std::cout << "|---------------------|-------------|-------------|-------------|" << std::endl; + PASSED; +#endif + std::cout << "[----------------- End container test : deque ------------------]" << std::endl; +} + +} // namespace deque_test +} // namespace test +} // namespace mystl +#endif // !MYTINYSTL_DEQUE_TEST_H_ + diff --git a/src/MyTinySTL-master/MyTinySTL-master/Test/list_test.h b/src/MyTinySTL-master/MyTinySTL-master/Test/list_test.h new file mode 100755 index 0000000..83f90a6 --- /dev/null +++ b/src/MyTinySTL-master/MyTinySTL-master/Test/list_test.h @@ -0,0 +1,118 @@ +#ifndef MYTINYSTL_LIST_TEST_H_ +#define MYTINYSTL_LIST_TEST_H_ + +// list test : 测试 list 的接口与 insert, sort 的性能 + +#include + +#include "../MyTinySTL/list.h" +#include "test.h" + +namespace mystl +{ +namespace test +{ +namespace list_test +{ + +// 一个辅助测试函数 +bool is_odd(int x) { return x & 1; } + +void list_test() +{ + std::cout << "[===============================================================]" << std::endl; + std::cout << "[------------------ Run container test : list ------------------]" << std::endl; + std::cout << "[-------------------------- API test ---------------------------]" << std::endl; + int a[] = { 1,2,3,4,5 }; + mystl::list l1; + mystl::list l2(5); + mystl::list l3(5, 1); + mystl::list l4(a, a + 5); + mystl::list l5(l2); + mystl::list l6(std::move(l2)); + mystl::list l7{ 1,2,3,4,5,6,7,8,9 }; + mystl::list l8; + l8 = l3; + mystl::list l9; + l9 = std::move(l3); + mystl::list l10; + l10 = { 1, 2, 2, 3, 5, 6, 7, 8, 9 }; + + FUN_AFTER(l1, l1.assign(8, 8)); + FUN_AFTER(l1, l1.assign(a, a + 5)); + FUN_AFTER(l1, l1.assign({ 1,2,3,4,5,6 })); + FUN_AFTER(l1, l1.insert(l1.end(), 6)); + FUN_AFTER(l1, l1.insert(l1.end(), 2, 7)); + FUN_AFTER(l1, l1.insert(l1.begin(), a, a + 5)); + FUN_AFTER(l1, l1.push_back(2)); + FUN_AFTER(l1, l1.push_front(1)); + FUN_AFTER(l1, l1.emplace(l1.begin(),1)); + FUN_AFTER(l1, l1.emplace_front(0)); + FUN_AFTER(l1, l1.emplace_back(10)); + FUN_VALUE(l1.size()); + FUN_AFTER(l1, l1.pop_front()); + FUN_AFTER(l1, l1.pop_back()); + FUN_AFTER(l1, l1.erase(l1.begin())); + FUN_AFTER(l1, l1.erase(l1.begin(), l1.end())); + FUN_VALUE(l1.size()); + FUN_AFTER(l1, l1.resize(10)); + FUN_AFTER(l1, l1.resize(5, 1)); + FUN_AFTER(l1, l1.resize(8, 2)); + FUN_VALUE(l1.size()); + FUN_AFTER(l1, l1.splice(l1.end(), l4)); + FUN_AFTER(l1, l1.splice(l1.begin(), l5, l5.begin())); + FUN_AFTER(l1, l1.splice(l1.end(), l6, l6.begin(), ++l6.begin())); + FUN_VALUE(l1.size()); + FUN_AFTER(l1, l1.remove(0)); + FUN_AFTER(l1, l1.remove_if(is_odd)); + FUN_VALUE(l1.size()); + FUN_AFTER(l1, l1.assign({ 9,5,3,3,7,1,3,2,2,0,10 })); + FUN_VALUE(l1.size()); + FUN_AFTER(l1, l1.sort()); + FUN_AFTER(l1, l1.unique()); + FUN_AFTER(l1, l1.unique([&](int a, int b) {return b == a + 1; })); + FUN_AFTER(l1, l1.merge(l7)); + FUN_AFTER(l1, l1.sort(mystl::greater())); + FUN_AFTER(l1, l1.merge(l8, mystl::greater())); + FUN_AFTER(l1, l1.reverse()); + FUN_AFTER(l1, l1.clear()); + FUN_AFTER(l1, l1.swap(l9)); + FUN_VALUE(*l1.begin()); + FUN_VALUE(*l1.rbegin()); + FUN_VALUE(l1.front()); + FUN_VALUE(l1.back()); + std::cout << std::boolalpha; + FUN_VALUE(l1.empty()); + std::cout << std::noboolalpha; + FUN_VALUE(l1.size()); + FUN_VALUE(l1.max_size()); + PASSED; +#if PERFORMANCE_TEST_ON + std::cout << "[--------------------- Performance Testing ---------------------]" << std::endl; + std::cout << "|---------------------|-------------|-------------|-------------|" << std::endl; + std::cout << "| insert |"; +#if LARGER_TEST_DATA_ON + CON_TEST_P2(list, insert, end, rand(), SCALE_L(LEN1), SCALE_L(LEN2), SCALE_L(LEN3)); +#else + CON_TEST_P2(list, insert, end, rand(), SCALE_M(LEN1), SCALE_M(LEN2), SCALE_M(LEN3)); +#endif + std::cout << std::endl; + std::cout << "|---------------------|-------------|-------------|-------------|" << std::endl; + std::cout << "| sort |"; +#if LARGER_TEST_DATA_ON + LIST_SORT_TEST(SCALE_M(LEN1), SCALE_M(LEN2), SCALE_M(LEN3)); +#else + LIST_SORT_TEST(SCALE_S(LEN1), SCALE_S(LEN2), SCALE_S(LEN3)); +#endif + std::cout << std::endl; + std::cout << "|---------------------|-------------|-------------|-------------|" << std::endl; + PASSED; +#endif + std::cout << "[------------------ End container test : list ------------------]" << std::endl; +} + +} // namespace list_test +} // namespace test +} // namespace mystl +#endif // !MYTINYSTL_LIST_TEST_H_ + diff --git a/src/MyTinySTL-master/MyTinySTL-master/Test/map_test.h b/src/MyTinySTL-master/MyTinySTL-master/Test/map_test.h new file mode 100755 index 0000000..78a0553 --- /dev/null +++ b/src/MyTinySTL-master/MyTinySTL-master/Test/map_test.h @@ -0,0 +1,202 @@ +#ifndef MYTINYSTL_MAP_TEST_H_ +#define MYTINYSTL_MAP_TEST_H_ + +// map test : 测试 map, multimap 的接口与它们 insert 的性能 + +#include + +#include "../MyTinySTL/map.h" +#include "../MyTinySTL/vector.h" +#include "test.h" + +namespace mystl +{ +namespace test +{ +namespace map_test +{ + +// pair 的宏定义 +#define PAIR mystl::pair + +// map 的遍历输出 +#define MAP_COUT(m) do { \ + std::string m_name = #m; \ + std::cout << " " << m_name << " :"; \ + for (auto it : m) std::cout << " <" << it.first << "," << it.second << ">"; \ + std::cout << std::endl; \ +} while(0) + +// map 的函数操作 +#define MAP_FUN_AFTER(con, fun) do { \ + std::string str = #fun; \ + std::cout << " After " << str << " :" << std::endl; \ + fun; \ + MAP_COUT(con); \ +} while(0) + +// map 的函数值 +#define MAP_VALUE(fun) do { \ + std::string str = #fun; \ + auto it = fun; \ + std::cout << " " << str << " : <" << it.first << "," << it.second << ">\n"; \ +} while(0) + +void map_test() +{ + std::cout << "[===============================================================]" << std::endl; + std::cout << "[------------------ Run container test : map -------------------]" << std::endl; + std::cout << "[-------------------------- API test ---------------------------]" << std::endl; + mystl::vector v; + for (int i = 0; i < 5; ++i) + v.push_back(PAIR(i, i)); + mystl::map m1; + mystl::map> m2; + mystl::map m3(v.begin(), v.end()); + mystl::map m4(v.begin(), v.end()); + mystl::map m5(m3); + mystl::map m6(std::move(m3)); + mystl::map m7; + m7 = m4; + mystl::map m8; + m8 = std::move(m4); + mystl::map m9{ PAIR(1,1),PAIR(3,2),PAIR(2,3) }; + mystl::map m10; + m10 = { PAIR(1,1),PAIR(3,2),PAIR(2,3) }; + + for (int i = 5; i > 0; --i) + { + MAP_FUN_AFTER(m1, m1.emplace(i, i)); + } + MAP_FUN_AFTER(m1, m1.emplace_hint(m1.begin(), 0, 0)); + MAP_FUN_AFTER(m1, m1.erase(m1.begin())); + MAP_FUN_AFTER(m1, m1.erase(0)); + MAP_FUN_AFTER(m1, m1.erase(1)); + MAP_FUN_AFTER(m1, m1.erase(m1.begin(), m1.end())); + for (int i = 0; i < 5; ++i) + { + MAP_FUN_AFTER(m1, m1.insert(PAIR(i, i))); + } + MAP_FUN_AFTER(m1, m1.insert(v.begin(), v.end())); + MAP_FUN_AFTER(m1, m1.insert(m1.end(), PAIR(5, 5))); + FUN_VALUE(m1.count(1)); + MAP_VALUE(*m1.find(3)); + MAP_VALUE(*m1.lower_bound(3)); + MAP_VALUE(*m1.upper_bound(2)); + auto first = *m1.equal_range(2).first; + auto second = *m1.equal_range(2).second; + std::cout << " m1.equal_range(2) : from <" << first.first << ", " << first.second + << "> to <" << second.first << ", " << second.second << ">" << std::endl; + MAP_FUN_AFTER(m1, m1.erase(m1.begin())); + MAP_FUN_AFTER(m1, m1.erase(1)); + MAP_FUN_AFTER(m1, m1.erase(m1.begin(), m1.find(3))); + MAP_FUN_AFTER(m1, m1.clear()); + MAP_FUN_AFTER(m1, m1.swap(m9)); + MAP_VALUE(*m1.begin()); + MAP_VALUE(*m1.rbegin()); + FUN_VALUE(m1[1]); + MAP_FUN_AFTER(m1, m1[1] = 3); + FUN_VALUE(m1.at(1)); + std::cout << std::boolalpha; + FUN_VALUE(m1.empty()); + std::cout << std::noboolalpha; + FUN_VALUE(m1.size()); + FUN_VALUE(m1.max_size()); + PASSED; +#if PERFORMANCE_TEST_ON + std::cout << "[--------------------- Performance Testing ---------------------]" << std::endl; + std::cout << "|---------------------|-------------|-------------|-------------|" << std::endl; + std::cout << "| emplace |"; +#if LARGER_TEST_DATA_ON + MAP_EMPLACE_TEST(map, SCALE_L(LEN1), SCALE_L(LEN2), SCALE_L(LEN3)); +#else + MAP_EMPLACE_TEST(map, SCALE_M(LEN1), SCALE_M(LEN2), SCALE_M(LEN3)); +#endif + std::cout << std::endl; + std::cout << "|---------------------|-------------|-------------|-------------|" << std::endl; + PASSED; +#endif + std::cout << "[------------------ End container test : map -------------------]" << std::endl; +} + +void multimap_test() +{ + std::cout << "[===============================================================]" << std::endl; + std::cout << "[---------------- Run container test : multimap ----------------]" << std::endl; + std::cout << "[-------------------------- API test ---------------------------]" << std::endl; + mystl::vector v; + for (int i = 0; i < 5; ++i) + v.push_back(PAIR(i, i)); + mystl::multimap m1; + mystl::multimap> m2; + mystl::multimap m3(v.begin(), v.end()); + mystl::multimap m4(v.begin(), v.end()); + mystl::multimap m5(m3); + mystl::multimap m6(std::move(m3)); + mystl::multimap m7; + m7 = m4; + mystl::multimap m8; + m8 = std::move(m4); + mystl::multimap m9{ PAIR(1,1),PAIR(3,2),PAIR(2,3) }; + mystl::multimap m10; + m10 = { PAIR(1,1),PAIR(3,2),PAIR(2,3) }; + + for (int i = 5; i > 0; --i) + { + MAP_FUN_AFTER(m1, m1.emplace(i, i)); + } + MAP_FUN_AFTER(m1, m1.emplace_hint(m1.begin(), 0, 0)); + MAP_FUN_AFTER(m1, m1.erase(m1.begin())); + MAP_FUN_AFTER(m1, m1.erase(0)); + MAP_FUN_AFTER(m1, m1.erase(1)); + MAP_FUN_AFTER(m1, m1.erase(m1.begin(), m1.end())); + for (int i = 0; i < 5; ++i) + { + MAP_FUN_AFTER(m1, m1.insert(mystl::make_pair(i, i))); + } + MAP_FUN_AFTER(m1, m1.insert(v.begin(), v.end())); + MAP_FUN_AFTER(m1, m1.insert(PAIR(5, 5))); + MAP_FUN_AFTER(m1, m1.insert(m1.end(), PAIR(5, 5))); + FUN_VALUE(m1.count(3)); + MAP_VALUE(*m1.find(3)); + MAP_VALUE(*m1.lower_bound(3)); + MAP_VALUE(*m1.upper_bound(2)); + auto first = *m1.equal_range(2).first; + auto second = *m1.equal_range(2).second; + std::cout << " m1.equal_range(2) : from <" << first.first << ", " << first.second + << "> to <" << second.first << ", " << second.second << ">" << std::endl; + MAP_FUN_AFTER(m1, m1.erase(m1.begin())); + MAP_FUN_AFTER(m1, m1.erase(1)); + MAP_FUN_AFTER(m1, m1.erase(m1.begin(), m1.find(3))); + MAP_FUN_AFTER(m1, m1.clear()); + MAP_FUN_AFTER(m1, m1.swap(m9)); + MAP_FUN_AFTER(m1, m1.insert(PAIR(3, 3))); + MAP_VALUE(*m1.begin()); + MAP_VALUE(*m1.rbegin()); + std::cout << std::boolalpha; + FUN_VALUE(m1.empty()); + std::cout << std::noboolalpha; + FUN_VALUE(m1.size()); + FUN_VALUE(m1.max_size()); + PASSED; +#if PERFORMANCE_TEST_ON + std::cout << "[--------------------- Performance Testing ---------------------]" << std::endl; + std::cout << "|---------------------|-------------|-------------|-------------|" << std::endl; + std::cout << "| emplace |"; +#if LARGER_TEST_DATA_ON + MAP_EMPLACE_TEST(multimap, SCALE_M(LEN1), SCALE_M(LEN2), SCALE_M(LEN3)); +#else + MAP_EMPLACE_TEST(multimap, SCALE_S(LEN1), SCALE_S(LEN2), SCALE_S(LEN3)); +#endif + std::cout << std::endl; + std::cout << "|---------------------|-------------|-------------|-------------|" << std::endl; + PASSED; +#endif + std::cout << "[---------------- End container test : multimap ----------------]" << std::endl; +} + +} // namespace map_test +} // namespace test +} // namespace mystl +#endif // !MYTINYSTL_MAP_TEST_H_ + diff --git a/src/MyTinySTL-master/MyTinySTL-master/Test/queue_test.h b/src/MyTinySTL-master/MyTinySTL-master/Test/queue_test.h new file mode 100755 index 0000000..2a11174 --- /dev/null +++ b/src/MyTinySTL-master/MyTinySTL-master/Test/queue_test.h @@ -0,0 +1,186 @@ +#ifndef MYTINYSTL_QUEUE_TEST_H_ +#define MYTINYSTL_QUEUE_TEST_H_ + +// queue test : 测试 queue, priority_queue 的接口和它们 push 的性能 + +#include + +#include "../MyTinySTL/queue.h" +#include "test.h" + +namespace mystl +{ +namespace test +{ +namespace queue_test +{ + +void queue_print(mystl::queue q) +{ + while (!q.empty()) + { + std::cout << " " << q.front(); + q.pop(); + } + std::cout << std::endl; +} + +void p_queue_print(mystl::priority_queue p) +{ + while (!p.empty()) + { + std::cout << " " << p.top(); + p.pop(); + } + std::cout << std::endl; +} + +// queue 的遍历输出 +#define QUEUE_COUT(q) do { \ + std::string q_name = #q; \ + std::cout << " " << q_name << " :"; \ + queue_print(q); \ +} while(0) + +// priority_queue 的遍历输出 +#define P_QUEUE_COUT(p) do { \ + std::string p_name = #p; \ + std::cout << " " << p_name << " :"; \ + p_queue_print(p); \ +} while(0) + +#define QUEUE_FUN_AFTER(con, fun) do { \ + std::string fun_name = #fun; \ + std::cout << " After " << fun_name << " :\n"; \ + fun; \ + QUEUE_COUT(con); \ +} while(0) + +#define P_QUEUE_FUN_AFTER(con, fun) do { \ + std::string fun_name = #fun; \ + std::cout << " After " << fun_name << " :\n"; \ + fun; \ + P_QUEUE_COUT(con); \ +} while(0) + +void queue_test() +{ + std::cout << "[===============================================================]" << std::endl; + std::cout << "[----------------- Run container test : queue ------------------]" << std::endl; + std::cout << "[-------------------------- API test ---------------------------]" << std::endl; + int a[] = { 1,2,3,4,5 }; + mystl::deque d1(5); + mystl::queue q1; + mystl::queue q2(5); + mystl::queue q3(5, 1); + mystl::queue q4(a, a + 5); + mystl::queue q5(d1); + mystl::queue q6(std::move(d1)); + mystl::queue q7(q2); + mystl::queue q8(std::move(q2)); + mystl::queue q9; + q9 = q3; + mystl::queue q10; + q10 = std::move(q3); + mystl::queue q11{ 1,2,3,4,5 }; + mystl::queue q12; + q12 = { 1,2,3,4,5 }; + + QUEUE_FUN_AFTER(q1, q1.push(1)); + QUEUE_FUN_AFTER(q1, q1.push(2)); + QUEUE_FUN_AFTER(q1, q1.push(3)); + QUEUE_FUN_AFTER(q1, q1.pop()); + QUEUE_FUN_AFTER(q1, q1.emplace(4)); + QUEUE_FUN_AFTER(q1, q1.emplace(5)); + std::cout << std::boolalpha; + FUN_VALUE(q1.empty()); + std::cout << std::noboolalpha; + FUN_VALUE(q1.size()); + FUN_VALUE(q1.front()); + FUN_VALUE(q1.back()); + while (!q1.empty()) + { + QUEUE_FUN_AFTER(q1, q1.pop()); + } + QUEUE_FUN_AFTER(q1, q1.swap(q4)); + QUEUE_FUN_AFTER(q1, q1.clear()); + PASSED; +#if PERFORMANCE_TEST_ON + std::cout << "[--------------------- Performance Testing ---------------------]" << std::endl; + std::cout << "|---------------------|-------------|-------------|-------------|" << std::endl; + std::cout << "| push |"; +#if LARGER_TEST_DATA_ON + CON_TEST_P1(queue, push, rand(), SCALE_LL(LEN1), SCALE_LL(LEN2), SCALE_LL(LEN3)); +#else + CON_TEST_P1(queue, push, rand(), SCALE_L(LEN1), SCALE_L(LEN2), SCALE_L(LEN3)); +#endif + std::cout << std::endl; + std::cout << "|---------------------|-------------|-------------|-------------|" << std::endl; + PASSED; +#endif + std::cout << "[----------------- End container test : queue ------------------]" << std::endl; +} + +void priority_test() +{ + std::cout << "[===============================================================]" << std::endl; + std::cout << "[------------- Run container test : priority_queue -------------]" << std::endl; + std::cout << "[-------------------------- API test ---------------------------]" << std::endl; + int a[] = { 1,2,3,4,5 }; + mystl::vector v1(5); + mystl::priority_queue p1; + mystl::priority_queue p2(5); + mystl::priority_queue p3(5, 1); + mystl::priority_queue p4(a, a + 5); + mystl::priority_queue p5(v1); + mystl::priority_queue p6(std::move(v1)); + mystl::priority_queue p7(p2); + mystl::priority_queue p8(std::move(p2)); + mystl::priority_queue p9; + p9 = p3; + mystl::priority_queue p10; + p10 = std::move(p3); + mystl::priority_queue p11{ 1,2,3,4,5 }; + mystl::priority_queue p12; + p12 = { 1,2,3,4,5 }; + + P_QUEUE_FUN_AFTER(p1, p1.push(1)); + P_QUEUE_FUN_AFTER(p1, p1.push(5)); + P_QUEUE_FUN_AFTER(p1, p1.push(3)); + P_QUEUE_FUN_AFTER(p1, p1.pop()); + P_QUEUE_FUN_AFTER(p1, p1.emplace(7)); + P_QUEUE_FUN_AFTER(p1, p1.emplace(2)); + P_QUEUE_FUN_AFTER(p1, p1.emplace(8)); + std::cout << std::boolalpha; + FUN_VALUE(p1.empty()); + std::cout << std::noboolalpha; + FUN_VALUE(p1.size()); + FUN_VALUE(p1.top()); + while (!p1.empty()) + { + P_QUEUE_FUN_AFTER(p1, p1.pop()); + } + P_QUEUE_FUN_AFTER(p1, p1.swap(p4)); + P_QUEUE_FUN_AFTER(p1, p1.clear()); + PASSED; +#if PERFORMANCE_TEST_ON + std::cout << "[--------------------- Performance Testing ---------------------]" << std::endl; + std::cout << "|---------------------|-------------|-------------|-------------|" << std::endl; + std::cout << "| push |"; +#if LARGER_TEST_DATA_ON + CON_TEST_P1(priority_queue, push, rand(), SCALE_LL(LEN1), SCALE_LL(LEN2), SCALE_LL(LEN3)); +#else + CON_TEST_P1(priority_queue, push, rand(), SCALE_L(LEN1), SCALE_L(LEN2), SCALE_L(LEN3)); +#endif + std::cout << std::endl; + std::cout << "|---------------------|-------------|-------------|-------------|" << std::endl; + PASSED; +#endif + std::cout << "[------------- End container test : priority_queue -------------]" << std::endl; +} + +} // namespace queue_test +} // namespace test +} // namespace mystl +#endif // !MYTINYSTL_QUEUE_TEST_H_ + diff --git a/src/MyTinySTL-master/MyTinySTL-master/Test/set_test.h b/src/MyTinySTL-master/MyTinySTL-master/Test/set_test.h new file mode 100755 index 0000000..8389e74 --- /dev/null +++ b/src/MyTinySTL-master/MyTinySTL-master/Test/set_test.h @@ -0,0 +1,166 @@ +#ifndef MYTINYSTL_SET_TEST_H_ +#define MYTINYSTL_SET_TEST_H_ + +// set test : 测试 set, multiset 的接口与它们 insert 的性能 + +#include + +#include "../MyTinySTL/set.h" +#include "test.h" + +namespace mystl +{ +namespace test +{ +namespace set_test +{ + +void set_test() +{ + std::cout << "[===============================================================]" << std::endl; + std::cout << "[------------------ Run container test : set -------------------]" << std::endl; + std::cout << "[-------------------------- API test ---------------------------]" << std::endl; + int a[] = { 5,4,3,2,1 }; + mystl::set s1; + mystl::set> s2; + mystl::set s3(a, a + 5); + mystl::set s4(a, a + 5); + mystl::set s5(s3); + mystl::set s6(std::move(s3)); + mystl::set s7; + s7 = s4; + mystl::set s8; + s8 = std::move(s4); + mystl::set s9{ 1,2,3,4,5 }; + mystl::set s10; + s10 = { 1,2,3,4,5 }; + + for (int i = 5; i > 0; --i) + { + FUN_AFTER(s1, s1.emplace(i)); + } + FUN_AFTER(s1, s1.emplace_hint(s1.begin(), 0)); + FUN_AFTER(s1, s1.erase(s1.begin())); + FUN_AFTER(s1, s1.erase(0)); + FUN_AFTER(s1, s1.erase(1)); + FUN_AFTER(s1, s1.erase(s1.begin(), s1.end())); + for (int i = 0; i < 5; ++i) + { + FUN_AFTER(s1, s1.insert(i)); + } + FUN_AFTER(s1, s1.insert(a, a + 5)); + FUN_AFTER(s1, s1.insert(5)); + FUN_AFTER(s1, s1.insert(s1.end(), 5)); + FUN_VALUE(s1.count(5)); + FUN_VALUE(*s1.find(3)); + FUN_VALUE(*s1.lower_bound(3)); + FUN_VALUE(*s1.upper_bound(3)); + auto first = *s1.equal_range(3).first; + auto second = *s1.equal_range(3).second; + std::cout << " s1.equal_range(3) : from " << first << " to " << second << std::endl; + FUN_AFTER(s1, s1.erase(s1.begin())); + FUN_AFTER(s1, s1.erase(1)); + FUN_AFTER(s1, s1.erase(s1.begin(), s1.find(3))); + FUN_AFTER(s1, s1.clear()); + FUN_AFTER(s1, s1.swap(s5)); + FUN_VALUE(*s1.begin()); + FUN_VALUE(*s1.rbegin()); + std::cout << std::boolalpha; + FUN_VALUE(s1.empty()); + std::cout << std::noboolalpha; + FUN_VALUE(s1.size()); + FUN_VALUE(s1.max_size()); + PASSED; +#if PERFORMANCE_TEST_ON + std::cout << "[--------------------- Performance Testing ---------------------]" << std::endl; + std::cout << "|---------------------|-------------|-------------|-------------|" << std::endl; + std::cout << "| emplace |"; +#if LARGER_TEST_DATA_ON + CON_TEST_P1(set, emplace, rand(), SCALE_L(LEN1), SCALE_L(LEN2), SCALE_L(LEN3)); +#else + CON_TEST_P1(set, emplace, rand(), SCALE_M(LEN1), SCALE_M(LEN2), SCALE_M(LEN3)); +#endif + std::cout << std::endl; + std::cout << "|---------------------|-------------|-------------|-------------|" << std::endl; + PASSED; +#endif + std::cout << "[------------------ End container test : set -------------------]" << std::endl; +} + +void multiset_test() +{ + std::cout << "[===============================================================]" << std::endl; + std::cout << "[---------------- Run container test : multiset ----------------]" << std::endl; + std::cout << "[-------------------------- API test ---------------------------]" << std::endl; + int a[] = { 5,4,3,2,1 }; + mystl::multiset s1; + mystl::multiset> s2; + mystl::multiset s3(a, a + 5); + mystl::multiset s4(a, a + 5); + mystl::multiset s5(s3); + mystl::multiset s6(std::move(s3)); + mystl::multiset s7; + s7 = s4; + mystl::multiset s8; + s8 = std::move(s4); + mystl::multiset s9{ 1,2,3,4,5 }; + mystl::multiset s10; + s10 = { 1,2,3,4,5 }; + + for (int i = 5; i > 0; --i) + { + FUN_AFTER(s1, s1.emplace(i)); + } + FUN_AFTER(s1, s1.emplace_hint(s1.begin(), 0)); + FUN_AFTER(s1, s1.erase(s1.begin())); + FUN_AFTER(s1, s1.erase(0)); + FUN_AFTER(s1, s1.erase(1)); + FUN_AFTER(s1, s1.erase(s1.begin(), s1.end())); + for (int i = 0; i < 5; ++i) + { + FUN_AFTER(s1, s1.insert(i)); + } + FUN_AFTER(s1, s1.insert(a, a + 5)); + FUN_AFTER(s1, s1.insert(5)); + FUN_AFTER(s1, s1.insert(s1.end(), 5)); + FUN_VALUE(s1.count(5)); + FUN_VALUE(*s1.find(3)); + FUN_VALUE(*s1.lower_bound(3)); + FUN_VALUE(*s1.upper_bound(3)); + auto first = *s1.equal_range(3).first; + auto second = *s1.equal_range(3).second; + std::cout << " s1.equal_range(3) : from " << first << " to " << second << std::endl; + FUN_AFTER(s1, s1.erase(s1.begin())); + FUN_AFTER(s1, s1.erase(1)); + FUN_AFTER(s1, s1.erase(s1.begin(), s1.find(3))); + FUN_AFTER(s1, s1.clear()); + FUN_AFTER(s1, s1.swap(s5)); + FUN_VALUE(*s1.begin()); + FUN_VALUE(*s1.rbegin()); + std::cout << std::boolalpha; + FUN_VALUE(s1.empty()); + std::cout << std::noboolalpha; + FUN_VALUE(s1.size()); + FUN_VALUE(s1.max_size()); + PASSED; +#if PERFORMANCE_TEST_ON + std::cout << "[--------------------- Performance Testing ---------------------]" << std::endl; + std::cout << "|---------------------|-------------|-------------|-------------|" << std::endl; + std::cout << "| emplace |"; +#if LARGER_TEST_DATA_ON + CON_TEST_P1(multiset, emplace, rand(), SCALE_M(LEN1), SCALE_M(LEN2), SCALE_M(LEN3)); +#else + CON_TEST_P1(multiset, emplace, rand(), SCALE_S(LEN1), SCALE_S(LEN2), SCALE_S(LEN3)); +#endif + std::cout << std::endl; + std::cout << "|---------------------|-------------|-------------|-------------|" << std::endl; + PASSED; +#endif + std::cout << "[---------------- End container test : multiset ----------------]" << std::endl; +} + +} // namespace set_test +} // namespace test +} // namespace mystl +#endif // !MYTINYSTL_SET_TEST_H_ + diff --git a/src/MyTinySTL-master/MyTinySTL-master/Test/stack_test.h b/src/MyTinySTL-master/MyTinySTL-master/Test/stack_test.h new file mode 100755 index 0000000..4eebdbc --- /dev/null +++ b/src/MyTinySTL-master/MyTinySTL-master/Test/stack_test.h @@ -0,0 +1,103 @@ +#ifndef MYTINYSTL_STACK_TEST_H_ +#define MYTINYSTL_STACK_TEST_H_ + +// stack test : 测试 stack 的接口 和 push 的性能 + +#include + +#include "../MyTinySTL/stack.h" +#include "test.h" + +namespace mystl +{ +namespace test +{ +namespace stack_test +{ + +void stack_print(mystl::stack s) +{ + while (!s.empty()) + { + std::cout << " " << s.top(); + s.pop(); + } + std::cout << std::endl; +} + +// stack 的遍历输出 +#define STACK_COUT(s) do { \ + std::string s_name = #s; \ + std::cout << " " << s_name << " :"; \ + stack_print(s); \ +} while(0) + +#define STACK_FUN_AFTER(con, fun) do { \ + std::string fun_name = #fun; \ + std::cout << " After " << fun_name << " :\n"; \ + fun; \ + STACK_COUT(con); \ +} while(0) + +void stack_test() +{ + std::cout << "[===============================================================]" << std::endl; + std::cout << "[----------------- Run container test : stack ------------------]" << std::endl; + std::cout << "[-------------------------- API test ---------------------------]" << std::endl; + int a[] = { 1,2,3,4,5 }; + mystl::deque d1(5); + mystl::stack s1; + mystl::stack s2(5); + mystl::stack s3(5, 1); + mystl::stack s4(a, a + 5); + mystl::stack s5(d1); + mystl::stack s6(std::move(d1)); + mystl::stack s7(s2); + mystl::stack s8(std::move(s2)); + mystl::stack s9; + s9 = s3; + mystl::stack s10; + s10 = std::move(s3); + mystl::stack s11{ 1,2,3,4,5 }; + mystl::stack s12; + s12 = { 1,2,3,4,5 }; + + STACK_FUN_AFTER(s1, s1.push(1)); + STACK_FUN_AFTER(s1, s1.push(2)); + STACK_FUN_AFTER(s1, s1.push(3)); + STACK_FUN_AFTER(s1, s1.pop()); + STACK_FUN_AFTER(s1, s1.emplace(4)); + STACK_FUN_AFTER(s1, s1.emplace(5)); + std::cout << std::boolalpha; + FUN_VALUE(s1.empty()); + std::cout << std::noboolalpha; + FUN_VALUE(s1.size()); + FUN_VALUE(s1.top()); + while (!s1.empty()) + { + STACK_FUN_AFTER(s1, s1.pop()); + } + STACK_FUN_AFTER(s1, s1.swap(s4)); + STACK_FUN_AFTER(s1, s1.clear()); + PASSED; +#if PERFORMANCE_TEST_ON + std::cout << "[--------------------- Performance Testing ---------------------]" << std::endl; + std::cout << "|---------------------|-------------|-------------|-------------|" << std::endl; + std::cout << "| push |"; +#if LARGER_TEST_DATA_ON + CON_TEST_P1(stack, push, rand(), SCALE_LL(LEN1), SCALE_LL(LEN2), SCALE_LL(LEN3)); +#else + CON_TEST_P1(stack, push, rand(), SCALE_L(LEN1), SCALE_L(LEN2), SCALE_L(LEN3)); +#endif + std::cout << std::endl; + std::cout << "|---------------------|-------------|-------------|-------------|" << std::endl; + PASSED; +#endif + std::cout << "[----------------- End container test : stack ------------------]" << std::endl; +} + +} // namespace stack_test +} // namespace test +} // namespace mystl +#endif // !MYTINYSTL_STACK_TEST_H_ + diff --git a/src/MyTinySTL-master/MyTinySTL-master/Test/string_test.h b/src/MyTinySTL-master/MyTinySTL-master/Test/string_test.h new file mode 100755 index 0000000..7af3811 --- /dev/null +++ b/src/MyTinySTL-master/MyTinySTL-master/Test/string_test.h @@ -0,0 +1,207 @@ +#ifndef MYTINYSTL_STRING_TEST_H_ +#define MYTINYSTL_STRING_TEST_H_ + +// string test : 测试 string 的接口和 insert 的性能 + +#include + +#include "../MyTinySTL/astring.h" +#include "test.h" + +namespace mystl +{ +namespace test +{ +namespace string_test +{ + +void string_test() +{ + std::cout << "[===============================================================]" << std::endl; + std::cout << "[----------------- Run container test : string -----------------]" << std::endl; + std::cout << "[-------------------------- API test ---------------------------]" << std::endl; + const char* s = "abcdefg"; + mystl::string str; + mystl::string str1(5, 'a'); + mystl::string str2(str1, 3); + mystl::string str3(str1, 0, 3); + mystl::string str4("abc"); + mystl::string str5("abcde",3); + mystl::string str6(s, s + 5); + mystl::string str7(str1); + mystl::string str8(std::move(str1)); + mystl::string str9; + str9 = str2; + mystl::string str10; + str10 = std::move(str2); + mystl::string str11; + str11 = "123"; + mystl::string str12; + str12 = 'A'; + + STR_FUN_AFTER(str, str = 'a'); + STR_FUN_AFTER(str, str = "string"); + FUN_VALUE(*str.begin()); + FUN_VALUE(*str.rbegin()); + FUN_VALUE(*(str.end() - 1)); + FUN_VALUE(*(str.rend() - 1)); + FUN_VALUE(str.front()); + FUN_VALUE(str.back()); + FUN_VALUE(str[1]); + FUN_VALUE(str.at(2)); + STR_COUT(str.data()); + STR_COUT(str.c_str()); + std::cout << std::boolalpha; + FUN_VALUE(str.empty()); + std::cout << std::noboolalpha; + FUN_VALUE(str.size()); + FUN_VALUE(str.length()); + FUN_VALUE(str.capacity()); + FUN_VALUE(str.max_size()); + STR_FUN_AFTER(str, str.shrink_to_fit()); + FUN_VALUE(str.capacity()); + + STR_FUN_AFTER(str, str.insert(str.begin(), 'a')); + STR_FUN_AFTER(str, str.insert(str.end(), 3, 'x')); + STR_FUN_AFTER(str, str.insert(str.end(), s, s + 3)); + STR_FUN_AFTER(str, str.erase(str.begin())); + STR_FUN_AFTER(str, str.erase(str.begin(), str.begin() + 3)); + STR_FUN_AFTER(str, str.clear()); + STR_FUN_AFTER(str, str.push_back('s')); + STR_FUN_AFTER(str, str.push_back('t')); + STR_FUN_AFTER(str, str.pop_back()); + STR_FUN_AFTER(str, str.append(1, 't')); + STR_FUN_AFTER(str, str.append(str4)); + STR_FUN_AFTER(str, str.append(str4, 1)); + STR_FUN_AFTER(str, str.append(str4, 2, 1)); + STR_FUN_AFTER(str, str.append("str")); + STR_FUN_AFTER(str, str.append("inging", 3)); + STR_FUN_AFTER(str, str.append(s, s + 3)); + STR_FUN_AFTER(str, str.resize(10)); + FUN_VALUE(str.size()); + STR_FUN_AFTER(str, str.resize(20, 'x')); + FUN_VALUE(str.size()); + STR_FUN_AFTER(str, str.clear()); + + STR_FUN_AFTER(str, str = "string"); + STR_FUN_AFTER(str3, str3 = "astrings"); + FUN_VALUE(str.compare(str3)); + FUN_VALUE(str.compare(0, 6, str3)); + FUN_VALUE(str.compare(0, 6, str3, 1, 6)); + FUN_VALUE(str.compare("atringgg")); + FUN_VALUE(str.compare("zzz")); + FUN_VALUE(str.compare(0, 3, "str")); + FUN_VALUE(str.compare(0, 3, "stri", 4)); + FUN_VALUE(str.compare(0, 3, "s", 2)); + FUN_VALUE(str.compare(0, 9, "stringabc", 9)); + FUN_VALUE(str.substr(0)); + FUN_VALUE(str.substr(3)); + FUN_VALUE(str.substr(0, 3)); + FUN_VALUE(str.substr(0, 10)); + STR_FUN_AFTER(str, str.replace(0, 6, str3)); + STR_FUN_AFTER(str, str.replace(str.end() - 1, str.end(), str3)); + STR_FUN_AFTER(str, str.replace(0, 1, "my ")); + STR_FUN_AFTER(str, str.replace(str.end() - 8, str.end(), " test")); + STR_FUN_AFTER(str, str.replace(10, 4, "replace")); + STR_FUN_AFTER(str, str.replace(str.end(), str.end(), " test")); + STR_FUN_AFTER(str, str.replace(0, 2, 3, '6')); + STR_FUN_AFTER(str, str.replace(str.begin(), str.begin() + 3, 6, '6')); + STR_FUN_AFTER(str, str.replace(0, 3, str3, 1, 3)); + STR_FUN_AFTER(str, str.replace(str.begin(), str.begin() + 6, s, s + 3)); + STR_FUN_AFTER(str, str.reverse()); + STR_FUN_AFTER(str, str.reverse()); + + STR_FUN_AFTER(str, str = "abcabc stringgg"); + STR_FUN_AFTER(str3, str3 = "abc"); + FUN_VALUE(str.find('a')); + FUN_VALUE(str.find('a', 3)); + FUN_VALUE(str.find('a', 4)); + FUN_VALUE(str.find("abc")); + FUN_VALUE(str.find("abc", 1)); + FUN_VALUE(str.find("abc", 1, 1)); + FUN_VALUE(str.find(str3)); + FUN_VALUE(str.find(str3, 1)); + FUN_VALUE(str.rfind('g')); + FUN_VALUE(str.rfind('g', 3)); + FUN_VALUE(str.rfind("gg")); + FUN_VALUE(str.rfind("bc", 10)); + FUN_VALUE(str.rfind(str3)); + FUN_VALUE(str.rfind(str3, 3)); + FUN_VALUE(str.find_first_of('g')); + FUN_VALUE(str.find_first_of('k')); + FUN_VALUE(str.find_first_of("bca")); + FUN_VALUE(str.find_first_of("defg", 10)); + FUN_VALUE(str.find_first_of("gnirts")); + FUN_VALUE(str.find_first_of("abc", 6)); + FUN_VALUE(str.find_first_of("abcdf", 2, 3)); + FUN_VALUE(str.find_first_of(str3, 1)); + FUN_VALUE(str.find_first_of(str3, 10)); + FUN_VALUE(str.find_first_not_of('a')); + FUN_VALUE(str.find_first_not_of('d')); + FUN_VALUE(str.find_first_not_of('g', 14)); + FUN_VALUE(str.find_first_not_of("abc")); + FUN_VALUE(str.find_first_not_of("ggggg", 14, 4)); + FUN_VALUE(str.find_first_not_of(str3)); + FUN_VALUE(str.find_first_not_of(str3, 3)); + FUN_VALUE(str.find_last_of('a')); + FUN_VALUE(str.find_last_of('a', 4)); + FUN_VALUE(str.find_last_of('g')); + FUN_VALUE(str.find_last_of("gg")); + FUN_VALUE(str.find_last_of("gg", 14)); + FUN_VALUE(str.find_last_of("ggg", 14, 1)); + FUN_VALUE(str.find_last_of(str3)); + FUN_VALUE(str.find_last_of(str3, 3)); + FUN_VALUE(str.find_last_not_of('g')); + FUN_VALUE(str.find_last_not_of('a')); + FUN_VALUE(str.find_last_not_of('a', 1)); + FUN_VALUE(str.find_last_not_of("ggg")); + FUN_VALUE(str.find_last_not_of("ggg", 14)); + FUN_VALUE(str.find_last_not_of("abc", 3, 1)); + FUN_VALUE(str.find_last_not_of(str3)); + FUN_VALUE(str.find_last_not_of(str3, 2)); + FUN_VALUE(str.count('a')); + FUN_VALUE(str.count('a', 2)); + FUN_VALUE(str.count('d', 10)); + + STR_FUN_AFTER(str, str.swap(str3)); + FUN_VALUE(str.size()); + FUN_VALUE(str.length()); + FUN_VALUE(str.capacity()); + STR_FUN_AFTER(str, str += str); + STR_FUN_AFTER(str, str += 'a'); + STR_FUN_AFTER(str, str += "bc"); + FUN_VALUE(str.size()); + FUN_VALUE(str.length()); + FUN_VALUE(str.capacity()); + STR_FUN_AFTER(str, str.shrink_to_fit()); + FUN_VALUE(str.capacity()); + STR_FUN_AFTER(str, str.reserve(50)); + FUN_VALUE(str.capacity()); + STR_FUN_AFTER(str3, str3 = "test"); + STR_FUN_AFTER(str4, str4 = " ok!"); + std::cout << " str3 + '!' : " << str3 + '!' << std::endl; + std::cout << " '#' + str3 : " << '#' + str3 << std::endl; + std::cout << " str3 + \" success\" : " << str3 + " success" << std::endl; + std::cout << " \"My \" + str3 : " << "My " + str3 << std::endl; + std::cout << " str3 + str4 : " << str3 + str4 << std::endl; + PASSED; +#if PERFORMANCE_TEST_ON + std::cout << "[--------------------- Performance Testing ---------------------]" << std::endl; + std::cout << "|---------------------|-------------|-------------|-------------|" << std::endl; + std::cout << "| append |"; +#if LARGER_TEST_DATA_ON + CON_TEST_P1(string, append, "s", SCALE_LL(LEN1), SCALE_LL(LEN2), SCALE_LL(LEN3)); +#else + CON_TEST_P1(string, append, "s", SCALE_L(LEN1), SCALE_L(LEN2), SCALE_L(LEN3)); +#endif + std::cout << std::endl; + std::cout << "|---------------------|-------------|-------------|-------------|" << std::endl; + PASSED; +#endif + std::cout << "[----------------- End container test : string -----------------]" << std::endl; +} + +} // namespace string_test +} // namespace test +} // namespace mystl +#endif // !MYTINYSTL_STRING_TEST_H_ diff --git a/src/MyTinySTL-master/MyTinySTL-master/Test/test.cpp b/src/MyTinySTL-master/MyTinySTL-master/Test/test.cpp new file mode 100755 index 0000000..67c795f --- /dev/null +++ b/src/MyTinySTL-master/MyTinySTL-master/Test/test.cpp @@ -0,0 +1,52 @@ +#ifdef _MSC_VER +#define _SCL_SECURE_NO_WARNINGS +#endif + +#if defined(_MSC_VER) && defined(_DEBUG) +#define _CRTDBG_MAP_ALLOC +#include +#include +#endif // check memory leaks + +#include "algorithm_performance_test.h" +#include "algorithm_test.h" +#include "vector_test.h" +#include "list_test.h" +#include "deque_test.h" +#include "queue_test.h" +#include "stack_test.h" +#include "map_test.h" +#include "set_test.h" +#include "unordered_map_test.h" +#include "unordered_set_test.h" +#include "string_test.h" + +int main() +{ + using namespace mystl::test; + + std::cout.sync_with_stdio(false); + + RUN_ALL_TESTS(); + algorithm_performance_test::algorithm_performance_test(); + vector_test::vector_test(); + list_test::list_test(); + deque_test::deque_test(); + queue_test::queue_test(); + queue_test::priority_test(); + stack_test::stack_test(); + map_test::map_test(); + map_test::multimap_test(); + set_test::set_test(); + set_test::multiset_test(); + unordered_map_test::unordered_map_test(); + unordered_map_test::unordered_multimap_test(); + unordered_set_test::unordered_set_test(); + unordered_set_test::unordered_multiset_test(); + string_test::string_test(); + +#if defined(_MSC_VER) && defined(_DEBUG) + _CrtDumpMemoryLeaks(); +#endif // check memory leaks + +} diff --git a/src/MyTinySTL-master/MyTinySTL-master/Test/test.h b/src/MyTinySTL-master/MyTinySTL-master/Test/test.h new file mode 100755 index 0000000..56e9cba --- /dev/null +++ b/src/MyTinySTL-master/MyTinySTL-master/Test/test.h @@ -0,0 +1,717 @@ +#ifndef MYTINYSTL_TEST_H_ +#define MYTINYSTL_TEST_H_ + +// 一个简单的单元测试框架,定义了两个类 TestCase 和 UnitTest,以及一系列用于测试的宏 + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "Lib/redbud/io/color.h" + +namespace mystl +{ +namespace test +{ + +#define green redbud::io::state::manual << redbud::io::hfg::green +#define red redbud::io::state::manual << redbud::io::hfg::red + +#if defined(_MSC_VER) +#pragma warning(disable : 4244) +#pragma warning(disable : 4996) +#endif + +} // namespace test + +namespace test +{ + +// TestCase 类 +// 封装单个测试案例 +class TestCase +{ +public: + // 构造函数,接受一个字符串代表案例名称 + TestCase(const char* case_name) : testcase_name(case_name) {} + + // 一个纯虚函数,用于测试案例 + virtual void Run() = 0; + +public: + const char* testcase_name; // 测试案例的名称 + int nTestResult; // 测试案例的执行结果 + double nFailed; // 测试失败的案例数 + double nPassed; // 测试通过的案例数 +}; + +// UnitTest 类 +// 单元测试,把所有测试案例加入到 vector 中,依次执行测试案例 +class UnitTest +{ +public: + // 获取一个案例 + static UnitTest* GetInstance(); + + // 将案例依次加入 vector + TestCase* RegisterTestCase(TestCase* testcase); + + void Run(); + +public: + TestCase* CurrentTestCase; // 当前执行的测试案例 + double nPassed; // 通过案例数 + double nFailed; // 失败案例数 + +protected: + std::vector testcases_; // 保存案例集合 +}; + +UnitTest* UnitTest::GetInstance() +{ + static UnitTest instance; + return &instance; +} + +TestCase* UnitTest::RegisterTestCase(TestCase* testcase) +{ + testcases_.push_back(testcase); + return testcase; +} + +void UnitTest::Run() +{ + for (auto it : testcases_) + { + TestCase* testcase = it; + CurrentTestCase = testcase; + testcase->nTestResult = 1; + testcase->nFailed = 0; + testcase->nPassed = 0; + std::cout << green << "============================================\n"; + std::cout << green << " Run TestCase:" << testcase->testcase_name << "\n"; + testcase->Run(); + if (testcase->nFailed == 0) + std::cout << green; + else + std::cout << red; + std::cout << " " << testcase->nPassed << " / " << testcase->nFailed + testcase->nPassed + << " Cases passed. ( " << testcase->nPassed / + (testcase->nFailed + testcase->nPassed) * 100 << "% )\n"; + std::cout << green << " End TestCase:" << testcase->testcase_name << "\n"; + if (testcase->nTestResult) + ++nPassed; + else + ++nFailed; + } + std::cout << green << "============================================\n"; + std::cout << green << " Total TestCase : " << nPassed + nFailed << "\n"; + std::cout << green << " Total Passed : " << nPassed << "\n"; + std::cout << red << " Total Failed : " << nFailed << "\n"; + std::cout << green << " " << nPassed << " / " << nFailed + nPassed + << " TestCases passed. ( " << nPassed / (nFailed + nPassed) * 100 << "% )\n"; +} + +/*****************************************************************************************/ + +// 测试案例的类名,替换为 test_cast_TEST +#define TESTCASE_NAME(testcase_name) \ + testcase_name##_TEST + +// 使用宏定义掩盖复杂的测试样例封装过程,把 TEXT 中的测试案例放到单元测试中 +#define MYTINYSTL_TEST_(testcase_name) \ +class TESTCASE_NAME(testcase_name) : public TestCase { \ +public: \ + TESTCASE_NAME(testcase_name)(const char* case_name) \ + : TestCase(case_name) {}; \ + virtual void Run(); \ +private: \ + static TestCase* const testcase_; \ +}; \ + \ +TestCase* const TESTCASE_NAME(testcase_name) \ + ::testcase_ = UnitTest::GetInstance()->RegisterTestCase( \ + new TESTCASE_NAME(testcase_name)(#testcase_name)); \ +void TESTCASE_NAME(testcase_name)::Run() + +/* +Run()后边没有写实现,是为了用宏定义将测试用例放入到 Run 的实现里,例如: +TEST(AddTestDemo) +{ +EXPECT_EQ(3, Add(1, 2)); +EXPECT_EQ(2, Add(1, 1)); +} +上述代码将 { EXPECT_EQ(3, Add(1, 2)); EXPECT_EQ(2, Add(1, 1)); } 接到 Run() 的后面 +*/ + + +/*****************************************************************************************/ + +// 简单测试的宏定义 +// 断言 : 宏定义形式为 EXPECT_* ,符合验证条件的,案例测试通过,否则失败 +// 使用一系列的宏来封装验证条件,分为以下几大类 : + +/* +真假断言 +EXPECT_TRUE 验证条件: Condition 为 true +EXPECT_FALSE 验证条件: Condition 为 false + +Example: +bool isPrime(int n); 一个判断素数的函数 +EXPECT_TRUE(isPrime(2)); 通过 +EXPECT_FALSE(isPrime(4)); 通过 +EXPECT_TRUE(isPrime(6)); 失败 +EXPECT_FALSE(isPrime(3)); 失败 +*/ +#define EXPECT_TRUE(Condition) do { \ + if (Condition) { \ + UnitTest::GetInstance()->CurrentTestCase->nPassed++; \ + std::cout << green << " EXPECT_TRUE succeeded!\n"; \ + } \ + else { \ + UnitTest::GetInstance()->CurrentTestCase->nTestResult = 0; \ + UnitTest::GetInstance()->CurrentTestCase->nFailed++; \ + std::cout << red << " EXPECT_TRUE failed!\n"; \ +}} while(0) + +#define EXPECT_FALSE(Condition) do { \ + if (!Condition) { \ + UnitTest::GetInstance()->CurrentTestCase->nPassed++; \ + std::cout << green << " EXPECT_FALSE succeeded!\n"; \ + } \ + else { \ + UnitTest::GetInstance()->CurrentTestCase->nTestResult = 0; \ + UnitTest::GetInstance()->CurrentTestCase->nFailed++; \ + std::cout << red << " EXPECT_FALSE failed!\n"; \ +}} while(0) + +/* +比较断言 +EXPECT_EQ(v1, v2) 验证条件: v1 == v2 +EXPECT_NE(v1, v2) 验证条件: v1 != v2 +EXPECT_LT(v1, v2) 验证条件: v1 < v2 +EXPECT_LE(v1, v2) 验证条件: v1 <= v2 +EXPECT_GT(v1, v2) 验证条件: v1 > v2 +EXPECT_GE(v1, v2) 验证条件: v1 >= v2 + +Note: +1. 参数应满足 EXPECT_*(Expect, Actual)的格式,左边是期望值,右边是实际值 +2. 在断言失败时,会将期望值与实际值打印出来 +3. 参数值必须是可通过断言的比较操作符进行比较的,参数值还必须支持 << 操作符来 +将值输入到 ostream 中 +4. 这些断言可以用于用户自定义型别,但必须重载相应的比较操作符(如 == 、< 等) +5. EXPECT_EQ 对指针进行的是地址比较。即比较的是它们是否指向相同的内存地址, +而不是它们指向的内容是否相等。如果想比较两个 C 字符串(const char*)的值, +请使用 EXPECT_STREQ 。特别一提的是,要验证一个 C 字符串是否为空(NULL), +请使用 EXPECT_STREQ(NULL, c_str)。但是要比较两个 string 对象时, +应该使用 EXPECT_EQ + +Example: +EXPECT_EQ(3, foo()); +EXPECT_NE(NULL, pointer); +EXPECT_LT(len, v.size()); +*/ +#define EXPECT_EQ(v1, v2) do { \ + if (v1 == v2) { \ + UnitTest::GetInstance()->CurrentTestCase->nPassed++; \ + std::cout << green << " EXPECT_EQ succeeded!\n"; \ + } \ + else { \ + UnitTest::GetInstance()->CurrentTestCase->nTestResult = 0; \ + UnitTest::GetInstance()->CurrentTestCase->nFailed++; \ + std::cout << red << " EXPECT_EQ failed!\n"; \ + std::cout << red << " Expect:" << v1 << "\n"; \ + std::cout << red << " Actual:" << v2 << "\n"; \ +}} while(0) + +#define EXPECT_NE(v1, v2) do { \ + if (v1 != v2) { \ + UnitTest::GetInstance()->CurrentTestCase->nPassed++; \ + std::cout << green << " EXPECT_NE succeeded!\n"; \ + } \ + else { \ + UnitTest::GetInstance()->CurrentTestCase->nTestResult = 0; \ + UnitTest::GetInstance()->CurrentTestCase->nFailed++; \ + std::cout << red << " EXPECT_NE failed!\n"; \ + std::cout << red << " Expect:" << v1 << "\n"; \ + std::cout << red << " Actual:" << v2 << "\n"; \ +}} while(0) + +#define EXPECT_LT(v1, v2) do { \ + if (v1 < v2) { \ + UnitTest::GetInstance()->CurrentTestCase->nPassed++; \ + std::cout << green << " EXPECT_LT succeeded!\n"; \ + } \ + else { \ + UnitTest::GetInstance()->CurrentTestCase->nTestResult = 0; \ + UnitTest::GetInstance()->CurrentTestCase->nFailed++; \ + std::cout << red << " EXPECT_LT failed!\n"; \ + std::cout << red << " Expect:" << v1 << "\n"; \ + std::cout << red << " Actual:" << v2 << "\n"; \ +}} while(0) + +#define EXPECT_LE(v1, v2) do { \ + if (v1 <= v2) { \ + UnitTest::GetInstance()->CurrentTestCase->nPassed++; \ + std::cout << green << " EXPECT_LE succeeded!\n"; \ + } \ + else { \ + UnitTest::GetInstance()->CurrentTestCase->nTestResult = 0; \ + UnitTest::GetInstance()->CurrentTestCase->nFailed++; \ + std::cout << red << " EXPECT_LE failed!\n"; \ + std::cout << red << " Expect:" << v1 << "\n"; \ + std::cout << red << " Actual:" << v2 << "\n"; \ +}} while(0) + +#define EXPECT_GT(v1, v2) do { \ + if (v1 > v2) { \ + UnitTest::GetInstance()->CurrentTestCase->nPassed++; \ + std::cout << green << " EXPECT_GT succeeded!\n"; \ + } \ + else { \ + UnitTest::GetInstance()->CurrentTestCase->nTestResult = 0; \ + UnitTest::GetInstance()->CurrentTestCase->nFailed++; \ + std::cout << red << " EXPECT_GT failed!\n"; \ + std::cout << red << " Expect:" << v1 << "\n"; \ + std::cout << red << " Actual:" << v2 << "\n"; \ +}} while(0) + +#define EXPECT_GE(v1, v2) do { \ + if (v1 >= v2) { \ + UnitTest::GetInstance()->CurrentTestCase->nPassed++; \ + std::cout << green << " EXPECT_GE succeeded!\n"; \ + } \ + else { \ + UnitTest::GetInstance()->CurrentTestCase->nTestResult = 0; \ + UnitTest::GetInstance()->CurrentTestCase->nFailed++; \ + std::cout << red << " EXPECT_GE failed!\n"; \ + std::cout << red << " Expect:" << v1 << "\n"; \ + std::cout << red << " Actual:" << v2 << "\n"; \ +}} while(0) + +/* +字符串比较 +EXPECT_STREQ(s1, s2) 验证条件: 两个 C 字符串有相同的值 +EXPECT_STRNE(s1, s2) 验证条件: 两个 C 字符串有不同的值 + +Note: +1. 参数应满足 EXPECT_STR*(Expect, Actual)的格式,左边是期望值,右边是实际值 +2. 该组断言用于比较两个 C 字符串。如果你想要比较两个 string 对象,相应地使用 +EXPECT_EQ、EXPECT_NE 等断言 +3. EXPECT_STREQ 和 EXPECT_STRNE 不接受宽字符串(wchar_t*) +4. 一个 NULL 指针和一个空字符串会不是一样的 + +Example: +char* s1 = "", char* s2 = "abc", char* s3 = NULL; +EXPECT_STREQ("abc", s2); 通过 +EXPECT_STREQ(s1, s3); 失败 +EXPECT_STREQ(NULL, s3); 通过 +EXPECT_STRNE(" ", s1); 通过 +*/ + +#define EXPECT_STREQ(s1, s2) do { \ + if (s1 == NULL || s2 == NULL) { \ + if (s1 == NULL && s2 == NULL) { \ + UnitTest::GetInstance()->CurrentTestCase->nPassed++; \ + std::cout << green << " EXPECT_STRED succeeded!\n"; \ + } \ + else { \ + UnitTest::GetInstance()->CurrentTestCase->nTestResult = 0; \ + UnitTest::GetInstance()->CurrentTestCase->nFailed++; \ + std::cout << red << " EXPECT_STRED failed!\n"; \ + if(s1 == NULL) std::cout << " Expect: NULL\n"; \ + else std::cout << " Expect:\"" << s1 << "\"\n"; \ + if(s2 == NULL) std::cout << " Actual: NULL\n"; \ + else std::cout << " Actual:\"" << s2 << "\"\n"; \ + } \ + } \ + else if (strcmp(s1, s2) == 0) { \ + UnitTest::GetInstance()->CurrentTestCase->nPassed++; \ + std::cout << green << " EXPECT_STRED succeeded!\n"; \ + } \ + else { \ + UnitTest::GetInstance()->CurrentTestCase->nTestResult = 0; \ + UnitTest::GetInstance()->CurrentTestCase->nFailed++; \ + std::cout << red << " EXPECT_STRED failed!\n"; \ + std::cout << red << " Expect:\"" << s1 << "\"\n"; \ + std::cout << red << " Actual:\"" << s2 << "\"\n"; \ +}} while(0) + +#define EXPECT_STRNE(s1, s2) do { \ + if (s1 == NULL || s2 == NULL) { \ + if (s1 != NULL || s2 != NULL) { \ + UnitTest::GetInstance()->CurrentTestCase->nPassed++; \ + std::cout << green << " EXPECT_STRNE succeeded!\n"; \ + } \ + else { \ + UnitTest::GetInstance()->CurrentTestCase->nTestResult = 0; \ + UnitTest::GetInstance()->CurrentTestCase->nFailed++; \ + std::cout << red << " EXPECT_STRNE failed!\n"; \ + if(s1 == NULL) std::cout << " Expect: NULL\n"; \ + else std::cout << " Expect:\"" << s1 << "\"\n"; \ + if(s2 == NULL) std::cout << " Actual: NULL\n"; \ + else std::cout << " Actual:\"" << s2 << "\"\n"; \ + } \ + } \ + else if (strcmp(s1, s2) != 0) { \ + UnitTest::GetInstance()->CurrentTestCase->nPassed++; \ + std::cout << green << " EXPECT_STRNE succeeded!\n"; \ + } \ + else { \ + UnitTest::GetInstance()->CurrentTestCase->nTestResult = 0; \ + UnitTest::GetInstance()->CurrentTestCase->nFailed++; \ + std::cout << red << " EXPECT_STRNE failed!\n"; \ + std::cout << red << " Expect:\"" << s1 << "\"\n"; \ + std::cout << red << " Actual:\"" << s2 << "\"\n"; \ +}} while(0) + +/* +指针比较 +EXPECT_PTR_EQ(p1, p2) 验证条件: *p1 == *p2 +EXPECT_PTR_NE(p1, p2) 验证条件: *p1 != *p2 +EXPECT_PTR_RANGE_EQ(p1, p2, len) 验证条件: 任意 i (*p1 + i) == (*p2 + i) i∈[0,len) +EXPECT_PTR_RANGE_NE(p1, p2, len) 验证条件: 存在 i (*p1 + i) != (*p2 + i) i∈[0,len) + +Note: +1. 参数应满足 EXPECT_PTR_*(Expect, Actual)、 +EXPECT_PTR_RANGE_*(Expect, Actual, len)的格式, +即参数表中期望值在实际值左边 +2. EXPECT_PTR_EQ 比较的是指针所指元素的值,如果要比较 +指针指向的地址是否相等,请用 EXPECT_EQ +3. EXPECT_PTR_RANGE_* 比较的是从 p1,p2 开始, +长度为 len 的区间,请确保区间长度有效 + +Example: +int a[] = {1,2,3,4,5}; +int b[] = {1,2,3,4,6}; +int *p1 = a, *p2 = b; +EXPECT_PTR_EQ(p1, p2); 通过 +p1 = a + 4, p2 = b + 4; +EXPECT_PTR_EQ(p1, p2); 失败 +EXPECT_PTR_EQ(p1, std::find(a, a + 5, 5)); 通过 +EXPECT_PTR_RANGE_EQ(a, b, 5); 失败 +EXPECT_PTR_RANGE_EQ(a, b, 4); 通过 +*/ +#define EXPECT_PTR_EQ(p1, p2) do { \ + if (*p1 == *p2) { \ + UnitTest::GetInstance()->CurrentTestCase->nPassed++; \ + std::cout << green << " EXPECT_PTR_EQ succeeded!\n"; \ + } \ + else { \ + UnitTest::GetInstance()->CurrentTestCase->nTestResult = 0; \ + UnitTest::GetInstance()->CurrentTestCase->nFailed++; \ + std::cout << red << " EXPECT_PTR_EQ failed!\n"; \ + std::cout << red << " Expect:" << *p1 << "\n"; \ + std::cout << red << " Actual:" << *p2 << "\n"; \ +}} while(0) + +#define EXPECT_PTR_NE(p1, p2) do { \ + if (*p1 != *p2) { \ + UnitTest::GetInstance()->CurrentTestCase->nPassed++; \ + std::cout << green << " EXPECT_PTR_NE succeeded!\n"; \ + } \ + else { \ + UnitTest::GetInstance()->CurrentTestCase->nTestResult = 0; \ + UnitTest::GetInstance()->CurrentTestCase->nFailed++; \ + std::cout << red << " EXPECT_PTR_NE failed!\n"; \ + std::cout << red << " Expect:" << *p1 << "\n"; \ + std::cout << red << " Actual:" << *p2 << "\n"; \ +}} while(0) + +#define EXPECT_PTR_RANGE_EQ(p1, p2, len) do { \ + if (std::equal(p1, p1 + len, p2)) { \ + UnitTest::GetInstance()->CurrentTestCase->nPassed++; \ + std::cout << green << " EXPECT_PTR_RANGE_EQ succeeded!\n"; \ + } \ + else { \ + UnitTest::GetInstance()->CurrentTestCase->nTestResult = 0; \ + UnitTest::GetInstance()->CurrentTestCase->nFailed++; \ + std::cout << red << " EXPECT_PTR_RANGE_EQ failed!\n"; \ +}} while(0) + +#define EXPECT_PTR_RANGE_NE(p1, p2, len) do { \ + if (!std::equal(p1, p1 + len, p2)) { \ + UnitTest::GetInstance()->CurrentTestCase->nPassed++; \ + std::cout << green << " EXPECT_PTR_RANGE_NE succeeded!\n"; \ + } \ + else { \ + UnitTest::GetInstance()->CurrentTestCase->nTestResult = 0; \ + UnitTest::GetInstance()->CurrentTestCase->nFailed++; \ + std::cout << red << " EXPECT_PTR_RANGE_NE failed!\n"; \ +}} while(0) + +/* +容器比较 +EXPECT_CON_EQ(c1, c2) 验证条件: c1 == c2 +EXPECT_CON_NE(c1, c2) 验证条件: c1 != c2 + +Note: +1. 容器可以是 STL 容器,自定义的容器,或者数组,但不可以是指针 +2. 容器的数据类型要能够进行比较,类型一致或可以发生隐式转换 +3. EXPECT_CON_EQ 测试失败时,会打印首次不相等的两个值 + +Example: +int arr[] = {1,2,3}; +std::vector v1{1, 2, 3}; +std::vector v2{2, 3, 4}; +mystl::vector v3(arr, arr + 3); +EXPECT_CON_NE(v1, v2) ok +EXPECT_CON_EQ(arr, v1) ok +EXPECT_CON_EQ(v1, v3) ok +*/ +#define EXPECT_CON_EQ(c1, c2) do { \ + auto first1 = std::begin(c1), last1 = std::end(c1); \ + auto first2 = std::begin(c2), last2 = std::end(c2); \ + for (; first1 != last1 && first2 != last2; ++first1, ++first2) { \ + if (*first1 != *first2) break; \ + } \ + if (first1 == last1 && first2 == last2) { \ + UnitTest::GetInstance()->CurrentTestCase->nPassed++; \ + std::cout << green << " EXPECT_CON_EQ succeeded!\n"; \ + } \ + else { \ + UnitTest::GetInstance()->CurrentTestCase->nTestResult = 0; \ + UnitTest::GetInstance()->CurrentTestCase->nFailed++; \ + std::cout << red << " EXPECT_CON_EQ failed!\n"; \ + std::cout << red << " Expect:" << *first1 << "\n"; \ + std::cout << red << " Actual:" << *first2 << "\n"; \ +}} while(0) + +#define EXPECT_CON_NE(c1, c2) do { \ + auto first1 = std::begin(c1), last1 = std::end(c1); \ + auto first2 = std::begin(c2), last2 = std::end(c2); \ + for (; first1 != last1 && first2 != last2; ++first1, ++first2) { \ + if (*first1 != *first2) break; \ + } \ + if (first1 != last1 || first2 != last2) { \ + UnitTest::GetInstance()->CurrentTestCase->nPassed++; \ + std::cout << green << " EXPECT_CON_NE succeeded!\n"; \ + } \ + else { \ + UnitTest::GetInstance()->CurrentTestCase->nTestResult = 0; \ + UnitTest::GetInstance()->CurrentTestCase->nFailed++; \ + std::cout << red << " EXPECT_CON_NE failed!\n"; \ +}} while(0) + +/*****************************************************************************************/ +// 常用的宏定义 + +// 不同情况的测试数量级 +#if defined(_DEBUG) || defined(DEBUG) +#define LEN1 10000 +#define LEN2 100000 +#define LEN3 1000000 +#else +#define LEN1 100000 +#define LEN2 1000000 +#define LEN3 10000000 +#endif + +#define SCALE_LLL(N) (N * 20) +#define SCALE_LL(N) (N * 10) +#define SCALE_L(N) (N * 5) +#define SCALE_M(N) (N) +#define SCALE_S(N) (N / 5) +#define SCALE_SS(N) (N / 10) +#define SCALE_SSS(N) (N / 20) + +#define WIDE 14 + +// 输出通过提示 +#define PASSED std::cout << "[ PASSED ]\n" + +// 遍历输出容器 +#define COUT(container) do { \ + std::string con_name = #container; \ + std::cout << " " << con_name << " :"; \ + for (auto it : container) \ + std::cout << " " << it; \ + std::cout << "\n"; \ +} while(0) + +#define STR_COUT(str) do { \ + std::string str_name = #str; \ + std::cout << " " << str_name << " : " << str << "\n"; \ +} while(0) + +// 输出容器调用函数后的结果 +#define FUN_AFTER(con, fun) do { \ + std::string fun_name = #fun; \ + std::cout << " After " << fun_name << " :\n"; \ + fun; \ + COUT(con); \ +} while(0) + +#define STR_FUN_AFTER(str, fun) do { \ + std::string fun_name = #fun; \ + std::cout << " After " << fun_name << " :\n"; \ + fun; \ + STR_COUT(str); \ +} while(0) + +// 输出容器调用函数的值 +#define FUN_VALUE(fun) do { \ + std::string fun_name = #fun; \ + std::cout << " " << fun_name << " : " << fun << "\n"; \ +} while(0) + +// 输出测试数量级 +void test_len(size_t len1, size_t len2, size_t len3, size_t wide) +{ + std::string str1, str2, str3; + std::stringstream ss; + ss << len1 << " " << len2 << " " << len3; + ss >> str1 >> str2 >> str3; + str1 += " |"; + std::cout << std::setw(wide) << str1; + str2 += " |"; + std::cout << std::setw(wide) << str2; + str3 += " |"; + std::cout << std::setw(wide) << str3 << "\n"; +} + +#define TEST_LEN(len1, len2, len3, wide) \ + test_len(len1, len2, len3, wide) + +// 常用测试性能的宏 +#define FUN_TEST_FORMAT1(mode, fun, arg, count) do { \ + srand((int)time(0)); \ + clock_t start, end; \ + mode c; \ + char buf[10]; \ + start = clock(); \ + for (size_t i = 0; i < count; ++i) \ + c.fun(arg); \ + end = clock(); \ + int n = static_cast(static_cast(end - start) \ + / CLOCKS_PER_SEC * 1000); \ + std::snprintf(buf, sizeof(buf), "%d", n); \ + std::string t = buf; \ + t += "ms |"; \ + std::cout << std::setw(WIDE) << t; \ +} while(0) + +#define FUN_TEST_FORMAT2(mode, fun, arg1, arg2, count) do { \ + srand((int)time(0)); \ + clock_t start, end; \ + mode c; \ + char buf[10]; \ + start = clock(); \ + for (size_t i = 0; i < count; ++i) \ + c.fun(c.arg1(), arg2); \ + end = clock(); \ + int n = static_cast(static_cast(end - start) \ + / CLOCKS_PER_SEC * 1000); \ + std::snprintf(buf, sizeof(buf), "%d", n); \ + std::string t = buf; \ + t += "ms |"; \ + std::cout << std::setw(WIDE) << t; \ +} while(0) + +#define LIST_SORT_DO_TEST(mode, count) do { \ + srand((int)time(0)); \ + clock_t start, end; \ + mode::list l; \ + char buf[10]; \ + for (size_t i = 0; i < count; ++i) \ + l.insert(l.end(), rand()); \ + start = clock(); \ + l.sort(); \ + end = clock(); \ + int n = static_cast(static_cast(end - start) \ + / CLOCKS_PER_SEC * 1000); \ + std::snprintf(buf, sizeof(buf), "%d", n); \ + std::string t = buf; \ + t += "ms |"; \ + std::cout << std::setw(WIDE) << t; \ +} while(0) + +#define MAP_EMPLACE_DO_TEST(mode, con, count) do { \ + srand((int)time(0)); \ + clock_t start, end; \ + mode::con c; \ + char buf[10]; \ + start = clock(); \ + for (size_t i = 0; i < count; ++i) \ + c.emplace(mode::make_pair(rand(), rand())); \ + end = clock(); \ + int n = static_cast(static_cast(end - start) \ + / CLOCKS_PER_SEC * 1000); \ + std::snprintf(buf, sizeof(buf), "%d", n); \ + std::string t = buf; \ + t += "ms |"; \ + std::cout << std::setw(WIDE) << t; \ +} while(0) + +// 重构重复代码 +#define CON_TEST_P1(con, fun, arg, len1, len2, len3) \ + TEST_LEN(len1, len2, len3, WIDE); \ + std::cout << "| std |"; \ + FUN_TEST_FORMAT1(std::con, fun, arg, len1); \ + FUN_TEST_FORMAT1(std::con, fun, arg, len2); \ + FUN_TEST_FORMAT1(std::con, fun, arg, len3); \ + std::cout << "\n| mystl |"; \ + FUN_TEST_FORMAT1(mystl::con, fun, arg, len1); \ + FUN_TEST_FORMAT1(mystl::con, fun, arg, len2); \ + FUN_TEST_FORMAT1(mystl::con, fun, arg, len3); + +#define CON_TEST_P2(con, fun, arg1, arg2, len1, len2, len3) \ + TEST_LEN(len1, len2, len3, WIDE); \ + std::cout << "| std |"; \ + FUN_TEST_FORMAT2(std::con, fun, arg1, arg2, len1); \ + FUN_TEST_FORMAT2(std::con, fun, arg1, arg2, len2); \ + FUN_TEST_FORMAT2(std::con, fun, arg1, arg2, len3); \ + std::cout << "\n| mystl |"; \ + FUN_TEST_FORMAT2(mystl::con, fun, arg1, arg2, len1); \ + FUN_TEST_FORMAT2(mystl::con, fun, arg1, arg2, len2); \ + FUN_TEST_FORMAT2(mystl::con, fun, arg1, arg2, len3); + +#define MAP_EMPLACE_TEST(con, len1, len2, len3) \ + TEST_LEN(len1, len2, len3, WIDE); \ + std::cout << "| std |"; \ + MAP_EMPLACE_DO_TEST(std, con, len1); \ + MAP_EMPLACE_DO_TEST(std, con, len2); \ + MAP_EMPLACE_DO_TEST(std, con, len3); \ + std::cout << "\n| mystl |"; \ + MAP_EMPLACE_DO_TEST(mystl, con, len1); \ + MAP_EMPLACE_DO_TEST(mystl, con, len2); \ + MAP_EMPLACE_DO_TEST(mystl, con, len3); + +#define LIST_SORT_TEST(len1, len2, len3) \ + TEST_LEN(len1, len2, len3, WIDE); \ + std::cout << "| std |"; \ + LIST_SORT_DO_TEST(std, len1); \ + LIST_SORT_DO_TEST(std, len2); \ + LIST_SORT_DO_TEST(std, len3); \ + std::cout << "\n| mystl |"; \ + LIST_SORT_DO_TEST(mystl, len1); \ + LIST_SORT_DO_TEST(mystl, len2); \ + LIST_SORT_DO_TEST(mystl, len3); + +// 简单测试的宏定义 +#define TEST(testcase_name) \ + MYTINYSTL_TEST_(testcase_name) + +// 运行所有测试案例 +#define RUN_ALL_TESTS() \ + mystl::test::UnitTest::GetInstance()->Run() + +// 是否开启性能测试 +#ifndef PERFORMANCE_TEST_ON +#define PERFORMANCE_TEST_ON 1 +#endif // !PERFORMANCE_TEST_ON + +// 是否开启大数据量测试 +#ifndef LARGER_TEST_DATA_ON +#define LARGER_TEST_DATA_ON 0 +#endif // !LARGER_TEST_DATA_ON + +} // namespace test +} // namespace mystl +#endif // !MYTINYSTL_TEST_H_ + diff --git a/src/MyTinySTL-master/MyTinySTL-master/Test/unordered_map_test.h b/src/MyTinySTL-master/MyTinySTL-master/Test/unordered_map_test.h new file mode 100755 index 0000000..68dc96d --- /dev/null +++ b/src/MyTinySTL-master/MyTinySTL-master/Test/unordered_map_test.h @@ -0,0 +1,203 @@ +#ifndef MYTINYSTL_UNORDERED_MAP_TEST_H_ +#define MYTINYSTL_UNORDERED_MAP_TEST_H_ + +// unordered_map test : 测试 unordered_map, unordered_multimap 的接口与它们 insert 的性能 + +#include + +#include "../MyTinySTL/unordered_map.h" +#include "map_test.h" +#include "test.h" + +namespace mystl +{ +namespace test +{ +namespace unordered_map_test +{ + +void unordered_map_test() +{ + std::cout << "[===============================================================]" << std::endl; + std::cout << "[-------------- Run container test : unordered_map -------------]" << std::endl; + std::cout << "[-------------------------- API test ---------------------------]" << std::endl; + mystl::vector v; + for (int i = 0; i < 5; ++i) + v.push_back(PAIR(5 - i, 5 - i)); + mystl::unordered_map um1; + mystl::unordered_map um2(520); + mystl::unordered_map um3(520, mystl::hash()); + mystl::unordered_map um4(520, mystl::hash(), mystl::equal_to()); + mystl::unordered_map um5(v.begin(), v.end()); + mystl::unordered_map um6(v.begin(), v.end(), 100); + mystl::unordered_map um7(v.begin(), v.end(), 100, mystl::hash()); + mystl::unordered_map um8(v.begin(), v.end(), 100, mystl::hash(), mystl::equal_to()); + mystl::unordered_map um9(um5); + mystl::unordered_map um10(std::move(um5)); + mystl::unordered_map um11; + um11 = um6; + mystl::unordered_map um12; + um12 = std::move(um6); + mystl::unordered_map um13{ PAIR(1,1),PAIR(2,3),PAIR(3,3) }; + mystl::unordered_map um14; + um14 = { PAIR(1,1),PAIR(2,3),PAIR(3,3) }; + + MAP_FUN_AFTER(um1, um1.emplace(1, 1)); + MAP_FUN_AFTER(um1, um1.emplace_hint(um1.begin(), 1, 2)); + MAP_FUN_AFTER(um1, um1.insert(PAIR(2, 2))); + MAP_FUN_AFTER(um1, um1.insert(um1.end(), PAIR(3, 3))); + MAP_FUN_AFTER(um1, um1.insert(v.begin(), v.end())); + MAP_FUN_AFTER(um1, um1.erase(um1.begin())); + MAP_FUN_AFTER(um1, um1.erase(um1.begin(), um1.find(3))); + MAP_FUN_AFTER(um1, um1.erase(1)); + std::cout << std::boolalpha; + FUN_VALUE(um1.empty()); + std::cout << std::noboolalpha; + FUN_VALUE(um1.size()); + FUN_VALUE(um1.bucket_count()); + FUN_VALUE(um1.max_bucket_count()); + FUN_VALUE(um1.bucket(1)); + FUN_VALUE(um1.bucket_size(um1.bucket(5))); + MAP_FUN_AFTER(um1, um1.clear()); + MAP_FUN_AFTER(um1, um1.swap(um7)); + MAP_VALUE(*um1.begin()); + FUN_VALUE(um1.at(1)); + FUN_VALUE(um1[1]); + std::cout << std::boolalpha; + FUN_VALUE(um1.empty()); + std::cout << std::noboolalpha; + FUN_VALUE(um1.size()); + FUN_VALUE(um1.max_size()); + FUN_VALUE(um1.bucket_count()); + FUN_VALUE(um1.max_bucket_count()); + FUN_VALUE(um1.bucket(1)); + FUN_VALUE(um1.bucket_size(um1.bucket(1))); + MAP_FUN_AFTER(um1, um1.reserve(1000)); + FUN_VALUE(um1.size()); + FUN_VALUE(um1.bucket_count()); + FUN_VALUE(um1.bucket_size(1)); + FUN_VALUE(um1.bucket_size(2)); + FUN_VALUE(um1.bucket_size(3)); + MAP_FUN_AFTER(um1, um1.rehash(150)); + FUN_VALUE(um1.bucket_count()); + FUN_VALUE(um1.count(1)); + MAP_VALUE(*um1.find(3)); + auto first = *um1.equal_range(3).first; + auto second = *um1.equal_range(3).second; + std::cout << " um1.equal_range(3) : from <" << first.first << ", " << first.second + << "> to <" << second.first << ", " << second.second << ">" << std::endl; + FUN_VALUE(um1.load_factor()); + FUN_VALUE(um1.max_load_factor()); + MAP_FUN_AFTER(um1, um1.max_load_factor(1.5f)); + FUN_VALUE(um1.max_load_factor()); + PASSED; +#if PERFORMANCE_TEST_ON + std::cout << "[--------------------- Performance Testing ---------------------]" << std::endl; + std::cout << "|---------------------|-------------|-------------|-------------|" << std::endl; + std::cout << "| emplace |"; +#if LARGER_TEST_DATA_ON + MAP_EMPLACE_TEST(unordered_map, SCALE_M(LEN1), SCALE_M(LEN2), SCALE_M(LEN3)); +#else + MAP_EMPLACE_TEST(unordered_map, SCALE_S(LEN1), SCALE_S(LEN2), SCALE_S(LEN3)); +#endif + std::cout << std::endl; + std::cout << "|---------------------|-------------|-------------|-------------|" << std::endl; + PASSED; +#endif + std::cout << "[-------------- End container test : unordered_map -------------]" << std::endl; +} + +void unordered_multimap_test() +{ + std::cout << "[===============================================================]" << std::endl; + std::cout << "[----------- Run container test : unordered_multimap -----------]" << std::endl; + std::cout << "[-------------------------- API test ---------------------------]" << std::endl; + mystl::vector v; + for (int i = 0; i < 5; ++i) + v.push_back(PAIR(5 - i, 5 - i)); + mystl::unordered_multimap um1; + mystl::unordered_multimap um2(520); + mystl::unordered_multimap um3(520, mystl::hash()); + mystl::unordered_multimap um4(520, mystl::hash(), mystl::equal_to()); + mystl::unordered_multimap um5(v.begin(), v.end()); + mystl::unordered_multimap um6(v.begin(), v.end(), 100); + mystl::unordered_multimap um7(v.begin(), v.end(), 100, mystl::hash()); + mystl::unordered_multimap um8(v.begin(), v.end(), 100, mystl::hash(), mystl::equal_to()); + mystl::unordered_multimap um9(um5); + mystl::unordered_multimap um10(std::move(um5)); + mystl::unordered_multimap um11; + um11 = um6; + mystl::unordered_multimap um12; + um12 = std::move(um6); + mystl::unordered_multimap um13{ PAIR(1,1),PAIR(2,3),PAIR(3,3) }; + mystl::unordered_multimap um14; + um14 = { PAIR(1,1),PAIR(2,3),PAIR(3,3) }; + + MAP_FUN_AFTER(um1, um1.emplace(1, 1)); + MAP_FUN_AFTER(um1, um1.emplace_hint(um1.begin(), 1, 2)); + MAP_FUN_AFTER(um1, um1.insert(PAIR(2, 2))); + MAP_FUN_AFTER(um1, um1.insert(um1.end(), PAIR(3, 3))); + MAP_FUN_AFTER(um1, um1.insert(v.begin(), v.end())); + MAP_FUN_AFTER(um1, um1.erase(um1.begin())); + MAP_FUN_AFTER(um1, um1.erase(um1.begin(), um1.find(3))); + MAP_FUN_AFTER(um1, um1.erase(1)); + std::cout << std::boolalpha; + FUN_VALUE(um1.empty()); + std::cout << std::noboolalpha; + FUN_VALUE(um1.size()); + FUN_VALUE(um1.bucket_count()); + FUN_VALUE(um1.max_bucket_count()); + FUN_VALUE(um1.bucket(1)); + FUN_VALUE(um1.bucket_size(um1.bucket(5))); + MAP_FUN_AFTER(um1, um1.clear()); + MAP_FUN_AFTER(um1, um1.swap(um7)); + MAP_VALUE(*um1.begin()); + std::cout << std::boolalpha; + FUN_VALUE(um1.empty()); + std::cout << std::noboolalpha; + FUN_VALUE(um1.size()); + FUN_VALUE(um1.max_size()); + FUN_VALUE(um1.bucket_count()); + FUN_VALUE(um1.max_bucket_count()); + FUN_VALUE(um1.bucket(1)); + FUN_VALUE(um1.bucket_size(um1.bucket(1))); + MAP_FUN_AFTER(um1, um1.reserve(1000)); + FUN_VALUE(um1.size()); + FUN_VALUE(um1.bucket_count()); + FUN_VALUE(um1.bucket_size(1)); + FUN_VALUE(um1.bucket_size(2)); + FUN_VALUE(um1.bucket_size(3)); + MAP_FUN_AFTER(um1, um1.rehash(150)); + FUN_VALUE(um1.bucket_count()); + FUN_VALUE(um1.count(1)); + MAP_VALUE(*um1.find(3)); + auto first = *um1.equal_range(3).first; + auto second = *um1.equal_range(3).second; + std::cout << " um1.equal_range(3) : from <" << first.first << ", " << first.second + << "> to <" << second.first << ", " << second.second << ">" << std::endl; + FUN_VALUE(um1.load_factor()); + FUN_VALUE(um1.max_load_factor()); + MAP_FUN_AFTER(um1, um1.max_load_factor(1.5f)); + FUN_VALUE(um1.max_load_factor()); + PASSED; +#if PERFORMANCE_TEST_ON + std::cout << "[--------------------- Performance Testing ---------------------]" << std::endl; + std::cout << "|---------------------|-------------|-------------|-------------|" << std::endl; + std::cout << "| emplace |"; +#if LARGER_TEST_DATA_ON + MAP_EMPLACE_TEST(unordered_multimap, SCALE_M(LEN1), SCALE_M(LEN2), SCALE_M(LEN3)); +#else + MAP_EMPLACE_TEST(unordered_multimap, SCALE_S(LEN1), SCALE_S(LEN2), SCALE_S(LEN3)); +#endif + std::cout << std::endl; + std::cout << "|---------------------|-------------|-------------|-------------|" << std::endl; + PASSED; +#endif + std::cout << "[----------- End container test : unordered_multimap -----------]" << std::endl; +} + +} // namespace unordered_map_test +} // namespace test +} // namespace mystl +#endif // !MYTINYSTL_UNORDERED_MAP_TEST_H_ + diff --git a/src/MyTinySTL-master/MyTinySTL-master/Test/unordered_set_test.h b/src/MyTinySTL-master/MyTinySTL-master/Test/unordered_set_test.h new file mode 100755 index 0000000..82b99a2 --- /dev/null +++ b/src/MyTinySTL-master/MyTinySTL-master/Test/unordered_set_test.h @@ -0,0 +1,191 @@ +#ifndef MYTINYSTL_UNORDERED_SET_TEST_H_ +#define MYTINYSTL_UNORDERED_SET_TEST_H_ + +// unordered_set test : 测试 unordered_set, unordered_multiset 的接口与它们 insert 的性能 + +#include + +#include "../MyTinySTL/unordered_set.h" +#include "set_test.h" +#include "test.h" + +namespace mystl +{ +namespace test +{ +namespace unordered_set_test +{ + +void unordered_set_test() +{ + std::cout << "[===============================================================]" << std::endl; + std::cout << "[-------------- Run container test : unordered_set -------------]" << std::endl; + std::cout << "[-------------------------- API test ---------------------------]" << std::endl; + int a[] = { 5,4,3,2,1 }; + mystl::unordered_set us1; + mystl::unordered_set us2(520); + mystl::unordered_set us3(520, mystl::hash()); + mystl::unordered_set us4(520, mystl::hash(), mystl::equal_to()); + mystl::unordered_set us5(a, a + 5); + mystl::unordered_set us6(a, a + 5, 100); + mystl::unordered_set us7(a, a + 5, 100, mystl::hash()); + mystl::unordered_set us8(a, a + 5, 100, mystl::hash(), mystl::equal_to()); + mystl::unordered_set us9(us5); + mystl::unordered_set us10(std::move(us5)); + mystl::unordered_set us11; + us11 = us6; + mystl::unordered_set us12; + us12 = std::move(us6); + mystl::unordered_set us13{ 1,2,3,4,5 }; + mystl::unordered_set us14; + us13 = { 1,2,3,4,5 }; + + FUN_AFTER(us1, us1.emplace(1)); + FUN_AFTER(us1, us1.emplace_hint(us1.end(), 2)); + FUN_AFTER(us1, us1.insert(5)); + FUN_AFTER(us1, us1.insert(us1.begin(), 5)); + FUN_AFTER(us1, us1.insert(a, a + 5)); + FUN_AFTER(us1, us1.erase(us1.begin())); + FUN_AFTER(us1, us1.erase(us1.begin(), us1.find(3))); + FUN_AFTER(us1, us1.erase(1)); + std::cout << std::boolalpha; + FUN_VALUE(us1.empty()); + std::cout << std::noboolalpha; + FUN_VALUE(us1.size()); + FUN_VALUE(us1.bucket_count()); + FUN_VALUE(us1.max_bucket_count()); + FUN_VALUE(us1.bucket(1)); + FUN_VALUE(us1.bucket_size(us1.bucket(5))); + FUN_AFTER(us1, us1.clear()); + FUN_AFTER(us1, us1.swap(us7)); + FUN_VALUE(*us1.begin()); + std::cout << std::boolalpha; + FUN_VALUE(us1.empty()); + std::cout << std::noboolalpha; + FUN_VALUE(us1.size()); + FUN_VALUE(us1.max_size()); + FUN_VALUE(us1.bucket_count()); + FUN_AFTER(us1, us1.reserve(1000)); + FUN_VALUE(*us1.begin(us1.bucket(1))); + FUN_VALUE(us1.size()); + FUN_VALUE(us1.bucket_count()); + FUN_VALUE(us1.bucket_size(1)); + FUN_VALUE(us1.bucket_size(2)); + FUN_VALUE(us1.bucket_size(3)); + FUN_AFTER(us1, us1.rehash(150)); + FUN_VALUE(us1.bucket_count()); + FUN_VALUE(us1.count(1)); + FUN_VALUE(*us1.find(3)); + auto first = *us1.equal_range(3).first; + auto second = *us1.equal_range(3).second; + std::cout << " us1.equal_range(3) : from " << first << " to " << second << std::endl; + FUN_VALUE(us1.load_factor()); + FUN_VALUE(us1.max_load_factor()); + FUN_AFTER(us1, us1.max_load_factor(1.5f)); + FUN_VALUE(us1.max_load_factor()); + PASSED; +#if PERFORMANCE_TEST_ON + std::cout << "[--------------------- Performance Testing ---------------------]" << std::endl; + std::cout << "|---------------------|-------------|-------------|-------------|" << std::endl; + std::cout << "| emplace |"; +#if LARGER_TEST_DATA_ON + CON_TEST_P1(unordered_set, emplace, rand(), SCALE_L(LEN1), SCALE_L(LEN2), SCALE_L(LEN3)); +#else + CON_TEST_P1(unordered_set, emplace, rand(), SCALE_M(LEN1), SCALE_M(LEN2), SCALE_M(LEN3)); +#endif + std::cout << std::endl; + std::cout << "|---------------------|-------------|-------------|-------------|" << std::endl; + PASSED; +#endif + std::cout << "[-------------- End container test : unordered_set -------------]" << std::endl; +} + +void unordered_multiset_test() +{ + std::cout << "[===============================================================]" << std::endl; + std::cout << "[------------ Run container test : unordered_multiset ----------]" << std::endl; + std::cout << "[-------------------------- API test ---------------------------]" << std::endl; + int a[] = { 5,4,3,2,1 }; + mystl::unordered_multiset us1; + mystl::unordered_multiset us2(520); + mystl::unordered_multiset us3(520, mystl::hash()); + mystl::unordered_multiset us4(520, mystl::hash(), mystl::equal_to()); + mystl::unordered_multiset us5(a, a + 5); + mystl::unordered_multiset us6(a, a + 5, 100); + mystl::unordered_multiset us7(a, a + 5, 100, mystl::hash()); + mystl::unordered_multiset us8(a, a + 5, 100, mystl::hash(), mystl::equal_to()); + mystl::unordered_multiset us9(us5); + mystl::unordered_multiset us10(std::move(us5)); + mystl::unordered_multiset us11; + us11 = us6; + mystl::unordered_multiset us12; + us12 = std::move(us6); + mystl::unordered_multiset us13{ 1,2,3,4,5 }; + mystl::unordered_multiset us14; + us14 = { 1,2,3,4,5 }; + + FUN_AFTER(us1, us1.emplace(1)); + FUN_AFTER(us1, us1.emplace_hint(us1.end(), 2)); + FUN_AFTER(us1, us1.insert(5)); + FUN_AFTER(us1, us1.insert(us1.begin(), 5)); + FUN_AFTER(us1, us1.insert(a, a + 5)); + FUN_AFTER(us1, us1.erase(us1.begin())); + FUN_AFTER(us1, us1.erase(us1.begin(), us1.find(3))); + FUN_AFTER(us1, us1.erase(1)); + std::cout << std::boolalpha; + FUN_VALUE(us1.empty()); + std::cout << std::noboolalpha; + FUN_VALUE(us1.size()); + FUN_VALUE(us1.bucket_count()); + FUN_VALUE(us1.max_bucket_count()); + FUN_VALUE(us1.bucket(1)); + FUN_VALUE(us1.bucket_size(us1.bucket(5))); + FUN_AFTER(us1, us1.clear()); + FUN_AFTER(us1, us1.swap(us7)); + FUN_VALUE(*us1.begin()); + std::cout << std::boolalpha; + FUN_VALUE(us1.empty()); + std::cout << std::noboolalpha; + FUN_VALUE(us1.size()); + FUN_VALUE(us1.max_size()); + FUN_VALUE(us1.bucket_count()); + FUN_AFTER(us1, us1.reserve(1000)); + FUN_VALUE(*us1.begin(us1.bucket(1))); + FUN_VALUE(us1.size()); + FUN_VALUE(us1.bucket_count()); + FUN_VALUE(us1.bucket_size(1)); + FUN_VALUE(us1.bucket_size(2)); + FUN_VALUE(us1.bucket_size(3)); + FUN_AFTER(us1, us1.rehash(150)); + FUN_VALUE(us1.bucket_count()); + FUN_VALUE(us1.count(1)); + FUN_VALUE(*us1.find(3)); + auto first = *us1.equal_range(3).first; + auto second = *us1.equal_range(3).second; + std::cout << " us1.equal_range(3) : from " << first << " to " << second << std::endl; + FUN_VALUE(us1.load_factor()); + FUN_VALUE(us1.max_load_factor()); + FUN_AFTER(us1, us1.max_load_factor(1.5f)); + FUN_VALUE(us1.max_load_factor()); + PASSED; +#if PERFORMANCE_TEST_ON + std::cout << "[--------------------- Performance Testing ---------------------]" << std::endl; + std::cout << "|---------------------|-------------|-------------|-------------|" << std::endl; + std::cout << "| emplace |"; +#if LARGER_TEST_DATA_ON + CON_TEST_P1(unordered_multiset, emplace, rand(), SCALE_M(LEN1), SCALE_M(LEN2), SCALE_M(LEN3)); +#else + CON_TEST_P1(unordered_multiset, emplace, rand(), SCALE_S(LEN1), SCALE_S(LEN2), SCALE_S(LEN3)); +#endif + std::cout << std::endl; + std::cout << "|---------------------|-------------|-------------|-------------|" << std::endl; + PASSED; +#endif + std::cout << "[------------ End container test : unordered_multiset ----------]" << std::endl; +} + +} // namespace unordered_set_test +} // namespace test +} // namespace mystl +#endif // !MYTINYSTL_UNORDERED_SET_TEST_H_ + diff --git a/src/MyTinySTL-master/MyTinySTL-master/Test/vector_test.h b/src/MyTinySTL-master/MyTinySTL-master/Test/vector_test.h new file mode 100755 index 0000000..8b79ef6 --- /dev/null +++ b/src/MyTinySTL-master/MyTinySTL-master/Test/vector_test.h @@ -0,0 +1,114 @@ +#ifndef MYTINYSTL_VECTOR_TEST_H_ +#define MYTINYSTL_VECTOR_TEST_H_ + +// vector test : 测试 vector 的接口与 push_back 的性能 + +#include + +#include "../MyTinySTL/vector.h" +#include "test.h" + +namespace mystl +{ +namespace test +{ +namespace vector_test +{ + +void vector_test() +{ + std::cout << "[===============================================================]\n"; + std::cout << "[----------------- Run container test : vector -----------------]\n"; + std::cout << "[-------------------------- API test ---------------------------]\n"; + int a[] = { 1,2,3,4,5 }; + mystl::vector v1; + mystl::vector v2(10); + mystl::vector v3(10, 1); + mystl::vector v4(a, a + 5); + mystl::vector v5(v2); + mystl::vector v6(std::move(v2)); + mystl::vector v7{ 1,2,3,4,5,6,7,8,9 }; + mystl::vector v8, v9, v10; + v8 = v3; + v9 = std::move(v3); + v10 = { 1,2,3,4,5,6,7,8,9 }; + + FUN_AFTER(v1, v1.assign(8, 8)); + FUN_AFTER(v1, v1.assign(a, a + 5)); + FUN_AFTER(v1, v1.emplace(v1.begin(), 0)); + FUN_AFTER(v1, v1.emplace_back(6)); + FUN_AFTER(v1, v1.push_back(6)); + FUN_AFTER(v1, v1.insert(v1.end(), 7)); + FUN_AFTER(v1, v1.insert(v1.begin() + 3, 2, 3)); + FUN_AFTER(v1, v1.insert(v1.begin(), a, a + 5)); + FUN_AFTER(v1, v1.pop_back()); + FUN_AFTER(v1, v1.erase(v1.begin())); + FUN_AFTER(v1, v1.erase(v1.begin(), v1.begin() + 2)); + FUN_AFTER(v1, v1.reverse()); + FUN_AFTER(v1, v1.swap(v4)); + FUN_VALUE(*v1.begin()); + FUN_VALUE(*(v1.end() - 1)); + FUN_VALUE(*v1.rbegin()); + FUN_VALUE(*(v1.rend() - 1)); + FUN_VALUE(v1.front()); + FUN_VALUE(v1.back()); + FUN_VALUE(v1[0]); + FUN_VALUE(v1.at(1)); + int* p = v1.data(); + *p = 10; + *++p = 20; + p[1] = 30; + std::cout << " After change v1.data() :" << "\n"; + COUT(v1); + std::cout << std::boolalpha; + FUN_VALUE(v1.empty()); + std::cout << std::noboolalpha; + FUN_VALUE(v1.size()); + FUN_VALUE(v1.max_size()); + FUN_VALUE(v1.capacity()); + FUN_AFTER(v1, v1.resize(10)); + FUN_VALUE(v1.size()); + FUN_VALUE(v1.capacity()); + FUN_AFTER(v1, v1.shrink_to_fit()); + FUN_VALUE(v1.size()); + FUN_VALUE(v1.capacity()); + FUN_AFTER(v1, v1.resize(6, 6)); + FUN_VALUE(v1.size()); + FUN_VALUE(v1.capacity()); + FUN_AFTER(v1, v1.shrink_to_fit()); + FUN_VALUE(v1.size()); + FUN_VALUE(v1.capacity()); + FUN_AFTER(v1, v1.clear()); + FUN_VALUE(v1.size()); + FUN_VALUE(v1.capacity()); + FUN_AFTER(v1, v1.reserve(5)); + FUN_VALUE(v1.size()); + FUN_VALUE(v1.capacity()); + FUN_AFTER(v1, v1.reserve(20)); + FUN_VALUE(v1.size()); + FUN_VALUE(v1.capacity()); + FUN_AFTER(v1, v1.shrink_to_fit()); + FUN_VALUE(v1.size()); + FUN_VALUE(v1.capacity()); + PASSED; +#if PERFORMANCE_TEST_ON + std::cout << "[--------------------- Performance Testing ---------------------]\n"; + std::cout << "|---------------------|-------------|-------------|-------------|\n"; + std::cout << "| push_back |"; +#if LARGER_TEST_DATA_ON + CON_TEST_P1(vector, push_back, rand(), SCALE_LL(LEN1), SCALE_LL(LEN2), SCALE_LL(LEN3)); +#else + CON_TEST_P1(vector, push_back, rand(), SCALE_L(LEN1), SCALE_L(LEN2), SCALE_L(LEN3)); +#endif + std::cout << "\n"; + std::cout << "|---------------------|-------------|-------------|-------------|\n"; + PASSED; +#endif + std::cout << "[----------------- End container test : vector -----------------]\n"; +} + +} // namespace vector_test +} // namespace test +} // namespace mystl +#endif // !MYTINYSTL_VECTOR_TEST_H_ + diff --git a/src/MyTinySTL-master/MyTinySTL-master/appveyor.yml b/src/MyTinySTL-master/MyTinySTL-master/appveyor.yml new file mode 100755 index 0000000..faaba8d --- /dev/null +++ b/src/MyTinySTL-master/MyTinySTL-master/appveyor.yml @@ -0,0 +1,21 @@ +version: 2.0.1{build} + +branches: + only: + - master + +image: + - Visual Studio 2015 + - Visual Studio 2017 + +configuration: + - Release + +build: + parallel: true + project: MSVC\MyTinySTL_VS2015.sln + +test_script: + - cmd: cd .\MSVC\x64\Release\ + - cmd: MyTinySTL.exe +