├── .github └── workflows │ └── ci.yml ├── .gitignore ├── CMakeLists.txt ├── LICENSE ├── README.md ├── cmake └── st_treeConfig.cmake.in ├── examples ├── CMakeLists.txt ├── x01_hello_world.cpp ├── x02_ordered_children.cpp ├── x03_keyed_children.cpp ├── x04_sort_children.cpp ├── x05_node_methods.cpp ├── x06_graft.cpp ├── x07_iterators.cpp └── x_common.h ├── include ├── CMakeLists.txt ├── st_tree.h ├── st_tree_detail.h ├── st_tree_iterators.h └── st_tree_nodes.h └── tests ├── CMakeLists.txt ├── unit_tests.cpp ├── ut_common.h ├── ut_exception.cpp ├── ut_keyed.cpp ├── ut_ordered.cpp ├── ut_raw.cpp └── ut_vmap_iter.cpp /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: build 2 | 3 | on: 4 | pull_request: 5 | branches: ['**'] 6 | push: 7 | branches: ['**'] 8 | tags: [v*] 9 | 10 | jobs: 11 | build: 12 | runs-on: ubuntu-latest 13 | strategy: 14 | fail-fast: false 15 | matrix: 16 | cppstd: [11, 14, 17, 20] 17 | steps: 18 | - uses: actions/checkout@v2 19 | - name: install-build-tools 20 | run: | 21 | sudo apt-get install -y gcc g++ cmake make libboost-all-dev 22 | - name: build 23 | run: | 24 | cmake -DCMAKE_CXX_STANDARD=${{ matrix.cppstd }} -DBUILD_EXAMPLES=ON . 25 | make 26 | - name: unit-tests 27 | run: | 28 | ./tests/unit_tests 29 | - name: run-examples 30 | run: | 31 | export EXAMPLES=( 32 | x01_hello_world 33 | x02_ordered_children 34 | x03_keyed_children 35 | x04_sort_children 36 | x05_node_methods 37 | x06_graft 38 | x07_iterators 39 | ) 40 | for x in ${EXAMPLES[*]}; do 41 | echo === $x 42 | ./examples/$x 43 | echo === 44 | echo 45 | done 46 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | CMakeFiles/ 2 | Makefile 3 | *.cmake 4 | CMakeCache.txt 5 | x01_hello_world 6 | x02_ordered_children 7 | x03_keyed_children 8 | x04_sort_children 9 | x05_node_methods 10 | x06_graft 11 | x07_iterators 12 | unit_tests 13 | .DS_Store 14 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.0) 2 | project(st_tree VERSION 1.0.6) 3 | 4 | option(BUILD_EXAMPLES "Build the examples." OFF) 5 | option(ENABLE_TESTS "Enable the tests. Requires boost." ON) 6 | 7 | include(GNUInstallDirs) 8 | include(CMakePackageConfigHelpers) 9 | 10 | # Build against ANSI c++ standards 11 | IF (CMAKE_COMPILER_IS_GNUCXX OR CMAKE_COMPILER_IS_GNUCC OR MINGW) 12 | SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -ansi -pedantic -std=c++11") 13 | ENDIF() 14 | 15 | # include 16 | add_subdirectory(include) 17 | 18 | # tutorial examples 19 | if(BUILD_EXAMPLES) 20 | add_subdirectory(examples) 21 | endif() 22 | 23 | # testing programs 24 | if(ENABLE_TESTS) 25 | add_subdirectory(tests) 26 | endif() 27 | 28 | set(ST_TREE_HEADERS 29 | include/st_tree_detail.h 30 | include/st_tree.h 31 | include/st_tree_iterators.h 32 | include/st_tree_nodes.h) 33 | 34 | add_library(${PROJECT_NAME} INTERFACE) 35 | target_include_directories(${PROJECT_NAME} INTERFACE 36 | $ 37 | $) 38 | 39 | install(TARGETS ${PROJECT_NAME} 40 | EXPORT ${PROJECT_NAME}-targets) 41 | 42 | # Makes the project importable from the build directory 43 | export(EXPORT ${PROJECT_NAME}-targets 44 | FILE "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Targets.cmake") 45 | 46 | install(FILES ${ST_TREE_HEADERS} 47 | DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) 48 | 49 | configure_package_config_file(cmake/${PROJECT_NAME}Config.cmake.in 50 | "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake" 51 | INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake) 52 | 53 | write_basic_package_version_file(${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake 54 | VERSION ${${PROJECT_NAME}_VERSION} 55 | COMPATIBILITY AnyNewerVersion) 56 | 57 | install(FILES 58 | ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake 59 | ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake 60 | DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake) 61 | 62 | install(EXPORT ${PROJECT_NAME}-targets 63 | FILE ${PROJECT_NAME}Targets.cmake 64 | DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake) 65 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS 178 | 179 | APPENDIX: How to apply the Apache License to your work. 180 | 181 | To apply the Apache License to your work, attach the following 182 | boilerplate notice, with the fields enclosed by brackets "[]" 183 | replaced with your own identifying information. (Don't include 184 | the brackets!) The text should be enclosed in the appropriate 185 | comment syntax for the file format. We also recommend that a 186 | file or class name and description of purpose be included on the 187 | same "printed page" as the copyright notice for easier 188 | identification within third-party archives. 189 | 190 | Copyright [yyyy] [name of copyright owner] 191 | 192 | Licensed under the Apache License, Version 2.0 (the "License"); 193 | you may not use this file except in compliance with the License. 194 | You may obtain a copy of the License at 195 | 196 | http://www.apache.org/licenses/LICENSE-2.0 197 | 198 | Unless required by applicable law or agreed to in writing, software 199 | distributed under the License is distributed on an "AS IS" BASIS, 200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 201 | See the License for the specific language governing permissions and 202 | limitations under the License. 203 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # st_tree: A fast and flexible c++ template class for tree data structures 2 | 3 | ![Build Status](https://github.com/erikerlandson/st_tree/workflows/build/badge.svg?branch=develop) 4 | 5 | ## Introduction 6 | The st_tree library implements a C++ template tree container class for storing data in arbitrary tree structures. st_tree is short for “standard template tree,” and supports STL-compatible interfaces including iterators, allocators and standard STL container methods. 7 | 8 | The st_tree library allows the programmer to easily declare and manipulate data in a tree: 9 | 10 | ```cpp 11 | // declare a tree of integers, where children are stored using a vector storage model 12 | tree t1; 13 | 14 | // declare a tree of strings, where node children are maintained in sorted order 15 | tree > t2; 16 | 17 | // declare a tree of floating point, where children are indexed by a string label 18 | tree > t3; 19 | ``` 20 | 21 | ## Features 22 | The st_tree template container class provides the following features 23 | 24 | * Fully featured standard STL container interface, including standard container methods, iterators, typedefs and allocators 25 | * Common tree-related methods, including `ply()`, `depth()`, `subtree_size()`, `is_root()` and `parent()` 26 | * Computational efficiency — all operations execute in logarithmic time, except those involving deep copy 27 | * Configurable storage models for child nodes — children of a node may be managed using a `vector<>` (“raw”), `multiset<>` (“ordered”) or `map<>` (“keyed”) container model. 28 | * Compiles under standard ANSI C++ 29 | * Unit tested 30 | * Memory tested with valgrind 31 | * Open sourced under the Apache 2.0 License 32 | 33 | 34 | ## Documentation 35 | Documentation for the st_tree template container class and its components can be found here: 36 | https://github.com/erikerlandson/st_tree/wiki/st_tree-documentation 37 | 38 | The st_tree wiki is here: 39 | https://github.com/erikerlandson/st_tree/wiki 40 | 41 | ## Install 42 | The st_tree project home is here: 43 | https://github.com/erikerlandson/st_tree 44 | 45 | Instructions for download and install are here: 46 | https://github.com/erikerlandson/st_tree/wiki/st_tree-installation-and-building 47 | 48 | Quick start: 49 | ```sh 50 | # generate makefiles from cmake 51 | $ cd /path/to/st_tree 52 | $ cmake . 53 | 54 | # generate makefiles to build examples from cmake 55 | $ cd /path/to/st_tree 56 | $ cmake . -DBUILD_EXAMPLES=ON 57 | 58 | # make examples and tests: 59 | $ make 60 | 61 | # run unit tests 62 | $ ./tests/unit_tests 63 | 64 | # installs header files and cmake integrations to /usr/local 65 | $ make install 66 | ``` 67 | 68 | To build `st_tree` with a particular c++ standard (e.g. c++ 11, 14, 17, etc): 69 | ```sh 70 | $ cmake -D CMAKE_CXX_STANDARD=14 . 71 | ``` 72 | 73 | ## Examples 74 | Examples reside in the .../st_tree/examples subdirectory. You can also view an annotated list here: 75 | https://github.com/erikerlandson/st_tree/wiki/st_tree-examples 76 | -------------------------------------------------------------------------------- /cmake/st_treeConfig.cmake.in: -------------------------------------------------------------------------------- 1 | # st_tree cmake module 2 | # This module sets the following variables in your project: 3 | # 4 | # st_tree_FOUND - true if st_tree found on the system 5 | # st_tree_INCLUDE_DIRS - the directory containing st_tree headers 6 | # st_tree_LIBRARY - not set, unneeded for header-only library 7 | 8 | @PACKAGE_INIT@ 9 | 10 | include(CMakeFindDependencyMacro) 11 | 12 | if(NOT TARGET @PROJECT_NAME@) 13 | include("${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@Targets.cmake") 14 | get_target_property(@PROJECT_NAME@_INCLUDE_DIRS st_tree INTERFACE_INCLUDE_DIRECTORIES) 15 | endif() 16 | -------------------------------------------------------------------------------- /examples/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include_directories(${st_tree_SOURCE_DIR}/include) 2 | 3 | add_executable(x01_hello_world x01_hello_world.cpp) 4 | add_executable(x02_ordered_children x02_ordered_children.cpp) 5 | add_executable(x03_keyed_children x03_keyed_children.cpp) 6 | add_executable(x04_sort_children x04_sort_children.cpp) 7 | add_executable(x05_node_methods x05_node_methods.cpp) 8 | add_executable(x06_graft x06_graft.cpp) 9 | add_executable(x07_iterators x07_iterators.cpp) 10 | -------------------------------------------------------------------------------- /examples/x01_hello_world.cpp: -------------------------------------------------------------------------------- 1 | /****** 2 | st_tree: An easy to use and highly configurable C++ template tree class, 3 | using STL container style interfaces. 4 | 5 | Copyright (c) 2010-2011 Erik Erlandson 6 | 7 | Author: Erik Erlandson 8 | 9 | Licensed under the Apache License, Version 2.0 (the "License"); 10 | you may not use this file except in compliance with the License. 11 | You may obtain a copy of the License at 12 | 13 | http://www.apache.org/licenses/LICENSE-2.0 14 | 15 | Unless required by applicable law or agreed to in writing, software 16 | distributed under the License is distributed on an "AS IS" BASIS, 17 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | See the License for the specific language governing permissions and 19 | limitations under the License. 20 | ******/ 21 | 22 | #include 23 | using std::cout; 24 | 25 | // use the st_tree header and namespace 26 | #include "st_tree.h" 27 | using namespace st_tree; 28 | 29 | int main(int argc, char** argv) { 30 | // Declare a tree of strings. 31 | // Default child node storage model is raw<>, which provides a vector<> - like interface. 32 | tree t; 33 | // The basic iterator traverses nodes of the tree in breadth-first order. 34 | typedef tree::iterator iterator; 35 | 36 | // Insert a string at root (ply 0). 37 | t.insert("Hello"); 38 | 39 | // Insert strings at ply 1: children of root ("Hello") 40 | t.root().insert(" "); 41 | t.root().insert("world"); 42 | 43 | // Insert strings at ply 2 44 | t.root()[0].insert("!"); // a child of (" ") 45 | t.root()[1].insert("\n"); // a child of ("world") 46 | 47 | // Output data in breadth first order to print a traditional message 48 | for (iterator j(t.begin()); j != t.end(); ++j) 49 | cout << j->data(); 50 | 51 | return 0; 52 | } 53 | -------------------------------------------------------------------------------- /examples/x02_ordered_children.cpp: -------------------------------------------------------------------------------- 1 | /****** 2 | st_tree: An easy to use and highly configurable C++ template tree class, 3 | using STL container style interfaces. 4 | 5 | Copyright (c) 2010-2011 Erik Erlandson 6 | 7 | Author: Erik Erlandson 8 | 9 | Licensed under the Apache License, Version 2.0 (the "License"); 10 | you may not use this file except in compliance with the License. 11 | You may obtain a copy of the License at 12 | 13 | http://www.apache.org/licenses/LICENSE-2.0 14 | 15 | Unless required by applicable law or agreed to in writing, software 16 | distributed under the License is distributed on an "AS IS" BASIS, 17 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | See the License for the specific language governing permissions and 19 | limitations under the License. 20 | ******/ 21 | 22 | #include 23 | #include 24 | using std::cout; 25 | using std::string; 26 | 27 | // use the st_tree header and namespace 28 | #include "st_tree.h" 29 | using namespace st_tree; 30 | 31 | int main(int argc, char** argv) { 32 | // Declare a tree of strings, which stores node children using the ordered storage model. 33 | // The ordered child storage model ordered<> provides a multiset<> - like interface. 34 | tree > t; 35 | typedef tree >::iterator iterator; 36 | // Nodes have iterators, and generally model containers for child nodes 37 | typedef tree >::node_type::iterator node_iterator; 38 | 39 | // Insert a string at root (ply 0). 40 | t.insert("A"); 41 | 42 | // Insert strings at ply 1 43 | node_iterator c = t.root().insert("C"); 44 | t.root().insert("B"); 45 | t.root().insert("D"); 46 | 47 | // Insert strings at ply 2 48 | c->insert("F"); 49 | c->insert("E"); 50 | c->insert("G"); 51 | c->insert("E"); // duplicates are allowed 52 | 53 | // Output data in breadth first order. 54 | // Observe that child nodes are stored in order 55 | for (iterator j(t.begin()); j != t.end(); ++j) 56 | cout << j->data(); 57 | cout << "\n"; 58 | 59 | return 0; 60 | } 61 | -------------------------------------------------------------------------------- /examples/x03_keyed_children.cpp: -------------------------------------------------------------------------------- 1 | /****** 2 | st_tree: An easy to use and highly configurable C++ template tree class, 3 | using STL container style interfaces. 4 | 5 | Copyright (c) 2010-2011 Erik Erlandson 6 | 7 | Author: Erik Erlandson 8 | 9 | Licensed under the Apache License, Version 2.0 (the "License"); 10 | you may not use this file except in compliance with the License. 11 | You may obtain a copy of the License at 12 | 13 | http://www.apache.org/licenses/LICENSE-2.0 14 | 15 | Unless required by applicable law or agreed to in writing, software 16 | distributed under the License is distributed on an "AS IS" BASIS, 17 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | See the License for the specific language governing permissions and 19 | limitations under the License. 20 | ******/ 21 | 22 | #include 23 | #include 24 | using std::string; 25 | using std::cout; 26 | 27 | // use the st_tree header and namespace 28 | #include "st_tree.h" 29 | using namespace st_tree; 30 | 31 | int main(int argc, char** argv) { 32 | // Declare a tree of integers, which stores node children keyed by a string label. 33 | // The keyed<> child storage model has a map<> - like interface. 34 | tree > t; 35 | typedef tree >::iterator iterator; 36 | // This is standard key-val pair for insertion. Unlike map<>, value_type is the node type. 37 | typedef tree >::node_type::kv_pair kv_pair; 38 | 39 | // There is no key for root, since root node is always unique 40 | // The key takes its default value. 41 | t.insert(0); 42 | 43 | // Insert at ply 1 44 | t.root().insert("C", 3); 45 | t.root().insert("A", 1); 46 | t.root().insert(kv_pair("B", 2)); // standard map<> key/val pair insertion 47 | 48 | // Insert at ply 2 49 | t.root()["C"].insert("F", 6); 50 | t.root()["C"].insert("E", 5); 51 | t.root()["C"].insert("G", 7); 52 | t.root()["C"].insert("E", 99); // duplicate insertions are ignored, as with map<> 53 | t.root()["C"].insert("D", 4); 54 | 55 | // Output data in breadth first order. 56 | // Child nodes are stored in order of key. 57 | for (iterator j(t.begin()); j != t.end(); ++j) 58 | cout << "\"" << j->key() << "\" --> " << j->data() << "\n"; 59 | 60 | return 0; 61 | } 62 | -------------------------------------------------------------------------------- /examples/x04_sort_children.cpp: -------------------------------------------------------------------------------- 1 | /****** 2 | st_tree: An easy to use and highly configurable C++ template tree class, 3 | using STL container style interfaces. 4 | 5 | Copyright (c) 2010-2011 Erik Erlandson 6 | 7 | Author: Erik Erlandson 8 | 9 | Licensed under the Apache License, Version 2.0 (the "License"); 10 | you may not use this file except in compliance with the License. 11 | You may obtain a copy of the License at 12 | 13 | http://www.apache.org/licenses/LICENSE-2.0 14 | 15 | Unless required by applicable law or agreed to in writing, software 16 | distributed under the License is distributed on an "AS IS" BASIS, 17 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | See the License for the specific language governing permissions and 19 | limitations under the License. 20 | ******/ 21 | 22 | #include 23 | #include 24 | #include 25 | using std::cout; 26 | using std::string; 27 | using std::sort; 28 | 29 | // use the st_tree header and namespace 30 | #include "st_tree.h" 31 | using namespace st_tree; 32 | 33 | 34 | int main(int argc, char** argv) { 35 | // Declare a tree of strings. 36 | tree t; 37 | // The basic iterator traverses nodes of the tree in breadth-first order. 38 | typedef tree::iterator iterator; 39 | typedef tree::node_type node_type; 40 | typedef node_type::iterator child_iterator; 41 | 42 | // Insert a string at root (ply 0). 43 | t.insert("A"); 44 | 45 | // Insert strings at ply 1 46 | // For raw child storage model, push_back() and insert() are equivalent 47 | t.root().push_back("D"); 48 | t.root().push_back("C"); 49 | t.root().push_back("B"); 50 | 51 | // Insert strings at ply 2 52 | // You can use front() and back() with this storage model 53 | t.root().front().push_back("Z"); 54 | t.root().front().push_back("Y"); 55 | t.root()[1].push_back("R"); 56 | t.root()[1].push_back("Q"); 57 | t.root()[1].push_back("P"); 58 | t.root().back().push_back("X"); 59 | t.root().back().push_back("W"); 60 | 61 | // Child node iterators are random-access for the raw<> storage model, 62 | // so that means we can do things like call sort() on them. 63 | // This sort takes advantage of the default ordering relation on nodes, 64 | // which compares data() value as the primary comparison, and then compares 65 | // child nodes, recursively, in lex order. 66 | sort(t.root()[1].begin(), t.root()[1].end()); 67 | // (If you actually want ordered nodes, you should also consider using the 68 | // ordered<> child storage model) 69 | 70 | // Output data in breadth first order 71 | // Observe that only children of t.root()[1] ("C") are sorted: P Q R 72 | for (iterator j(t.begin()); j != t.end(); ++j) 73 | cout << j->data() << " "; 74 | cout << "\n"; 75 | 76 | return 0; 77 | } 78 | -------------------------------------------------------------------------------- /examples/x05_node_methods.cpp: -------------------------------------------------------------------------------- 1 | /****** 2 | st_tree: An easy to use and highly configurable C++ template tree class, 3 | using STL container style interfaces. 4 | 5 | Copyright (c) 2010-2011 Erik Erlandson 6 | 7 | Author: Erik Erlandson 8 | 9 | Licensed under the Apache License, Version 2.0 (the "License"); 10 | you may not use this file except in compliance with the License. 11 | You may obtain a copy of the License at 12 | 13 | http://www.apache.org/licenses/LICENSE-2.0 14 | 15 | Unless required by applicable law or agreed to in writing, software 16 | distributed under the License is distributed on an "AS IS" BASIS, 17 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | See the License for the specific language governing permissions and 19 | limitations under the License. 20 | ******/ 21 | 22 | #include 23 | #include 24 | using std::cout; 25 | using std::string; 26 | 27 | // use the st_tree header and namespace 28 | #include "st_tree.h" 29 | using namespace st_tree; 30 | 31 | const char* indent(unsigned n) { 32 | static char const spaces[] = " "; 33 | static const unsigned ns = sizeof(spaces)/sizeof(*spaces); 34 | return spaces + (ns-1-n); 35 | } 36 | 37 | int main(int argc, char** argv) { 38 | // Declare a tree of strings. 39 | tree t; 40 | // An iterator to traverse nodes in depth first pre-order 41 | typedef tree::df_pre_iterator iterator; 42 | typedef tree::node_type node_type; 43 | 44 | // Insert a string at root (ply 0). 45 | t.insert("Animals"); 46 | 47 | // Insert strings at ply 1 48 | // For raw child storage model, push_back() and insert() are equivalent 49 | t.root().push_back("Canines"); 50 | t.root().push_back("Felines"); 51 | t.root().push_back("Equines"); 52 | 53 | // Insert strings at ply 2 54 | t.root()[0].push_back("Dog"); 55 | t.root()[0].push_back("Wolf"); 56 | t.root()[0].push_back("Fox"); 57 | 58 | t.root()[1].push_back("Cat"); 59 | t.root()[1].push_back("Lion"); 60 | t.root()[1].push_back("Panther"); 61 | 62 | t.root()[2].push_back("Horse"); 63 | t.root()[2].push_back("Zebra"); 64 | 65 | 66 | // Demonstrate some of the basic tree-related node methods. 67 | // Output the tree nodes in depth first pre-order. 68 | for (iterator j(t.df_pre_begin()); j != t.df_pre_end(); ++j) { 69 | // data() gives the data 'payload' of the node 70 | string data = j->data(); 71 | 72 | // ply() gives the ply, or layer, of the node 73 | unsigned ply = j->ply(); 74 | 75 | // padding for nice output 76 | unsigned w = 16; 77 | unsigned padL = ply * 4; 78 | unsigned padR = w - data.size() - padL; 79 | cout << indent(padL); 80 | cout << data; 81 | cout << indent(padR); 82 | 83 | // is_root() is true if the node has no parent 84 | // parent() returns the node's parent 85 | cout << " parent= " << ((j->is_root()) ? " " : j->parent().data()); 86 | 87 | // ply() gives the ply, or layer, of the node 88 | cout << " ply= " << j->ply(); 89 | 90 | // depth() is the depth of the node's subtree 91 | cout << " depth= " << j->depth(); 92 | 93 | // subtree_size() is the size of the node's subtree 94 | cout << " subtree_size= " << j->subtree_size(); 95 | cout << "\n"; 96 | } 97 | 98 | return 0; 99 | } 100 | -------------------------------------------------------------------------------- /examples/x06_graft.cpp: -------------------------------------------------------------------------------- 1 | /****** 2 | st_tree: An easy to use and highly configurable C++ template tree class, 3 | using STL container style interfaces. 4 | 5 | Copyright (c) 2010-2011 Erik Erlandson 6 | 7 | Author: Erik Erlandson 8 | 9 | Licensed under the Apache License, Version 2.0 (the "License"); 10 | you may not use this file except in compliance with the License. 11 | You may obtain a copy of the License at 12 | 13 | http://www.apache.org/licenses/LICENSE-2.0 14 | 15 | Unless required by applicable law or agreed to in writing, software 16 | distributed under the License is distributed on an "AS IS" BASIS, 17 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | See the License for the specific language governing permissions and 19 | limitations under the License. 20 | ******/ 21 | 22 | #include 23 | #include 24 | using std::cout; 25 | using std::string; 26 | 27 | // use the st_tree header and namespace 28 | #include "st_tree.h" 29 | using namespace st_tree; 30 | 31 | #include "x_common.h" 32 | 33 | int main(int argc, char** argv) { 34 | // construct a basic tree with two plys 35 | tree t; 36 | t.insert("A"); 37 | t.root().insert("B"); // children of "A" 38 | t.root().insert("C"); 39 | t.root().insert("D"); 40 | 41 | // another tree 42 | tree t2; 43 | t2.insert("T"); 44 | t2.root().insert("U"); // children of "T" 45 | t2.root().insert("V"); 46 | t2.root()[0].insert("W"); // children of "U" 47 | t2.root()[0].insert("X"); 48 | t2.root()[1].insert("Y"); // children of "V" 49 | t2.root()[1].insert("Z"); 50 | 51 | // Demonstrate the differences between node assignment, insert and graft: 52 | // Assignment replaces destination with deep copy of source (and subtree) 53 | t.root()[0] = t2.root()[1]; // node "B" <-- "V","Y","Z" subtree 54 | 55 | // insert() inserts a deep copy of source into node's children 56 | t.root()[1].insert(t2.root()[1]); // node "C" gets child subtree "V","Y","Z" 57 | 58 | // graft() *removes* source and inserts to destination's children 59 | t.root()[2].graft(t2.root()[1]); // subtree "V","Y","Z" is moved from t2 to child of "D" on (t) 60 | // tree (t2) will no longer have subtree "V","Y","Z" 61 | 62 | // Display tree (t) with changes 63 | cout << "Tree (t)\n"; 64 | serialize_indented(t, cout, 2); 65 | 66 | // Observe that (t2) subtree "V","Y","Z" is gone after graft() 67 | cout << "\nTree (t2)\n"; 68 | serialize_indented(t2, cout, 2); 69 | 70 | return 0; 71 | } 72 | -------------------------------------------------------------------------------- /examples/x07_iterators.cpp: -------------------------------------------------------------------------------- 1 | /****** 2 | st_tree: An easy to use and highly configurable C++ template tree class, 3 | using STL container style interfaces. 4 | 5 | Copyright (c) 2010-2011 Erik Erlandson 6 | 7 | Author: Erik Erlandson 8 | 9 | Licensed under the Apache License, Version 2.0 (the "License"); 10 | you may not use this file except in compliance with the License. 11 | You may obtain a copy of the License at 12 | 13 | http://www.apache.org/licenses/LICENSE-2.0 14 | 15 | Unless required by applicable law or agreed to in writing, software 16 | distributed under the License is distributed on an "AS IS" BASIS, 17 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | See the License for the specific language governing permissions and 19 | limitations under the License. 20 | ******/ 21 | 22 | #include 23 | #include 24 | using std::cout; 25 | using std::string; 26 | 27 | // use the st_tree header and namespace 28 | #include "st_tree.h" 29 | using namespace st_tree; 30 | 31 | #include "x_common.h" 32 | 33 | int main(int argc, char** argv) { 34 | // construct a basic tree 35 | tree t; 36 | t.insert("T"); 37 | t.root().insert("U"); // children of "T" 38 | t.root().insert("V"); 39 | t.root()[0].insert("W"); // children of "U" 40 | t.root()[0].insert("X"); 41 | t.root()[1].insert("Y"); // children of "V" 42 | t.root()[1].insert("Z"); 43 | 44 | 45 | // The basic tree<>::iterator is breadth first traversal 46 | cout << "tree<>::iterator\n"; 47 | serialize_indented(t.begin(), t.end(), cout); 48 | 49 | // tree<>::bf_iterator is also breadth-first 50 | cout << "\ntree<>::bf_iterator\n"; 51 | serialize_indented(t.bf_begin(), t.bf_end(), cout); 52 | 53 | // tree<>::df_pre_iterator is depth-first, pre order traversal 54 | cout << "\ntree<>::df_pre_iterator\n"; 55 | serialize_indented(t.df_pre_begin(), t.df_pre_end(), cout); 56 | 57 | // tree<>::df_post_iterator id depth-first post order traversal 58 | cout << "\ntree<>::df_post_iterator\n"; 59 | serialize_indented(t.df_post_begin(), t.df_post_end(), cout); 60 | 61 | 62 | // the basic tree<>::node_type::iterator is iterator over that node's children 63 | // so, this only iterates over children of "U": "W" and "X" 64 | cout << "\ntree<>::node_type::iterator\n"; 65 | serialize_indented(t.root()[0].begin(), t.root()[0].end(), cout, 0); 66 | 67 | // tree<>::node_type::bf_iterator traverses a node's subtree, breadth first 68 | cout << "\ntree<>::node_type::bf_iterator\n"; 69 | serialize_indented(t.root()[0].bf_begin(), t.root()[0].bf_end(), cout); 70 | 71 | // tree<>::node_type::df_pre_iterator traverses a node's subtree, depth first pre-order 72 | cout << "\ntree<>::node_type::df_pre_iterator\n"; 73 | serialize_indented(t.root()[0].df_pre_begin(), t.root()[0].df_pre_end(), cout); 74 | 75 | // tree<>::node_type::df_post_iterator traverses a node's subtree, depth first post-order 76 | cout << "\ntree<>::node_type::df_post_iterator\n"; 77 | serialize_indented(t.root()[0].df_post_begin(), t.root()[0].df_post_end(), cout); 78 | 79 | return 0; 80 | } 81 | -------------------------------------------------------------------------------- /examples/x_common.h: -------------------------------------------------------------------------------- 1 | /****** 2 | st_tree: An easy to use and highly configurable C++ template tree class, 3 | using STL container style interfaces. 4 | 5 | Copyright (c) 2010-2011 Erik Erlandson 6 | 7 | Author: Erik Erlandson 8 | 9 | Licensed under the Apache License, Version 2.0 (the "License"); 10 | you may not use this file except in compliance with the License. 11 | You may obtain a copy of the License at 12 | 13 | http://www.apache.org/licenses/LICENSE-2.0 14 | 15 | Unless required by applicable law or agreed to in writing, software 16 | distributed under the License is distributed on an "AS IS" BASIS, 17 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | See the License for the specific language governing permissions and 19 | limitations under the License. 20 | ******/ 21 | 22 | #if !defined(__x_common_h__) 23 | #define __x_common_h__ 1 24 | 25 | inline const char* indent_padding(unsigned n) { 26 | static char const spaces[] = " "; 27 | static const unsigned ns = sizeof(spaces)/sizeof(*spaces); 28 | if (n >= ns) n = ns-1; 29 | return spaces + (ns-1-n); 30 | } 31 | 32 | 33 | template 34 | void serialize_indented(const Iterator& F, const Iterator& L, Stream& s, unsigned indent=2) { 35 | for (Iterator j(F); j != L; ++j) { 36 | s << indent_padding(j->ply() * indent); 37 | s << j->data(); 38 | s << "\n"; 39 | } 40 | } 41 | 42 | 43 | template 44 | void serialize_indented(const Tree& t, Stream& s, unsigned indent=2) { 45 | serialize_indented(t.df_pre_begin(), t.df_pre_end(), s, indent); 46 | } 47 | 48 | #endif 49 | -------------------------------------------------------------------------------- /include/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Currently nothing to do for the include subdir 2 | -------------------------------------------------------------------------------- /include/st_tree.h: -------------------------------------------------------------------------------- 1 | /****** 2 | st_tree: A highly configurable C++ template tree class, using STL style interfaces. 3 | 4 | Copyright (c) 2010-2011 Erik Erlandson 5 | 6 | Author: Erik Erlandson 7 | 8 | Licensed under the Apache License, Version 2.0 (the "License"); 9 | you may not use this file except in compliance with the License. 10 | You may obtain a copy of the License at 11 | 12 | http://www.apache.org/licenses/LICENSE-2.0 13 | 14 | Unless required by applicable law or agreed to in writing, software 15 | distributed under the License is distributed on an "AS IS" BASIS, 16 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | See the License for the specific language governing permissions and 18 | limitations under the License. 19 | ******/ 20 | 21 | #if !defined(__st_tree_h__) 22 | #define __st_tree_h__ 1 23 | 24 | 25 | #include 26 | #include 27 | 28 | 29 | namespace st_tree { 30 | 31 | // some data types to flag template argument behaviors 32 | struct arg_default {}; 33 | struct arg_unused {}; 34 | 35 | 36 | // Node storage classes: 37 | // use this if you want raw (vector) child node storage 38 | template 39 | struct raw {}; 40 | // provides ordered child node storage 41 | template 42 | struct ordered {}; 43 | // child nodes are indexed by external key 44 | template > 45 | struct keyed {}; 46 | 47 | 48 | // generic exception base class for tree package 49 | struct exception: public std::exception { 50 | exception() throw(): std::exception(), _what() {} 51 | virtual ~exception() throw() {} 52 | exception(const std::string& w) throw(): std::exception(), _what(w) {} 53 | virtual const char* what() const throw() { return _what.c_str(); } 54 | protected: 55 | std::string _what; 56 | }; 57 | 58 | // attempting operations undefined without a parent node 59 | struct parent_exception: public exception { 60 | parent_exception() throw(): exception() {} 61 | virtual ~parent_exception() throw() {} 62 | parent_exception(const std::string& w) throw(): exception(w) {} 63 | }; 64 | 65 | // attempting operations on a node unassociated with a tree 66 | struct orphan_exception: public exception { 67 | orphan_exception() throw(): exception() {} 68 | virtual ~orphan_exception() throw() {} 69 | orphan_exception(const std::string& w) throw(): exception(w) {} 70 | }; 71 | 72 | // attempting operation that would create a cycle in tree 73 | struct cycle_exception: public exception { 74 | cycle_exception() throw(): exception() {} 75 | virtual ~cycle_exception() throw() {} 76 | cycle_exception(const std::string& w) throw(): exception(w) {} 77 | }; 78 | 79 | // attempting operation that is undefined on an empty tree 80 | struct empty_exception: public exception { 81 | empty_exception() throw(): exception() {} 82 | virtual ~empty_exception() throw() {} 83 | empty_exception(const std::string& w) throw(): exception(w) {} 84 | }; 85 | 86 | // data, node, key, etc was undefined or not present 87 | struct missing_exception: public exception { 88 | missing_exception() throw(): exception() {} 89 | virtual ~missing_exception() throw() {} 90 | missing_exception(const std::string& w) throw(): exception(w) {} 91 | }; 92 | 93 | } // namespace st_tree 94 | 95 | 96 | #if !defined(__st_tree_detail_h__) 97 | #include "st_tree_detail.h" 98 | #endif 99 | 100 | #if !defined(__st_tree_iterators_h__) 101 | #include "st_tree_iterators.h" 102 | #endif 103 | 104 | #if !defined(__st_tree_nodes_h__) 105 | #include "st_tree_nodes.h" 106 | #endif 107 | 108 | 109 | namespace st_tree { 110 | 111 | template 112 | struct tree { 113 | typedef tree tree_type; 114 | typedef Data data_type; 115 | typedef CSModel cs_model_type; 116 | typedef Alloc allocator_type; 117 | typedef size_t size_type; 118 | typedef st_tree::detail::difference_type difference_type; 119 | 120 | protected: 121 | typedef detail::node_type_dispatch nt_dispatch; 122 | 123 | public: 124 | typedef typename nt_dispatch::node_type node_type; 125 | typedef typename std::allocator node_allocator_type; 126 | typedef typename std::allocator cs_allocator_type; 127 | 128 | protected: 129 | typedef typename node_type::base_type node_base_type; 130 | 131 | public: 132 | typedef node_type value_type; 133 | typedef node_type* pointer; 134 | typedef node_type const* const_pointer; 135 | typedef node_type& reference; 136 | typedef node_type const& const_reference; 137 | 138 | typedef typename node_type::bf_iterator iterator; 139 | typedef typename node_type::const_bf_iterator const_iterator; 140 | typedef typename node_type::bf_iterator bf_iterator; 141 | typedef typename node_type::const_bf_iterator const_bf_iterator; 142 | typedef typename node_type::df_post_iterator df_post_iterator; 143 | typedef typename node_type::const_df_post_iterator const_df_post_iterator; 144 | typedef typename node_type::df_pre_iterator df_pre_iterator; 145 | typedef typename node_type::const_df_pre_iterator const_df_pre_iterator; 146 | 147 | 148 | tree() : _root(NULL), _node_allocator() {} 149 | virtual ~tree() { clear(); } 150 | 151 | tree(const tree& src) : _root(NULL) { *this = src; } 152 | 153 | tree(const node_allocator_type& a) : _root(NULL), _node_allocator(a) {} 154 | 155 | tree& operator=(const tree& src) { 156 | if (&src == this) return *this; 157 | 158 | _node_allocator = src._node_allocator; 159 | 160 | if (src.empty()) { 161 | clear(); 162 | return *this; 163 | } 164 | 165 | if (empty()) { 166 | _root = _new_node(); 167 | _root->_tree = this; 168 | _root->_depth.insert(1); 169 | } 170 | 171 | *_root = src.root(); 172 | 173 | return *this; 174 | } 175 | 176 | 177 | bool empty() const { return _root == NULL; } 178 | size_type size() const { return (empty()) ? 0 : root().subtree_size(); } 179 | size_type depth() const { return (empty()) ? 0 : root().depth(); } 180 | 181 | node_type& root() { 182 | if (empty()) throw empty_exception("root(): empty tree has no root node"); 183 | return *_root; 184 | } 185 | 186 | const node_type& root() const { 187 | if (empty()) throw empty_exception("root(): empty tree has no root node"); 188 | return *_root; 189 | } 190 | 191 | template< class... Args > 192 | void emplace( Args&&... args ){ 193 | clear(); 194 | _root = _new_node(); 195 | _root->_data = data_type(std::forward(args) ... ); 196 | _root->_tree = this; 197 | _root->_depth.insert(1); 198 | } 199 | 200 | void insert(const data_type& data) { emplace(data); }; 201 | 202 | // there is only one node to erase from the tree: the root 203 | void erase() { clear(); } 204 | 205 | void clear() { 206 | if (empty()) return; 207 | _delete_node(_root); 208 | _root = NULL; 209 | } 210 | 211 | void swap(tree_type& src) { 212 | if (this == &src) return; 213 | std::swap(_root, src._root); 214 | } 215 | 216 | void graft(node_type& src) { 217 | node_type* s = &src; 218 | node_base_type::_excise(s); 219 | clear(); 220 | _root = s; 221 | _graft(s); 222 | } 223 | 224 | void graft(tree_type& src) { 225 | if (src.empty()) erase(); 226 | else graft(src.root()); 227 | } 228 | 229 | void insert(const node_type& src) { 230 | node_type* n = src._copy_data(*this); 231 | node_base_type::_thread(n); 232 | clear(); 233 | _root = n; 234 | _graft(n); 235 | } 236 | 237 | void insert(const tree_type& src) { 238 | if (src.empty()) erase(); 239 | else insert(src.root()); 240 | } 241 | 242 | bool operator==(const tree& rhs) const { 243 | if (size() != rhs.size()) return false; 244 | if (size() == 0) return true; 245 | return root() == rhs.root(); 246 | } 247 | bool operator!=(const tree& rhs) const { return !(*this == rhs); } 248 | 249 | bool operator<(const tree& rhs) const { 250 | if (empty()) return !rhs.empty(); 251 | if (rhs.empty()) return false; 252 | return root() < rhs.root(); 253 | } 254 | bool operator>(const tree& rhs) const { return rhs < *this; } 255 | bool operator<=(const tree& rhs) const { return !(rhs < *this); } 256 | bool operator>=(const tree& rhs) const { return !(*this < rhs); } 257 | 258 | iterator begin() { return iterator(_root); } 259 | iterator end() { return iterator(); } 260 | const_iterator begin() const { return const_iterator(_root); } 261 | const_iterator end() const { return const_iterator(); } 262 | 263 | bf_iterator bf_begin() { return bf_iterator(_root); } 264 | bf_iterator bf_end() { return bf_iterator(); } 265 | const_bf_iterator bf_begin() const { return const_bf_iterator(_root); } 266 | const_bf_iterator bf_end() const { return const_bf_iterator(); } 267 | 268 | df_post_iterator df_post_begin() { return df_post_iterator(_root); } 269 | df_post_iterator df_post_end() { return df_post_iterator(); } 270 | const_df_post_iterator df_post_begin() const { return const_df_post_iterator(_root); } 271 | const_df_post_iterator df_post_end() const { return const_df_post_iterator(); } 272 | 273 | df_pre_iterator df_pre_begin() { return df_pre_iterator(_root); } 274 | df_pre_iterator df_pre_end() { return df_pre_iterator(); } 275 | const_df_pre_iterator df_pre_begin() const { return const_df_pre_iterator(_root); } 276 | const_df_pre_iterator df_pre_end() const { return const_df_pre_iterator(); } 277 | 278 | template friend struct detail::node_base; 279 | template friend struct detail::node_raw; 280 | template friend struct detail::node_ordered; 281 | template friend struct detail::node_keyed; 282 | 283 | protected: 284 | node_type* _root; 285 | node_allocator_type _node_allocator; 286 | static const node_type _node_init_val; 287 | 288 | node_type* _new_node() { 289 | node_type* n = _node_allocator.allocate(1); 290 | std::allocator_traits::construct(_node_allocator, n, _node_init_val); 291 | return n; 292 | } 293 | 294 | void _delete_node(node_type* n) { 295 | std::allocator_traits::destroy(_node_allocator, n); 296 | std::allocator_traits::deallocate(_node_allocator, n, 1); 297 | } 298 | 299 | void _prune(node_type* n) { 300 | } 301 | 302 | void _graft(node_type* n) { 303 | n->_parent = NULL; 304 | n->_tree = this; 305 | } 306 | }; 307 | 308 | 309 | template 310 | const typename tree::node_type tree::_node_init_val; 311 | 312 | 313 | } // namespace st_tree 314 | 315 | 316 | 317 | #endif // __st_tree_h__ 318 | -------------------------------------------------------------------------------- /include/st_tree_detail.h: -------------------------------------------------------------------------------- 1 | /****** 2 | st_tree: A highly configurable C++ template tree class, using STL style interfaces. 3 | 4 | Copyright (c) 2010-2011 Erik Erlandson 5 | 6 | Author: Erik Erlandson 7 | 8 | Licensed under the Apache License, Version 2.0 (the "License"); 9 | you may not use this file except in compliance with the License. 10 | You may obtain a copy of the License at 11 | 12 | http://www.apache.org/licenses/LICENSE-2.0 13 | 14 | Unless required by applicable law or agreed to in writing, software 15 | distributed under the License is distributed on an "AS IS" BASIS, 16 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | See the License for the specific language governing permissions and 18 | limitations under the License. 19 | ******/ 20 | 21 | #if !defined(__st_tree_detail_h__) 22 | #define __st_tree_detail_h__ 1 23 | 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | namespace st_tree { 33 | 34 | // forward declarations 35 | template , typename Alloc=std::allocator > struct tree; 36 | 37 | namespace detail { 38 | 39 | using std::vector; 40 | using std::deque; 41 | using std::multiset; 42 | using std::map; 43 | using std::less; 44 | using std::pair; 45 | 46 | // ptrdiff_t no longer working 47 | typedef vector::difference_type difference_type; 48 | 49 | // forward declarations 50 | template struct node_raw; 51 | template struct node_ordered; 52 | template struct node_keyed; 53 | 54 | template 55 | struct max_maintainer { 56 | typedef size_t size_type; 57 | 58 | max_maintainer(): _hist(), _max(0) {} 59 | virtual ~max_maintainer() {} 60 | 61 | max_maintainer(const max_maintainer& src) { *this = src; } 62 | max_maintainer& operator=(const max_maintainer& rhs) { 63 | if (this == &rhs) return *this; 64 | _max = rhs._max; 65 | _hist = rhs._hist; 66 | return *this; 67 | } 68 | 69 | Unsigned max() const { return _max; } 70 | 71 | void insert(const Unsigned& n) { 72 | if (n >= _hist.size()) _hist.resize(1+n, 0); 73 | _hist[n] += 1; 74 | if (n > _max) _max = n; 75 | } 76 | 77 | void erase(const Unsigned& n) { 78 | if (n > _max) return; 79 | _hist[n] -= 1; 80 | while ((_max > 0) && (_hist[_max] <= 0)) _max -= 1; 81 | } 82 | 83 | void insert(const max_maintainer& src, const Unsigned& d) { 84 | if (src._hist.size() <= 0) return; 85 | if ((src._max + d) > _max) _max = src._max + d; 86 | if (_max >= _hist.size()) _hist.resize(1+_max, 0); 87 | for (size_type s = 0; s <= src._max; ++s) _hist[s + d] += src._hist[s]; 88 | } 89 | 90 | void erase(const max_maintainer& src, const Unsigned& d) { 91 | if (src._hist.size() <= 0) return; 92 | size_type n = src._max; 93 | if (d > _max) return; 94 | if ((_max-d) < n) n = _max-d; 95 | for (size_type s = 0; s <= n; ++s) _hist[s + d] -= src._hist[s]; 96 | while ((_max > 0) && (_hist[_max] <= 0)) _max -= 1; 97 | } 98 | 99 | void clear() { 100 | _hist.clear(); 101 | _max = 0; 102 | } 103 | 104 | void swap(max_maintainer& src) { 105 | if (this == &src) return; 106 | std::swap(_max, src._max); 107 | _hist.swap(src._hist); 108 | } 109 | 110 | protected: 111 | typedef typename std::allocator unsigned_allocator; 112 | vector _hist; 113 | Unsigned _max; 114 | }; 115 | 116 | 117 | // This is my poor-man substitute for typeof(*dr) 118 | template struct dr_value {}; 119 | 120 | template 121 | struct dr_value { 122 | typedef V value_type; 123 | }; 124 | 125 | template 126 | struct dref_vmap { 127 | // DR is a type that is de-referenceable: supports the unary "*" dereference operator 128 | typedef typename dr_value::value_type value_type; 129 | 130 | // These both return a non-const reference -- this enables me to handle 131 | // (multi)set iterators in a useful way below: those iterators are always const, 132 | // however I need non-const behavior for many ops. It is only the data field that 133 | // must remain const, because it is the true sorting key 134 | value_type& operator()(DR& x) const { return *x; } 135 | value_type& operator()(const DR& x) const { return const_cast(*x); } 136 | 137 | bool operator==(const dref_vmap& rhs) const { return true; } 138 | bool operator!=(const dref_vmap& rhs) const { return false; } 139 | }; 140 | 141 | 142 | template 143 | struct dref_second_vmap { 144 | // P is assumed to be of type pair<>, or at least define 'second' and 'second_type' 145 | typedef typename dr_value::value_type value_type; 146 | 147 | // Set these both to return non-const reference (see dref_vmap comment above) 148 | value_type& operator()(P& x) const { return *(x.second); } 149 | value_type& operator()(const P& x) const { return const_cast(*(x.second)); } 150 | 151 | bool operator==(const dref_second_vmap& rhs) const { return true; } 152 | bool operator!=(const dref_second_vmap& rhs) const { return false; } 153 | }; 154 | 155 | 156 | template 157 | struct valmap_iterator_adaptor_forward { 158 | protected: 159 | typedef Iterator base_iterator_type; 160 | typedef ValMap valmap; 161 | 162 | base_iterator_type _base; 163 | valmap _vmap; 164 | 165 | public: 166 | typedef std::forward_iterator_tag iterator_category; 167 | typedef typename ValMap::value_type value_type; 168 | typedef typename base_iterator_type::difference_type difference_type; 169 | typedef value_type* pointer; 170 | typedef value_type& reference; 171 | 172 | // default ctor/dtor 173 | valmap_iterator_adaptor_forward(): _base(), _vmap() {} 174 | virtual ~valmap_iterator_adaptor_forward() {} 175 | 176 | // copy/assign 177 | valmap_iterator_adaptor_forward(const valmap_iterator_adaptor_forward& src): _base(src._base), _vmap(src._vmap) {} 178 | valmap_iterator_adaptor_forward& operator=(const valmap_iterator_adaptor_forward& rhs) { 179 | if (this == &rhs) return *this; 180 | _base = rhs._base; 181 | _vmap = rhs._vmap; 182 | return *this; 183 | } 184 | 185 | // casting 186 | base_iterator_type base() const { return this->_base; } 187 | valmap_iterator_adaptor_forward(const base_iterator_type& src): _base(src), _vmap() {} 188 | valmap_iterator_adaptor_forward(const base_iterator_type& src, const valmap& vmap): _base(src), _vmap(vmap) {} 189 | valmap_iterator_adaptor_forward& operator=(const base_iterator_type& rhs) { 190 | _base = rhs; 191 | return *this; 192 | } 193 | 194 | // pre-increment: 195 | valmap_iterator_adaptor_forward& operator++() { 196 | ++_base; 197 | return *this; 198 | } 199 | 200 | // post-increment: 201 | valmap_iterator_adaptor_forward operator++(int) { 202 | valmap_iterator_adaptor_forward r(*this); 203 | ++(*this); 204 | return r; 205 | } 206 | 207 | // access methods 208 | reference operator*() const { return _vmap(*_base); } 209 | pointer operator->() const { return &(_vmap(*_base)); } 210 | 211 | bool operator==(const valmap_iterator_adaptor_forward& rhs) const { 212 | if (_base != rhs._base) return false; 213 | if (!(_vmap == rhs._vmap)) return false; 214 | return true; 215 | } 216 | bool operator!=(const valmap_iterator_adaptor_forward& rhs) const { return !(*this == rhs); } 217 | }; 218 | 219 | 220 | template 221 | struct valmap_iterator_adaptor_random { 222 | typedef Iterator base_iterator_type; 223 | typedef ValMap valmap_type; 224 | 225 | typedef std::random_access_iterator_tag iterator_category; 226 | typedef typename ValMap::value_type value_type; 227 | typedef typename base_iterator_type::difference_type difference_type; 228 | typedef value_type* pointer; 229 | typedef value_type& reference; 230 | 231 | protected: 232 | base_iterator_type _base; 233 | valmap_type _vmap; 234 | 235 | public: 236 | valmap_iterator_adaptor_random() : _base(), _vmap() {} 237 | virtual ~valmap_iterator_adaptor_random() {} 238 | 239 | valmap_iterator_adaptor_random(const valmap_iterator_adaptor_random& src): _base(src._base), _vmap(src._vmap) {} 240 | valmap_iterator_adaptor_random& operator=(const valmap_iterator_adaptor_random& src) { 241 | if (this == &src) return *this; 242 | _base = src._base; 243 | _vmap = src._vmap; 244 | return *this; 245 | } 246 | 247 | base_iterator_type base() const { return this->_base; } 248 | valmap_iterator_adaptor_random(const base_iterator_type& src) : _base(src), _vmap() {} 249 | valmap_iterator_adaptor_random& operator=(const base_iterator_type& src) { 250 | _base = src; 251 | return *this; 252 | } 253 | 254 | // access methods 255 | reference operator*() const { return _vmap(*_base); } 256 | 257 | pointer operator->() const { return &(_vmap(*_base)); } 258 | 259 | reference operator[](const difference_type& n) { 260 | return this->_vmap(*(this->_base+n)); 261 | } 262 | 263 | 264 | // pre-increment: 265 | valmap_iterator_adaptor_random& operator++() { 266 | ++_base; 267 | return *this; 268 | } 269 | 270 | // post-increment: 271 | valmap_iterator_adaptor_random operator++(int) { 272 | valmap_iterator_adaptor_random r(*this); 273 | ++(*this); 274 | return r; 275 | } 276 | 277 | // pre-dec: 278 | valmap_iterator_adaptor_random& operator--() { 279 | --(this->_base); 280 | return *this; 281 | } 282 | 283 | // post-dec: 284 | valmap_iterator_adaptor_random operator--(int) { 285 | valmap_iterator_adaptor_random r(*this); 286 | --(*this); 287 | return r; 288 | } 289 | 290 | 291 | valmap_iterator_adaptor_random& operator+=(const difference_type& n) { 292 | this->_base += n; 293 | return *this; 294 | } 295 | valmap_iterator_adaptor_random& operator-=(const difference_type& n) { 296 | this->_base -= n; 297 | return *this; 298 | } 299 | 300 | valmap_iterator_adaptor_random operator+(const difference_type& n) const { 301 | return valmap_iterator_adaptor_random(this->_base + n); 302 | } 303 | valmap_iterator_adaptor_random operator-(const difference_type& n) const { 304 | return valmap_iterator_adaptor_random(this->_base - n); 305 | } 306 | 307 | difference_type operator-(const valmap_iterator_adaptor_random& s) const { 308 | return this->_base - s._base; 309 | } 310 | 311 | 312 | bool operator==(const valmap_iterator_adaptor_random& rhs) const { 313 | if (_base != rhs._base) return false; 314 | if (!(_vmap == rhs._vmap)) return false; 315 | return true; 316 | } 317 | bool operator!=(const valmap_iterator_adaptor_random& rhs) const { return !(*this == rhs); } 318 | 319 | bool operator<(const valmap_iterator_adaptor_random& rhs) const { 320 | return this->_base < rhs._base; 321 | } 322 | bool operator<=(const valmap_iterator_adaptor_random& rhs) const { 323 | return this->_base <= rhs._base; 324 | } 325 | bool operator>(const valmap_iterator_adaptor_random& rhs) const { 326 | return this->_base > rhs._base; 327 | } 328 | bool operator>=(const valmap_iterator_adaptor_random& rhs) const { 329 | return this->_base >= rhs._base; 330 | } 331 | }; 332 | 333 | template 334 | valmap_iterator_adaptor_random operator+(const DiffType& n, const valmap_iterator_adaptor_random& j) { 335 | return j + n; 336 | } 337 | 338 | 339 | 340 | // default will be forward iterator 341 | template 342 | struct valmap_iterator_dispatch { 343 | typedef valmap_iterator_adaptor_forward adaptor_type; 344 | }; 345 | 346 | 347 | // random access iterators 348 | template 349 | struct valmap_iterator_dispatch { 350 | typedef valmap_iterator_adaptor_random adaptor_type; 351 | }; 352 | 353 | 354 | template 355 | struct ptr_less { 356 | ptr_less() : _comp() {} 357 | virtual ~ptr_less() {} 358 | 359 | template 360 | bool operator()(const Pointer& a, const Pointer& b) const { return _comp(*a, *b); } 361 | 362 | Compare _comp; 363 | }; 364 | 365 | template 366 | struct ptr_less_data { 367 | ptr_less_data() : _comp() {} 368 | virtual ~ptr_less_data() {} 369 | 370 | template 371 | bool operator()(const Pointer& a, const Pointer& b) const { return _comp(a->data(), b->data()); } 372 | 373 | Compare _comp; 374 | }; 375 | 376 | 377 | template 378 | struct dereferenceable_lessthan { 379 | template 380 | bool operator()(const D& a, const D& b) const { return *a < *b; } 381 | }; 382 | 383 | template 384 | struct dereferenceable_lessthan > { 385 | template 386 | bool operator()(const D& a, const D& b) const { 387 | if (_lt((a.first), (b.first))) return true; 388 | if (_lt((b.first), (a.first))) return false; 389 | return *(a.second) < *(b.second); 390 | } 391 | Compare _lt; 392 | }; 393 | 394 | template 395 | struct vmap_dispatch { 396 | typedef dref_vmap vmap; 397 | }; 398 | 399 | template 400 | struct vmap_dispatch, Value> { 401 | typedef dref_second_vmap vmap; 402 | }; 403 | 404 | 405 | struct node_type_dispatch_failed {}; 406 | 407 | template 408 | struct node_type_dispatch { 409 | // catch-all should be compile error 410 | typedef node_type_dispatch_failed node_type; 411 | typedef node_type_dispatch_failed cs_value_type; 412 | }; 413 | 414 | 415 | template 416 | struct node_type_dispatch > { 417 | typedef node_raw node_type; 418 | typedef node_type* cs_value_type; 419 | }; 420 | 421 | template 422 | struct node_type_dispatch > { 423 | typedef node_ordered node_type; 424 | typedef node_type* cs_value_type; 425 | }; 426 | 427 | 428 | template 429 | struct node_type_dispatch > { 430 | typedef node_ordered > node_type; 431 | typedef node_type* cs_value_type; 432 | }; 433 | 434 | 435 | template 436 | struct node_type_dispatch > { 437 | typedef node_keyed node_type; 438 | typedef std::pair cs_value_type; 439 | }; 440 | 441 | 442 | } // namespace detail 443 | } // namespace st_tree 444 | 445 | 446 | namespace std { 447 | 448 | template 449 | void swap(st_tree::tree& a, st_tree::tree& b) { 450 | a.swap(b); 451 | } 452 | 453 | template 454 | void swap(st_tree::detail::node_raw& a, st_tree::detail::node_raw& b) { 455 | a.swap(b); 456 | } 457 | 458 | template 459 | void swap(st_tree::detail::node_ordered& a, st_tree::detail::node_ordered& b) { 460 | a.swap(b); 461 | } 462 | 463 | template 464 | void swap(st_tree::detail::node_keyed& a, st_tree::detail::node_keyed& b) { 465 | a.swap(b); 466 | } 467 | 468 | } // namespace std 469 | 470 | #endif 471 | -------------------------------------------------------------------------------- /include/st_tree_iterators.h: -------------------------------------------------------------------------------- 1 | /****** 2 | st_tree: A highly configurable C++ template tree class, using STL style interfaces. 3 | 4 | Copyright (c) 2010-2011 Erik Erlandson 5 | 6 | Author: Erik Erlandson 7 | 8 | Licensed under the Apache License, Version 2.0 (the "License"); 9 | you may not use this file except in compliance with the License. 10 | You may obtain a copy of the License at 11 | 12 | http://www.apache.org/licenses/LICENSE-2.0 13 | 14 | Unless required by applicable law or agreed to in writing, software 15 | distributed under the License is distributed on an "AS IS" BASIS, 16 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | See the License for the specific language governing permissions and 18 | limitations under the License. 19 | ******/ 20 | 21 | #if !defined(__st_tree_iterators_h__) 22 | #define __st_tree_iterators_h__ 1 23 | 24 | #if !defined(__st_tree_detail_h__) 25 | #include "st_tree_detail.h" 26 | #endif 27 | 28 | namespace st_tree { 29 | namespace detail { 30 | 31 | template 32 | struct b1st_iterator { 33 | typedef Node node_type; 34 | typedef typename Node::iterator iterator; 35 | 36 | typedef std::forward_iterator_tag iterator_category; 37 | typedef Value value_type; 38 | typedef typename iterator::difference_type difference_type; 39 | typedef Value* pointer; 40 | typedef Value& reference; 41 | 42 | b1st_iterator() : _queue() {} 43 | virtual ~b1st_iterator() {} 44 | 45 | b1st_iterator(const b1st_iterator& rhs) : _queue(rhs._queue) {} 46 | b1st_iterator& operator=(const b1st_iterator& rhs) { _queue = rhs._queue; return *this; } 47 | 48 | b1st_iterator(value_type* root) { 49 | if (root == NULL) return; 50 | _queue.push_back(const_cast(root)); 51 | } 52 | 53 | reference operator*() const { return *(_queue.front()); } 54 | pointer operator->() const { return _queue.front(); } 55 | 56 | // pre-increment iterator 57 | b1st_iterator operator++() { 58 | // if we are already past the end of elements in tree, then this is a no-op 59 | if (_queue.empty()) return *this; 60 | 61 | // take current node off front of the queue 62 | node_type* f(_queue.front()); 63 | _queue.pop_front(); 64 | 65 | if (f->empty()) return *this; 66 | for (iterator j(f->begin()); j != iterator(f->end()); ++j) 67 | _queue.push_back(&*j); 68 | 69 | return *this; 70 | } 71 | 72 | // post-increment iterator 73 | b1st_iterator operator++(int) { 74 | b1st_iterator r(*this); 75 | ++(*this); 76 | return r; 77 | } 78 | 79 | bool operator==(const b1st_iterator& rhs) const { return _queue == rhs._queue; } 80 | bool operator!=(const b1st_iterator& rhs) const { return _queue != rhs._queue; } 81 | 82 | protected: 83 | typedef typename std::allocator node_ptr_allocator_type; 84 | deque _queue; 85 | }; 86 | 87 | 88 | template 89 | struct d1st_post_iterator { 90 | typedef Node node_type; 91 | typedef typename node_type::iterator iterator; 92 | 93 | typedef std::forward_iterator_tag iterator_category; 94 | typedef Value value_type; 95 | typedef typename iterator::difference_type difference_type; 96 | typedef Value* pointer; 97 | typedef Value& reference; 98 | 99 | struct frame { 100 | frame(): first(), second(), visited() {} 101 | virtual ~frame() {} 102 | frame(const frame& rhs): first(rhs.first), second(rhs.second), visited(rhs.visited) {} 103 | frame& operator=(const frame& rhs) { first=rhs.first; second=rhs.second; visited=rhs.visited; return *this; } 104 | frame(node_type* first_, const iterator& second_, const bool& visited_) { 105 | first = first_; second = second_; visited = visited_; 106 | } 107 | bool operator==(const frame& rhs) const { 108 | if (first != rhs.first) return false; 109 | if (second != rhs.second) return false; 110 | if (visited != rhs.visited) return false; 111 | return true; 112 | } 113 | bool operator!=(const frame& rhs) const { return !(*this == rhs); } 114 | node_type* first; 115 | iterator second; 116 | bool visited; 117 | }; 118 | 119 | d1st_post_iterator() : _stack() {} 120 | virtual ~d1st_post_iterator() {} 121 | 122 | d1st_post_iterator(const d1st_post_iterator& rhs) : _stack(rhs._stack) { } 123 | d1st_post_iterator& operator=(const d1st_post_iterator& rhs) { _stack = rhs._stack; return *this; } 124 | 125 | d1st_post_iterator(value_type* root) { 126 | if (root == NULL) return; 127 | _stack.push_back(frame(const_cast(root), iterator(const_cast(root)->begin()), false)); 128 | while (true) { 129 | if (_stack.back().first->empty()) { 130 | _stack.back().visited = true; 131 | break; 132 | } 133 | iterator b(_stack.back().first->begin()); 134 | _stack.push_back(frame(&*b, iterator((b)->begin()), false)); 135 | } 136 | } 137 | 138 | reference operator*() const { return *(_stack.back().first); } 139 | pointer operator->() const { return _stack.back().first; } 140 | 141 | // pre-increment 142 | d1st_post_iterator operator++() { 143 | // if we are already past the end of elements in tree, then this is a no-op 144 | if (_stack.empty()) return *this; 145 | 146 | // check whether we are ready to pop the current frame 147 | if (_stack.back().visited) _stack.pop_back(); 148 | 149 | // empty stack flags that we just incremented past last element in tree, so leave in that state 150 | if (_stack.empty()) return *this; 151 | 152 | // we just popped up stack, so move to next child at this ply: 153 | ++(_stack.back().second); 154 | 155 | // if we have visited all the children, set the visited flag for this node 156 | if (_stack.back().second == iterator(_stack.back().first->end())) { 157 | _stack.back().visited = true; 158 | return *this; 159 | } 160 | 161 | // we found a next child at current ply: push down its first children to the bottom 162 | _stack.push_back(frame(&*(_stack.back().second), iterator((_stack.back().second)->begin()), false)); 163 | while (true) { 164 | if (_stack.back().first->empty()) { 165 | _stack.back().visited = true; 166 | break; 167 | } 168 | iterator b(_stack.back().first->begin()); 169 | _stack.push_back(frame(&*b, iterator((b)->begin()), false)); 170 | } 171 | 172 | return *this; 173 | } 174 | 175 | // post-increment 176 | d1st_post_iterator operator++(int) { 177 | d1st_post_iterator r(*this); 178 | ++(*this); 179 | return r; 180 | } 181 | 182 | bool operator==(const d1st_post_iterator& rhs) const { return _stack == rhs._stack; } 183 | bool operator!=(const d1st_post_iterator& rhs) const { return _stack != rhs._stack; } 184 | 185 | protected: 186 | typedef typename std::allocator frame_allocator_type; 187 | vector _stack; 188 | }; 189 | 190 | 191 | template 192 | struct d1st_pre_iterator { 193 | typedef Node node_type; 194 | typedef typename node_type::iterator iterator; 195 | 196 | typedef std::forward_iterator_tag iterator_category; 197 | typedef Value value_type; 198 | typedef typename iterator::difference_type difference_type; 199 | typedef Value* pointer; 200 | typedef Value& reference; 201 | 202 | struct frame { 203 | frame(): first(), second(), visited() {} 204 | virtual ~frame() {} 205 | frame(const frame& rhs): first(rhs.first), second(rhs.second), visited(rhs.visited) {} 206 | frame& operator=(const frame& rhs) { first=rhs.first; second=rhs.second; visited=rhs.visited; return *this; } 207 | frame(node_type* first_, const iterator& second_, const bool& visited_) { 208 | first = first_; second = second_; visited = visited_; 209 | } 210 | bool operator==(const frame& rhs) const { 211 | if (first != rhs.first) return false; 212 | if (second != rhs.second) return false; 213 | if (visited != rhs.visited) return false; 214 | return true; 215 | } 216 | bool operator!=(const frame& rhs) const { return !(*this == rhs); } 217 | node_type* first; 218 | iterator second; 219 | bool visited; 220 | }; 221 | 222 | d1st_pre_iterator() : _stack() {} 223 | virtual ~d1st_pre_iterator() {} 224 | 225 | d1st_pre_iterator(const d1st_pre_iterator& rhs) : _stack(rhs._stack) { } 226 | d1st_pre_iterator& operator=(const d1st_pre_iterator& rhs) { _stack = rhs._stack; return *this; } 227 | 228 | d1st_pre_iterator(value_type* root) { 229 | if (root == NULL) return; 230 | _stack.push_back(frame(const_cast(root), iterator(const_cast(root)->begin()), false)); 231 | } 232 | 233 | reference operator*() const { return *(_stack.back().first); } 234 | pointer operator->() const { return _stack.back().first; } 235 | 236 | // pre-increment 237 | d1st_pre_iterator operator++() { 238 | // if we are already past the end of elements in tree, then this is a no-op 239 | if (_stack.empty()) return *this; 240 | 241 | // check the case where this is node we have just visited pre-order 242 | if (!_stack.back().visited) { 243 | _stack.back().visited = true; 244 | if (!_stack.back().first->empty()) { 245 | _stack.push_back(frame(&*(_stack.back().second), iterator(((_stack.back().second))->begin()), false)); 246 | return *this; 247 | } 248 | } 249 | 250 | // pop off any frames we're finished with 251 | while (true) { 252 | if (!_stack.back().first->empty()) { 253 | ++(_stack.back().second); 254 | // in this case, we're not finished at this frame: 255 | if (_stack.back().second != iterator(_stack.back().first->end())) break; 256 | } 257 | _stack.pop_back(); 258 | // if we emptied the stack, we're at end of tree elements 259 | if (_stack.empty()) return *this; 260 | } 261 | 262 | // push the next child 263 | _stack.push_back(frame(&*(_stack.back().second), iterator(((_stack.back().second))->begin()), false)); 264 | 265 | return *this; 266 | } 267 | 268 | // post-increment 269 | d1st_pre_iterator operator++(int) { 270 | d1st_pre_iterator r(*this); 271 | ++(*this); 272 | return r; 273 | } 274 | 275 | bool operator==(const d1st_pre_iterator& rhs) const { return _stack == rhs._stack; } 276 | bool operator!=(const d1st_pre_iterator& rhs) const { return _stack != rhs._stack; } 277 | 278 | protected: 279 | typedef typename std::allocator frame_allocator_type; 280 | vector _stack; 281 | }; 282 | 283 | 284 | } // namespace detail 285 | } // namespace st_tree 286 | 287 | 288 | #endif 289 | -------------------------------------------------------------------------------- /tests/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # unit testing is built on the boost unit testing package 2 | find_package(Boost 1.36 COMPONENTS unit_test_framework) 3 | 4 | # include path to st_tree.h 5 | include_directories(${st_tree_SOURCE_DIR}/include) 6 | 7 | if (Boost_FOUND) 8 | enable_testing() 9 | 10 | add_executable(unit_tests 11 | unit_tests.cpp 12 | ut_exception.cpp 13 | ut_vmap_iter.cpp 14 | ut_raw.cpp 15 | ut_ordered.cpp 16 | ut_keyed.cpp 17 | ) 18 | target_compile_definitions(unit_tests PRIVATE BOOST_ALL_NO_LIB=1) 19 | if (NOT Boost_USE_STATIC_LIBS) 20 | target_compile_definitions(unit_tests PRIVATE BOOST_TEST_DYN_LINK=1) 21 | endif () 22 | target_link_libraries(unit_tests Boost::unit_test_framework) 23 | 24 | add_test(NAME unit_tests COMMAND unit_tests) 25 | add_custom_target(test COMMAND unit_tests DEPENDS unit_tests) 26 | endif () 27 | -------------------------------------------------------------------------------- /tests/unit_tests.cpp: -------------------------------------------------------------------------------- 1 | #define BOOST_TEST_MODULE st_tree 2 | #include 3 | -------------------------------------------------------------------------------- /tests/ut_common.h: -------------------------------------------------------------------------------- 1 | /****** 2 | st_tree: An easy to use and highly configurable C++ template tree class, 3 | using STL container style interfaces. 4 | 5 | Copyright (c) 2010-2011 Erik Erlandson 6 | 7 | Author: Erik Erlandson 8 | 9 | Licensed under the Apache License, Version 2.0 (the "License"); 10 | you may not use this file except in compliance with the License. 11 | You may obtain a copy of the License at 12 | 13 | http://www.apache.org/licenses/LICENSE-2.0 14 | 15 | Unless required by applicable law or agreed to in writing, software 16 | distributed under the License is distributed on an "AS IS" BASIS, 17 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | See the License for the specific language governing permissions and 19 | limitations under the License. 20 | ******/ 21 | 22 | #if !defined(__ut_common_h__) 23 | #define __ut_common_h__ 1 24 | 25 | 26 | #include 27 | #include 28 | 29 | #include "st_tree.h" 30 | 31 | using namespace st_tree; 32 | using std::string; 33 | using std::pair; 34 | 35 | template 36 | typename Tree::const_bf_iterator bf_begin(const Tree& t) { 37 | return t.bf_begin(); 38 | } 39 | template 40 | typename Tree::const_bf_iterator bf_end(const Tree& t) { 41 | return t.bf_end(); 42 | } 43 | template 44 | typename Tree::const_bf_iterator& bf_j(const Tree& t) { 45 | static typename Tree::const_bf_iterator j; 46 | return j; 47 | } 48 | 49 | template 50 | typename Tree::const_df_pre_iterator df_pre_begin(const Tree& t) { 51 | return t.df_pre_begin(); 52 | } 53 | template 54 | typename Tree::const_df_pre_iterator df_pre_end(const Tree& t) { 55 | return t.df_pre_end(); 56 | } 57 | template 58 | typename Tree::const_df_pre_iterator& df_pre_j(const Tree& t) { 59 | static typename Tree::const_df_pre_iterator j; 60 | return j; 61 | } 62 | 63 | template 64 | typename Tree::const_df_post_iterator df_post_begin(const Tree& t) { 65 | return t.df_post_begin(); 66 | } 67 | template 68 | typename Tree::const_df_post_iterator df_post_end(const Tree& t) { 69 | return t.df_post_end(); 70 | } 71 | template 72 | typename Tree::const_df_post_iterator& df_post_j(const Tree& t) { 73 | static typename Tree::const_df_post_iterator j; 74 | return j; 75 | } 76 | 77 | 78 | // These were more elegant with typedef(), but does ansi support typedef? Nooooo. 79 | #define CHECK_TREE(t, meth, ref) { \ 80 | std::stringstream tst; \ 81 | for (bf_j(t) = bf_begin(t); bf_j(t) != bf_end(t); ++bf_j(t)) { \ 82 | if (bf_j(t) != bf_begin(t)) tst << " "; \ 83 | tst << bf_j(t)->meth; \ 84 | } \ 85 | BOOST_CHECK_MESSAGE(tst.str() == ref, "Checking " << #meth << ": Expected \"" << ref << "\" received \"" << tst.str() << "\"\n"); \ 86 | } 87 | 88 | 89 | #define CHECK_TREE_DF_POST(t, meth, ref) { \ 90 | std::stringstream tst; \ 91 | for (df_post_j(t) = df_post_begin(t); df_post_j(t) != df_post_end(t); ++df_post_j(t)) { \ 92 | if (df_post_j(t) != df_post_begin(t)) tst << " "; \ 93 | tst << df_post_j(t)->meth; \ 94 | } \ 95 | BOOST_CHECK_MESSAGE(tst.str() == ref, "Checking " << #meth << ": Expected \"" << ref << "\" received \"" << tst.str() << "\"\n"); \ 96 | } 97 | 98 | 99 | #define CHECK_TREE_DF_PRE(t, meth, ref) { \ 100 | std::stringstream tst; \ 101 | for (df_pre_j(t) = df_pre_begin(t); df_pre_j(t) != df_pre_end(t); ++df_pre_j(t)) { \ 102 | if (df_pre_j(t) != df_pre_begin(t)) tst << " "; \ 103 | tst << df_pre_j(t)->meth; \ 104 | } \ 105 | BOOST_CHECK_MESSAGE(tst.str() == ref, "Checking " << #meth << ": Expected \"" << ref << "\" received \"" << tst.str() << "\"\n"); \ 106 | } 107 | 108 | 109 | #endif 110 | -------------------------------------------------------------------------------- /tests/ut_exception.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "st_tree.h" 4 | #include "ut_common.h" 5 | 6 | 7 | BOOST_AUTO_TEST_SUITE(ut_exception) 8 | 9 | 10 | BOOST_AUTO_TEST_CASE(exceptions) { 11 | parent_exception px("a"); 12 | orphan_exception ox("b"); 13 | cycle_exception cx("c"); 14 | empty_exception ex("d"); 15 | missing_exception mx("e"); 16 | 17 | string t; 18 | 19 | t = px.what(); 20 | BOOST_CHECK_EQUAL(t, "a"); 21 | 22 | t = ox.what(); 23 | BOOST_CHECK_EQUAL(t, "b"); 24 | 25 | t = cx.what(); 26 | BOOST_CHECK_EQUAL(t, "c"); 27 | 28 | t = ex.what(); 29 | BOOST_CHECK_EQUAL(t, "d"); 30 | 31 | t = mx.what(); 32 | BOOST_CHECK_EQUAL(t, "e"); 33 | } 34 | 35 | 36 | BOOST_AUTO_TEST_SUITE_END() // ut_exception 37 | -------------------------------------------------------------------------------- /tests/ut_keyed.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "st_tree.h" 4 | #include "ut_common.h" 5 | 6 | 7 | BOOST_AUTO_TEST_SUITE(ut_keyed) 8 | 9 | 10 | BOOST_AUTO_TEST_CASE(default_ctor) { 11 | tree > t1; 12 | BOOST_CHECK(t1.empty()); 13 | BOOST_CHECK_EQUAL(t1.size(), 0); 14 | BOOST_CHECK_EQUAL(t1.depth(), 0); 15 | BOOST_CHECK_THROW(t1.root(), st_tree::exception); 16 | } 17 | 18 | BOOST_AUTO_TEST_CASE(insert_root) { 19 | tree > t1; 20 | t1.insert(7); 21 | BOOST_CHECK_EQUAL(t1.empty(), false); 22 | BOOST_CHECK_EQUAL(t1.size(), 1); 23 | BOOST_CHECK_EQUAL(t1.depth(), 1); 24 | BOOST_CHECK_EQUAL(t1.root().is_root(), true); 25 | BOOST_CHECK_EQUAL(t1.root().data(), 7); 26 | BOOST_CHECK_THROW(t1.root().parent(), st_tree::exception); 27 | } 28 | 29 | 30 | BOOST_AUTO_TEST_CASE(insert_subnodes) { 31 | tree > t1; 32 | typedef tree >::node_type::kv_pair kv_pair; 33 | 34 | t1.insert(7); 35 | BOOST_CHECK_EQUAL(t1.empty(), false); 36 | BOOST_CHECK_EQUAL(t1.size(), 1); 37 | BOOST_CHECK_EQUAL(t1.depth(), 1); 38 | BOOST_CHECK_EQUAL(t1.root().size(), 0); 39 | 40 | t1.root().insert(kv_pair("0", 8)); 41 | BOOST_CHECK_EQUAL(t1.size(), 2); 42 | BOOST_CHECK_EQUAL(t1.depth(), 2); 43 | BOOST_CHECK_EQUAL(t1.empty(), false); 44 | BOOST_CHECK_EQUAL(t1.root().size(), 1); 45 | 46 | t1.root().insert(kv_pair("1", 9)); 47 | BOOST_CHECK_EQUAL(t1.size(), 3); 48 | BOOST_CHECK_EQUAL(t1.depth(), 2); 49 | BOOST_CHECK_EQUAL(t1.empty(), false); 50 | BOOST_CHECK_EQUAL(t1.root().size(), 2); 51 | 52 | BOOST_CHECK_EQUAL(t1.root().data(), 7); 53 | BOOST_CHECK_EQUAL(t1.root()["0"].data(), 8); 54 | BOOST_CHECK_EQUAL(t1.root()["1"].data(), 9); 55 | } 56 | 57 | BOOST_AUTO_TEST_CASE(emplace_subnodes) { 58 | struct str1 { 59 | int i1; 60 | std::string s1; 61 | str1() { 62 | i1 = 0; 63 | s1 = ""; 64 | } 65 | str1(int i, const std::string s) { 66 | i1 = i; 67 | s1 = s; 68 | } 69 | }; 70 | 71 | tree > t1; 72 | 73 | t1.emplace(7 , "7"); 74 | BOOST_CHECK_EQUAL(t1.empty(), false); 75 | BOOST_CHECK_EQUAL(t1.size(), 1); 76 | BOOST_CHECK_EQUAL(t1.depth(), 1); 77 | BOOST_CHECK_EQUAL(t1.root().size(), 0); 78 | 79 | t1.root().emplace_insert("0", 8, "8"); 80 | BOOST_CHECK_EQUAL(t1.size(), 2); 81 | BOOST_CHECK_EQUAL(t1.depth(), 2); 82 | BOOST_CHECK_EQUAL(t1.empty(), false); 83 | BOOST_CHECK_EQUAL(t1.root().size(), 1); 84 | 85 | t1.root().emplace_insert("1", 9, "9"); 86 | BOOST_CHECK_EQUAL(t1.size(), 3); 87 | BOOST_CHECK_EQUAL(t1.depth(), 2); 88 | BOOST_CHECK_EQUAL(t1.empty(), false); 89 | BOOST_CHECK_EQUAL(t1.root().size(), 2); 90 | 91 | BOOST_CHECK_EQUAL(t1.root().data().i1, 7); 92 | BOOST_CHECK_EQUAL(t1.root()["0"].data().i1, 8); 93 | BOOST_CHECK_EQUAL(t1.root()["1"].data().i1, 9); 94 | 95 | BOOST_CHECK_EQUAL(t1.root().data().s1, "7"); 96 | BOOST_CHECK_EQUAL(t1.root()["0"].data().s1, "8"); 97 | BOOST_CHECK_EQUAL(t1.root()["1"].data().s1, "9"); 98 | } 99 | 100 | BOOST_AUTO_TEST_CASE(clear) { 101 | tree > t1; 102 | 103 | t1.insert(7); 104 | t1.root().insert("0", 8); 105 | t1.root().insert("1", 9); 106 | BOOST_CHECK_EQUAL(t1.size(), 3); 107 | BOOST_CHECK_EQUAL(t1.depth(), 2); 108 | BOOST_CHECK_EQUAL(t1.empty(), false); 109 | BOOST_CHECK_EQUAL(t1.root().size(), 2); 110 | 111 | CHECK_TREE(t1, data(), "7 8 9"); 112 | 113 | t1.clear(); 114 | BOOST_CHECK_EQUAL(t1.size(), 0); 115 | BOOST_CHECK_EQUAL(t1.depth(), 0); 116 | BOOST_CHECK_EQUAL(t1.empty(), true); 117 | BOOST_CHECK_THROW(t1.root(), st_tree::exception); 118 | } 119 | 120 | 121 | BOOST_AUTO_TEST_CASE(reinsert) { 122 | tree > t1; 123 | 124 | t1.insert(7); 125 | t1.root().insert("0", 8); 126 | t1.root().insert("1", 9); 127 | BOOST_CHECK_EQUAL(t1.size(), 3); 128 | BOOST_CHECK_EQUAL(t1.depth(), 2); 129 | BOOST_CHECK_EQUAL(t1.empty(), false); 130 | BOOST_CHECK_EQUAL(t1.root().size(), 2); 131 | CHECK_TREE(t1, data(), "7 8 9"); 132 | 133 | t1.insert(3); 134 | BOOST_CHECK_EQUAL(t1.size(), 1); 135 | BOOST_CHECK_EQUAL(t1.depth(), 1); 136 | BOOST_CHECK_EQUAL(t1.empty(), false); 137 | BOOST_CHECK_EQUAL(t1.root().size(), 0); 138 | BOOST_CHECK_EQUAL(t1.root().data(), 3); 139 | CHECK_TREE(t1, data(), "3"); 140 | } 141 | 142 | 143 | BOOST_AUTO_TEST_CASE(erase) { 144 | tree > t1; 145 | 146 | t1.insert(7); 147 | t1.root().insert("0", 8); 148 | CHECK_TREE(t1, data(), "7 8"); 149 | 150 | t1.root().erase(t1.root().begin()); 151 | BOOST_CHECK_EQUAL(t1.size(), 1); 152 | BOOST_CHECK_EQUAL(t1.depth(), 1); 153 | BOOST_CHECK_EQUAL(t1.empty(), false); 154 | BOOST_CHECK_EQUAL(t1.root().size(), 0); 155 | BOOST_CHECK_EQUAL(t1.root().data(), 7); 156 | } 157 | 158 | 159 | BOOST_AUTO_TEST_CASE(erase_noarg) { 160 | tree > t1; 161 | 162 | t1.insert(2); 163 | t1.root().insert("0", 3); 164 | t1.root().insert("1", 5); 165 | t1.root()["0"].insert("0",7); 166 | t1.root()["0"].insert("1",11); 167 | t1.root()["1"].insert("0",13); 168 | t1.root()["1"].insert("1",17); 169 | 170 | CHECK_TREE(t1, data(), "2 3 5 7 11 13 17"); 171 | t1.root()["1"].erase(); 172 | CHECK_TREE(t1, data(), "2 3 7 11"); 173 | 174 | t1.root()["0"]["1"].erase(); 175 | CHECK_TREE(t1, data(), "2 3 7"); 176 | 177 | t1.root().erase(); 178 | BOOST_CHECK_EQUAL(t1.empty(), true); 179 | CHECK_TREE(t1, data(), ""); 180 | } 181 | 182 | 183 | BOOST_AUTO_TEST_CASE(bf_iterator_empty) { 184 | tree > t1; 185 | 186 | BOOST_CHECK_EQUAL(t1.bf_begin() == t1.bf_end(), true); 187 | BOOST_CHECK_EQUAL(t1.bf_begin() != t1.bf_end(), false); 188 | } 189 | 190 | 191 | BOOST_AUTO_TEST_CASE(bf_iterator) { 192 | tree > t1; 193 | 194 | CHECK_TREE(t1, data(), ""); 195 | 196 | t1.insert(2); 197 | CHECK_TREE(t1, data(), "2"); 198 | 199 | t1.root().insert("0", 3); 200 | t1.root().insert("1", 5); 201 | CHECK_TREE(t1, data(), "2 3 5"); 202 | 203 | t1.root()["0"].insert("0",7); 204 | t1.root()["1"].insert("0",13); 205 | t1.root()["0"].insert("1",11); 206 | t1.root()["1"].insert("1",17); 207 | CHECK_TREE(t1, data(), "2 3 5 7 11 13 17"); 208 | CHECK_TREE(t1.root(), data(), "2 3 5 7 11 13 17"); 209 | } 210 | 211 | 212 | BOOST_AUTO_TEST_CASE(df_post_iterator_empty) { 213 | tree > t1; 214 | 215 | BOOST_CHECK_EQUAL(t1.df_post_begin() == t1.df_post_end(), true); 216 | BOOST_CHECK_EQUAL(t1.df_post_begin() != t1.df_post_end(), false); 217 | } 218 | 219 | 220 | BOOST_AUTO_TEST_CASE(df_post_iterator) { 221 | tree > t1; 222 | 223 | CHECK_TREE_DF_POST(t1, data(), ""); 224 | 225 | t1.insert(2); 226 | CHECK_TREE_DF_POST(t1, data(), "2"); 227 | 228 | t1.root().insert("0",3); 229 | t1.root().insert("1",5); 230 | CHECK_TREE_DF_POST(t1, data(), "3 5 2"); 231 | 232 | t1.root()["0"].insert("0",7); 233 | t1.root()["1"].insert("0",13); 234 | t1.root()["0"].insert("1",11); 235 | t1.root()["1"].insert("1",17); 236 | CHECK_TREE_DF_POST(t1, data(), "7 11 3 13 17 5 2"); 237 | CHECK_TREE_DF_POST(t1.root(), data(), "7 11 3 13 17 5 2"); 238 | } 239 | 240 | 241 | BOOST_AUTO_TEST_CASE(df_pre_iterator_empty) { 242 | tree > t1; 243 | 244 | BOOST_CHECK_EQUAL(t1.df_pre_begin() == t1.df_pre_end(), true); 245 | BOOST_CHECK_EQUAL(t1.df_pre_begin() != t1.df_pre_end(), false); 246 | } 247 | 248 | 249 | BOOST_AUTO_TEST_CASE(df_pre_iterator) { 250 | tree > t1; 251 | 252 | CHECK_TREE_DF_PRE(t1, data(), ""); 253 | 254 | t1.insert(2); 255 | CHECK_TREE_DF_PRE(t1, data(), "2"); 256 | 257 | t1.root().insert("0",3); 258 | t1.root().insert("1",5); 259 | CHECK_TREE_DF_PRE(t1, data(), "2 3 5"); 260 | 261 | t1.root()["0"].insert("0",7); 262 | t1.root()["1"].insert("0",13); 263 | t1.root()["0"].insert("1",11); 264 | t1.root()["1"].insert("1",17); 265 | CHECK_TREE_DF_PRE(t1, data(), "2 3 7 11 5 13 17"); 266 | CHECK_TREE_DF_PRE(t1.root(), data(), "2 3 7 11 5 13 17"); 267 | } 268 | 269 | 270 | BOOST_AUTO_TEST_CASE(node_ply) { 271 | tree > t1; 272 | 273 | t1.insert(2); 274 | CHECK_TREE(t1, data(), "2"); 275 | CHECK_TREE(t1, ply(), "0"); 276 | 277 | t1.root().insert("0",3); 278 | t1.root().insert("1",5); 279 | CHECK_TREE(t1, data(), "2 3 5"); 280 | CHECK_TREE(t1, ply(), "0 1 1"); 281 | 282 | t1.root()["0"].insert("0",7); 283 | t1.root()["0"].insert("1",11); 284 | t1.root()["1"].insert("0",13); 285 | t1.root()["1"].insert("1",17); 286 | CHECK_TREE(t1, data(), "2 3 5 7 11 13 17"); 287 | CHECK_TREE(t1, ply(), "0 1 1 2 2 2 2"); 288 | 289 | t1.root().insert("2",77); 290 | CHECK_TREE(t1, data(), "2 3 5 77 7 11 13 17"); 291 | CHECK_TREE(t1, ply(), "0 1 1 1 2 2 2 2"); 292 | 293 | t1.root().erase(t1.root().begin()); 294 | CHECK_TREE(t1, data(), "2 5 77 13 17"); 295 | CHECK_TREE(t1, ply(), "0 1 1 2 2"); 296 | 297 | t1.root().erase(t1.root().begin()); 298 | CHECK_TREE(t1, data(), "2 77"); 299 | CHECK_TREE(t1, ply(), "0 1"); 300 | 301 | t1.root().erase(t1.root().begin()); 302 | CHECK_TREE(t1, data(), "2"); 303 | CHECK_TREE(t1, ply(), "0"); 304 | } 305 | 306 | BOOST_AUTO_TEST_CASE(node_depth) { 307 | tree > t1; 308 | 309 | t1.insert(2); 310 | CHECK_TREE(t1, data(), "2"); 311 | CHECK_TREE(t1, depth(), "1"); 312 | CHECK_TREE(t1, ply(), "0"); 313 | 314 | t1.root().insert("0",3); 315 | t1.root().insert("1",5); 316 | CHECK_TREE(t1, data(), "2 3 5"); 317 | CHECK_TREE(t1, depth(), "2 1 1"); 318 | CHECK_TREE(t1, ply(), "0 1 1"); 319 | 320 | t1.root()["0"].insert("0",7); 321 | t1.root()["0"].insert("1",11); 322 | t1.root()["1"].insert("0",13); 323 | t1.root()["1"].insert("1",17); 324 | CHECK_TREE(t1, data(), "2 3 5 7 11 13 17"); 325 | CHECK_TREE(t1, depth(), "3 2 2 1 1 1 1"); 326 | CHECK_TREE(t1, ply(), "0 1 1 2 2 2 2"); 327 | 328 | t1.root().insert("2",77); 329 | CHECK_TREE(t1, data(), "2 3 5 77 7 11 13 17"); 330 | CHECK_TREE(t1, depth(), "3 2 2 1 1 1 1 1"); 331 | CHECK_TREE(t1, ply(), "0 1 1 1 2 2 2 2"); 332 | 333 | t1.root().erase(t1.root().begin()); 334 | CHECK_TREE(t1, data(), "2 5 77 13 17"); 335 | CHECK_TREE(t1, depth(), "3 2 1 1 1"); 336 | 337 | t1.root().erase(t1.root().begin()); 338 | CHECK_TREE(t1, data(), "2 77"); 339 | CHECK_TREE(t1, depth(), "2 1"); 340 | 341 | t1.root().erase(t1.root().begin()); 342 | CHECK_TREE(t1, data(), "2"); 343 | CHECK_TREE(t1, depth(), "1"); 344 | } 345 | 346 | BOOST_AUTO_TEST_CASE(node_subtree_size) { 347 | tree > t1; 348 | 349 | t1.insert(2); 350 | CHECK_TREE(t1, data(), "2"); 351 | CHECK_TREE(t1, subtree_size(), "1"); 352 | 353 | t1.root().insert("0",3); 354 | t1.root().insert("1",5); 355 | CHECK_TREE(t1, data(), "2 3 5"); 356 | CHECK_TREE(t1, subtree_size(), "3 1 1"); 357 | 358 | t1.root()["0"].insert("0",7); 359 | t1.root()["0"].insert("1",11); 360 | t1.root()["1"].insert("0",13); 361 | t1.root()["1"].insert("1",17); 362 | CHECK_TREE(t1, data(), "2 3 5 7 11 13 17"); 363 | CHECK_TREE(t1, subtree_size(), "7 3 3 1 1 1 1"); 364 | 365 | t1.root().insert("2",77); 366 | CHECK_TREE(t1, data(), "2 3 5 77 7 11 13 17"); 367 | CHECK_TREE(t1, subtree_size(), "8 3 3 1 1 1 1 1"); 368 | 369 | t1.root().erase(t1.root().begin()); 370 | CHECK_TREE(t1, data(), "2 5 77 13 17"); 371 | CHECK_TREE(t1, subtree_size(), "5 3 1 1 1"); 372 | 373 | t1.root().erase(t1.root().begin()); 374 | CHECK_TREE(t1, data(), "2 77"); 375 | CHECK_TREE(t1, subtree_size(), "2 1"); 376 | 377 | t1.root().erase(t1.root().begin()); 378 | CHECK_TREE(t1, data(), "2"); 379 | CHECK_TREE(t1, subtree_size(), "1"); 380 | } 381 | 382 | BOOST_AUTO_TEST_CASE(node_parent) { 383 | tree > t1; 384 | 385 | t1.insert(2); 386 | BOOST_CHECK_THROW(t1.root().parent(), st_tree::exception); 387 | t1.root().insert("0",3); 388 | BOOST_CHECK_EQUAL(t1.root()["0"].parent().data(), 2); 389 | const tree >& t2 = t1; 390 | BOOST_CHECK_EQUAL(t2.root()["0"].parent().data(), 2); 391 | } 392 | 393 | 394 | BOOST_AUTO_TEST_CASE(node_tree) { 395 | tree > t1; 396 | 397 | t1.insert(2); 398 | t1.root().insert("0",3); 399 | t1.root().insert("1",5); 400 | tree >& t2 = t1.root().tree(); 401 | BOOST_CHECK_EQUAL(t1 == t2, true); 402 | t2 = t1.root()["0"].tree(); 403 | BOOST_CHECK_EQUAL(t1 == t2, true); 404 | const tree >& t3 = t1; 405 | const tree >& t4 = t3.root().tree(); 406 | BOOST_CHECK_EQUAL(t1 == t4, true); 407 | } 408 | 409 | 410 | BOOST_AUTO_TEST_CASE(erase_node) { 411 | tree > t1; 412 | 413 | t1.insert(2); 414 | t1.root().insert("0",3); 415 | t1.root().insert("1",5); 416 | t1.root()["0"].insert("0",7); 417 | t1.root()["1"].insert("0",13); 418 | t1.root()["0"].insert("1",11); 419 | t1.root()["1"].insert("1",17); 420 | BOOST_CHECK_EQUAL(t1.size(), 7); 421 | BOOST_CHECK_EQUAL(t1.depth(), 3); 422 | 423 | t1.root().erase(t1.root().begin()); 424 | BOOST_CHECK_EQUAL(t1.size(), 4); 425 | BOOST_CHECK_EQUAL(t1.depth(), 3); 426 | 427 | CHECK_TREE(t1, data(), "2 5 13 17"); 428 | CHECK_TREE(t1, ply(), "0 1 2 2"); 429 | CHECK_TREE(t1, subtree_size(), "4 3 1 1"); 430 | } 431 | 432 | 433 | BOOST_AUTO_TEST_CASE(clear_node) { 434 | tree > t1; 435 | 436 | t1.insert(2); 437 | t1.root().insert("0",3); 438 | t1.root().insert("1",5); 439 | t1.root()["0"].insert("0",7); 440 | t1.root()["1"].insert("0",13); 441 | t1.root()["0"].insert("1",11); 442 | t1.root()["1"].insert("1",17); 443 | BOOST_CHECK_EQUAL(t1.size(), 7); 444 | BOOST_CHECK_EQUAL(t1.depth(), 3); 445 | 446 | t1.root().clear(); 447 | BOOST_CHECK_EQUAL(t1.size(), 1); 448 | BOOST_CHECK_EQUAL(t1.depth(), 1); 449 | 450 | CHECK_TREE(t1, data(), "2"); 451 | CHECK_TREE(t1, ply(), "0"); 452 | CHECK_TREE(t1, subtree_size(), "1"); 453 | } 454 | 455 | 456 | BOOST_AUTO_TEST_CASE(node_op_equal) { 457 | tree > t1; 458 | 459 | t1.insert(2); 460 | t1.root().insert("0",3); 461 | 462 | CHECK_TREE(t1, data(), "2 3"); 463 | CHECK_TREE(t1, ply(), "0 1"); 464 | CHECK_TREE(t1, key(), " 0"); 465 | 466 | tree > t2; 467 | t2.insert(5); 468 | t2.root().insert("0",7); 469 | t2.root().insert("1",11); 470 | 471 | t1.root()["0"] = t2.root(); 472 | BOOST_CHECK_EQUAL(t1.size(), 4); 473 | BOOST_CHECK_EQUAL(t1.depth(), 3); 474 | 475 | CHECK_TREE(t1, data(), "2 5 7 11"); 476 | CHECK_TREE(t1, ply(), "0 1 2 2"); 477 | CHECK_TREE(t1, subtree_size(), "4 3 1 1"); 478 | CHECK_TREE(t1, key(), " 0 0 1"); 479 | 480 | CHECK_TREE(t2, data(), "5 7 11"); 481 | CHECK_TREE(t2, ply(), "0 1 1"); 482 | CHECK_TREE(t2, subtree_size(), "3 1 1"); 483 | } 484 | 485 | 486 | BOOST_AUTO_TEST_CASE(node_op_equal_root) { 487 | tree > t1; 488 | 489 | t1.insert(2); 490 | t1.root().insert("0",3); 491 | 492 | tree > t2; 493 | t2.insert(5); 494 | t2.root().insert("0",7); 495 | t2.root().insert("1",11); 496 | 497 | t1.root() = t2.root(); 498 | BOOST_CHECK_EQUAL(t1.size(), 3); 499 | BOOST_CHECK_EQUAL(t1.depth(), 2); 500 | 501 | CHECK_TREE(t1, data(), "5 7 11"); 502 | CHECK_TREE(t1, ply(), "0 1 1"); 503 | CHECK_TREE(t1, subtree_size(), "3 1 1"); 504 | CHECK_TREE(t1, key(), " 0 1"); 505 | 506 | CHECK_TREE(t2, data(), "5 7 11"); 507 | CHECK_TREE(t2, ply(), "0 1 1"); 508 | CHECK_TREE(t1, subtree_size(), "3 1 1"); 509 | } 510 | 511 | 512 | BOOST_AUTO_TEST_CASE(node_op_equal_subtree) { 513 | tree > t1; 514 | 515 | t1.insert(2); 516 | t1.root().insert("0",3); 517 | t1.root().insert("1",5); 518 | t1.root()["0"].insert("0",7); 519 | t1.root()["0"].insert("1",11); 520 | t1.root()["1"].insert("0",13); 521 | t1.root()["1"].insert("1",17); 522 | 523 | BOOST_CHECK_THROW(t1.root()["0"] = t1.root(), st_tree::exception); 524 | 525 | t1.root() = t1.root()["0"]; 526 | CHECK_TREE(t1, data(), "3 7 11"); 527 | CHECK_TREE(t1, key(), " 0 1"); 528 | BOOST_CHECK_EQUAL(t1.size(), 3); 529 | BOOST_CHECK_EQUAL(t1.depth(), 2); 530 | 531 | t1.root()["1"].insert("0",13); 532 | t1.root()["1"].insert("1",17); 533 | t1.root()["1"] = t1.root()["1"]["1"]; 534 | CHECK_TREE(t1, data(), "3 7 17"); 535 | CHECK_TREE(t1, key(), " 0 1"); 536 | } 537 | 538 | BOOST_AUTO_TEST_CASE(node_swap) { 539 | tree > t1; 540 | tree > t2; 541 | 542 | t1.insert(2); 543 | t1.root().insert("0",3); 544 | t1.root().insert("1",5); 545 | t1.root()["0"].insert("0",7); 546 | t1.root()["0"].insert("1",11); 547 | 548 | t2.insert(102); 549 | t2.root().insert("0",103); 550 | t2.root().insert("1",105); 551 | t2.root()["0"].insert("0",107); 552 | t2.root()["0"].insert("1",111); 553 | 554 | // swap a leaf 555 | swap(t1.root()["0"]["0"], t2.root()["0"]["0"]); 556 | BOOST_CHECK_EQUAL(t1.size(), 5); 557 | BOOST_CHECK_EQUAL(t1.depth(), 3); 558 | CHECK_TREE(t1, data(), "2 3 5 107 11"); 559 | CHECK_TREE(t1, ply(), "0 1 1 2 2"); 560 | CHECK_TREE(t1, depth(), "3 2 1 1 1"); 561 | CHECK_TREE(t1, subtree_size(), "5 3 1 1 1"); 562 | 563 | BOOST_CHECK_EQUAL(t2.size(), 5); 564 | BOOST_CHECK_EQUAL(t2.depth(), 3); 565 | CHECK_TREE(t2, data(), "102 103 105 7 111"); 566 | CHECK_TREE(t2, ply(), "0 1 1 2 2"); 567 | CHECK_TREE(t2, depth(), "3 2 1 1 1"); 568 | CHECK_TREE(t2, subtree_size(), "5 3 1 1 1"); 569 | 570 | // put it back 571 | swap(t1.root()["0"]["0"], t2.root()["0"]["0"]); 572 | 573 | // swap an internal 574 | swap(t1.root()["0"], t2.root()["0"]); 575 | BOOST_CHECK_EQUAL(t1.size(), 5); 576 | BOOST_CHECK_EQUAL(t1.depth(), 3); 577 | CHECK_TREE(t1, data(), "2 103 5 107 111"); 578 | CHECK_TREE(t1, ply(), "0 1 1 2 2"); 579 | CHECK_TREE(t1, depth(), "3 2 1 1 1"); 580 | CHECK_TREE(t1, subtree_size(), "5 3 1 1 1"); 581 | BOOST_CHECK_EQUAL(t2.size(), 5); 582 | BOOST_CHECK_EQUAL(t2.depth(), 3); 583 | CHECK_TREE(t2, data(), "102 3 105 7 11"); 584 | CHECK_TREE(t2, ply(), "0 1 1 2 2"); 585 | CHECK_TREE(t2, depth(), "3 2 1 1 1"); 586 | CHECK_TREE(t2, subtree_size(), "5 3 1 1 1"); 587 | 588 | // put it back 589 | swap(t1.root()["0"], t2.root()["0"]); 590 | 591 | // swap the root 592 | swap(t1.root(), t2.root()); 593 | BOOST_CHECK_EQUAL(t1.size(), 5); 594 | BOOST_CHECK_EQUAL(t1.depth(), 3); 595 | CHECK_TREE(t1, data(), "102 103 105 107 111"); 596 | CHECK_TREE(t1, ply(), "0 1 1 2 2"); 597 | CHECK_TREE(t1, depth(), "3 2 1 1 1"); 598 | CHECK_TREE(t1, subtree_size(), "5 3 1 1 1"); 599 | BOOST_CHECK_EQUAL(t2.size(), 5); 600 | BOOST_CHECK_EQUAL(t2.depth(), 3); 601 | CHECK_TREE(t2, data(), "2 3 5 7 11"); 602 | CHECK_TREE(t2, ply(), "0 1 1 2 2"); 603 | CHECK_TREE(t2, depth(), "3 2 1 1 1"); 604 | CHECK_TREE(t2, subtree_size(), "5 3 1 1 1"); 605 | 606 | // put it back 607 | swap(t1.root(), t2.root()); 608 | 609 | // swap different plies 610 | swap(t1.root(), t2.root()["0"]); 611 | BOOST_CHECK_EQUAL(t1.size(), 3); 612 | BOOST_CHECK_EQUAL(t1.depth(), 2); 613 | CHECK_TREE(t1, data(), "103 107 111"); 614 | CHECK_TREE(t1, ply(), "0 1 1"); 615 | CHECK_TREE(t1, depth(), "2 1 1"); 616 | CHECK_TREE(t1, subtree_size(), "3 1 1"); 617 | BOOST_CHECK_EQUAL(t2.size(), 7); 618 | BOOST_CHECK_EQUAL(t2.depth(), 4); 619 | CHECK_TREE(t2, data(), "102 2 105 3 5 7 11"); 620 | CHECK_TREE(t2, ply(), "0 1 1 2 2 3 3"); 621 | CHECK_TREE(t2, depth(), "4 3 1 2 1 1 1"); 622 | CHECK_TREE(t2, subtree_size(), "7 5 1 3 1 1 1"); 623 | 624 | // put them back 625 | swap(t1.root(), t2.root()["0"]); 626 | 627 | // on same tree 628 | swap(t1.root()["0"], t1.root()["1"]); 629 | BOOST_CHECK_EQUAL(t1.size(), 5); 630 | BOOST_CHECK_EQUAL(t1.depth(), 3); 631 | CHECK_TREE(t1, data(), "2 5 3 7 11"); 632 | CHECK_TREE(t1, ply(), "0 1 1 2 2"); 633 | CHECK_TREE(t1, depth(), "3 1 2 1 1"); 634 | CHECK_TREE(t1, subtree_size(), "5 1 3 1 1"); 635 | 636 | // put them back 637 | swap(t1.root()["0"], t1.root()["1"]); 638 | 639 | // no-no 640 | BOOST_CHECK_THROW(swap(t1.root(), t1.root()["0"]), st_tree::exception); 641 | BOOST_CHECK_THROW(swap(t1.root()["1"], t1.root()), st_tree::exception); 642 | } 643 | 644 | BOOST_AUTO_TEST_CASE(graft) { 645 | tree > t1; 646 | tree > t2; 647 | 648 | // start with the node/tree overloadings 649 | // graft node -> tree 650 | t1.insert(2); 651 | t2.insert(1); 652 | t2.graft(t1.root()); 653 | CHECK_TREE(t1, data(), ""); 654 | CHECK_TREE(t2, data(), "2"); 655 | CHECK_TREE(t2, depth(), "1"); 656 | CHECK_TREE(t2, ply(), "0"); 657 | CHECK_TREE(t2, subtree_size(), "1"); 658 | 659 | t1.insert(2); 660 | t1.root().insert("0",3); 661 | t1.root().insert("1",5); 662 | t2.graft(t1.root()); 663 | CHECK_TREE(t1, data(), ""); 664 | CHECK_TREE(t2, data(), "2 3 5"); 665 | CHECK_TREE(t2, depth(), "2 1 1"); 666 | CHECK_TREE(t2, ply(), "0 1 1"); 667 | CHECK_TREE(t2, subtree_size(), "3 1 1"); 668 | 669 | t1.insert(2); 670 | t1.root().insert("0",3); 671 | t1.root().insert("1",5); 672 | t2.graft(t1.root()["1"]); 673 | CHECK_TREE(t1, data(), "2 3"); 674 | CHECK_TREE(t1, depth(), "2 1"); 675 | CHECK_TREE(t1, ply(), "0 1"); 676 | CHECK_TREE(t1, subtree_size(), "2 1"); 677 | CHECK_TREE(t2, data(), "5"); 678 | CHECK_TREE(t2, depth(), "1"); 679 | CHECK_TREE(t2, ply(), "0"); 680 | CHECK_TREE(t2, subtree_size(), "1"); 681 | 682 | // graft tree -> tree (empty) 683 | t1.clear(); 684 | t2.graft(t1); 685 | CHECK_TREE(t1, data(), ""); 686 | CHECK_TREE(t2, data(), ""); 687 | 688 | // graft tree -> tree (non-empty) 689 | t1.insert(2); 690 | t2.graft(t1); 691 | CHECK_TREE(t1, data(), ""); 692 | CHECK_TREE(t2, data(), "2"); 693 | 694 | // graft tree -> node (empty) 695 | t2.root().graft("0",t1); 696 | CHECK_TREE(t1, data(), ""); 697 | CHECK_TREE(t2, data(), "2"); 698 | 699 | // graft tree -> node (non-empty) 700 | t1.insert(2); 701 | t2.insert(1); 702 | t2.root().graft("0",t1); 703 | CHECK_TREE(t1, data(), ""); 704 | CHECK_TREE(t2, data(), "1 2"); 705 | 706 | // node --> node 707 | t1.insert(2); 708 | t2.insert(1); 709 | t2.root().graft("0",t1.root()); 710 | CHECK_TREE(t1, data(), ""); 711 | CHECK_TREE(t2, data(), "1 2"); 712 | CHECK_TREE(t2, depth(), "2 1"); 713 | CHECK_TREE(t2, ply(), "0 1"); 714 | CHECK_TREE(t2, subtree_size(), "2 1"); 715 | 716 | t1.insert(2); 717 | t1.root().insert("0",3); 718 | t1.root().insert("1",5); 719 | t2.insert(1); 720 | t2.root().graft("0",t1.root()); 721 | CHECK_TREE(t1, data(), ""); 722 | CHECK_TREE(t2, data(), "1 2 3 5"); 723 | CHECK_TREE(t2, depth(), "3 2 1 1"); 724 | CHECK_TREE(t2, ply(), "0 1 2 2"); 725 | CHECK_TREE(t2, subtree_size(), "4 3 1 1"); 726 | 727 | t1.insert(2); 728 | t1.root().insert("0",3); 729 | t1.root().insert("1",5); 730 | t2.insert(1); 731 | t2.root().graft("0",t1.root()["1"]); 732 | CHECK_TREE(t1, data(), "2 3"); 733 | CHECK_TREE(t1, depth(), "2 1"); 734 | CHECK_TREE(t1, ply(), "0 1"); 735 | CHECK_TREE(t1, subtree_size(), "2 1"); 736 | CHECK_TREE(t2, data(), "1 5"); 737 | CHECK_TREE(t2, depth(), "2 1"); 738 | CHECK_TREE(t2, ply(), "0 1"); 739 | CHECK_TREE(t2, subtree_size(), "2 1"); 740 | } 741 | 742 | 743 | BOOST_AUTO_TEST_CASE(insert_node) { 744 | tree > t1; 745 | tree > t2; 746 | 747 | // start with the node/tree overloadings 748 | // insert node -> tree 749 | t1.insert(2); 750 | t2.insert(1); 751 | t2.insert(t1.root()); 752 | CHECK_TREE(t1, data(), "2"); 753 | CHECK_TREE(t2, data(), "2"); 754 | CHECK_TREE(t2, depth(), "1"); 755 | CHECK_TREE(t2, ply(), "0"); 756 | CHECK_TREE(t2, subtree_size(), "1"); 757 | 758 | t1.insert(2); 759 | t1.root().insert("0",3); 760 | t1.root().insert("1",5); 761 | t2.insert(t1.root()); 762 | CHECK_TREE(t1, data(), "2 3 5"); 763 | CHECK_TREE(t2, data(), "2 3 5"); 764 | CHECK_TREE(t2, depth(), "2 1 1"); 765 | CHECK_TREE(t2, ply(), "0 1 1"); 766 | CHECK_TREE(t2, subtree_size(), "3 1 1"); 767 | 768 | t1.insert(2); 769 | t1.root().insert("0",3); 770 | t1.root().insert("1",5); 771 | t2.insert(t1.root()["1"]); 772 | CHECK_TREE(t1, data(), "2 3 5"); 773 | CHECK_TREE(t1, depth(), "2 1 1"); 774 | CHECK_TREE(t1, ply(), "0 1 1"); 775 | CHECK_TREE(t1, subtree_size(), "3 1 1"); 776 | CHECK_TREE(t2, data(), "5"); 777 | CHECK_TREE(t2, depth(), "1"); 778 | CHECK_TREE(t2, ply(), "0"); 779 | CHECK_TREE(t2, subtree_size(), "1"); 780 | 781 | // insert tree -> tree (empty) 782 | t1.clear(); 783 | t2.insert(t1); 784 | CHECK_TREE(t1, data(), ""); 785 | CHECK_TREE(t2, data(), ""); 786 | 787 | // insert tree -> tree (non-empty) 788 | t1.insert(2); 789 | t2.insert(t1); 790 | CHECK_TREE(t1, data(), "2"); 791 | CHECK_TREE(t2, data(), "2"); 792 | 793 | // insert tree -> node (empty) 794 | t1.clear(); 795 | t2.root().insert("0",t1); 796 | CHECK_TREE(t1, data(), ""); 797 | CHECK_TREE(t2, data(), "2"); 798 | 799 | // insert tree -> node (non-empty) 800 | t1.insert(2); 801 | t2.insert(1); 802 | t2.root().insert("0",t1); 803 | CHECK_TREE(t1, data(), "2"); 804 | CHECK_TREE(t2, data(), "1 2"); 805 | 806 | // node --> node 807 | t1.insert(2); 808 | t2.insert(1); 809 | t2.root().insert("0",t1.root()); 810 | CHECK_TREE(t1, data(), "2"); 811 | CHECK_TREE(t2, data(), "1 2"); 812 | CHECK_TREE(t2, depth(), "2 1"); 813 | CHECK_TREE(t2, ply(), "0 1"); 814 | CHECK_TREE(t2, subtree_size(), "2 1"); 815 | 816 | t1.insert(2); 817 | t1.root().insert("0",3); 818 | t1.root().insert("1",5); 819 | t2.insert(1); 820 | t2.root().insert("0",t1.root()); 821 | CHECK_TREE(t1, data(), "2 3 5"); 822 | CHECK_TREE(t2, data(), "1 2 3 5"); 823 | CHECK_TREE(t2, depth(), "3 2 1 1"); 824 | CHECK_TREE(t2, ply(), "0 1 2 2"); 825 | CHECK_TREE(t2, subtree_size(), "4 3 1 1"); 826 | 827 | t1.insert(2); 828 | t1.root().insert("0",3); 829 | t1.root().insert("1",5); 830 | t2.insert(1); 831 | t2.root().insert("0",t1.root()["1"]); 832 | CHECK_TREE(t1, data(), "2 3 5"); 833 | CHECK_TREE(t1, depth(), "2 1 1"); 834 | CHECK_TREE(t1, ply(), "0 1 1"); 835 | CHECK_TREE(t1, subtree_size(), "3 1 1"); 836 | CHECK_TREE(t2, data(), "1 5"); 837 | CHECK_TREE(t2, depth(), "2 1"); 838 | CHECK_TREE(t2, ply(), "0 1"); 839 | CHECK_TREE(t2, subtree_size(), "2 1"); 840 | } 841 | 842 | 843 | BOOST_AUTO_TEST_CASE(node_op_equality) { 844 | tree > t1; 845 | tree > t2; 846 | 847 | t1.insert(2); 848 | t1.root().insert("0",3); 849 | t1.root().insert("1",5); 850 | t1.root()["0"].insert("0",7); 851 | t1.root()["1"].insert("0",13); 852 | t1.root()["0"].insert("1",11); 853 | t1.root()["1"].insert("1",17); 854 | 855 | t2.insert(2); 856 | t2.root().insert("0",3); 857 | t2.root().insert("1",5); 858 | t2.root()["0"].insert("0",7); 859 | t2.root()["1"].insert("0",13); 860 | t2.root()["0"].insert("1",11); 861 | t2.root()["1"].insert("1",17); 862 | 863 | BOOST_CHECK_EQUAL(t1.root() == t1.root(), true); 864 | BOOST_CHECK_EQUAL(t1.root()["0"] == t1.root()["0"], true); 865 | BOOST_CHECK_EQUAL(t1.root()["0"]["0"] == t1.root()["0"]["0"], true); 866 | 867 | BOOST_CHECK_EQUAL(t1.root() == t2.root(), true); 868 | BOOST_CHECK_EQUAL(t1.root()["0"] == t2.root()["0"], true); 869 | BOOST_CHECK_EQUAL(t1.root()["0"]["0"] == t2.root()["0"]["0"], true); 870 | 871 | BOOST_CHECK_EQUAL(t1.root()["0"] == t2.root()["1"], false); 872 | BOOST_CHECK_EQUAL(t1.root()["0"]["0"] == t2.root()["0"]["1"], false); 873 | } 874 | 875 | 876 | BOOST_AUTO_TEST_CASE(node_op_lessthan) { 877 | tree > t1; 878 | tree > t2; 879 | 880 | t1.insert(2); 881 | t2.insert(2); 882 | 883 | BOOST_CHECK_EQUAL(t1.root() < t2.root(), false); 884 | 885 | t2.root().data() = 3; 886 | BOOST_CHECK_EQUAL(t1.root() < t2.root(), true); 887 | 888 | t2.root().data() = 2; 889 | t1.root().insert("0",3); 890 | t1.root().insert("1",5); 891 | t2.root().insert("0",3); 892 | t2.root().insert("1",5); 893 | 894 | BOOST_CHECK_EQUAL(t1.root() < t2.root(), false); 895 | 896 | t2.root()["1"].data() = 7; 897 | BOOST_CHECK_EQUAL(t1.root() < t2.root(), true); 898 | } 899 | 900 | 901 | BOOST_AUTO_TEST_CASE(node_derived_comp_ops) { 902 | tree > t1; 903 | tree > t2; 904 | 905 | t1.insert(2); 906 | t2.insert(2); 907 | BOOST_CHECK_EQUAL(t1.root() != t2.root(), false); 908 | BOOST_CHECK_EQUAL(t2.root() != t1.root(), false); 909 | BOOST_CHECK_EQUAL(t1.root() > t2.root(), false); 910 | BOOST_CHECK_EQUAL(t2.root() > t1.root(), false); 911 | BOOST_CHECK_EQUAL(t1.root() <= t2.root(), true); 912 | BOOST_CHECK_EQUAL(t2.root() <= t1.root(), true); 913 | BOOST_CHECK_EQUAL(t1.root() >= t2.root(), true); 914 | BOOST_CHECK_EQUAL(t2.root() >= t1.root(), true); 915 | 916 | t2.root().data() = 3; 917 | BOOST_CHECK_EQUAL(t1.root() != t2.root(), true); 918 | BOOST_CHECK_EQUAL(t2.root() != t1.root(), true); 919 | BOOST_CHECK_EQUAL(t1.root() > t2.root(), false); 920 | BOOST_CHECK_EQUAL(t2.root() > t1.root(), true); 921 | BOOST_CHECK_EQUAL(t1.root() <= t2.root(), true); 922 | BOOST_CHECK_EQUAL(t2.root() <= t1.root(), false); 923 | BOOST_CHECK_EQUAL(t1.root() >= t2.root(), false); 924 | BOOST_CHECK_EQUAL(t2.root() >= t1.root(), true); 925 | } 926 | 927 | 928 | BOOST_AUTO_TEST_CASE(tree_op_equality) { 929 | tree > t1; 930 | tree > t2; 931 | 932 | BOOST_CHECK_EQUAL(t1 == t2, true); 933 | 934 | t2.insert(2); 935 | BOOST_CHECK_EQUAL(t1 == t2, false); 936 | 937 | t1.insert(2); 938 | BOOST_CHECK_EQUAL(t1 == t2, true); 939 | 940 | t2.root().data() = 3; 941 | BOOST_CHECK_EQUAL(t1 == t2, false); 942 | } 943 | 944 | 945 | BOOST_AUTO_TEST_CASE(tree_op_lessthan) { 946 | tree > t1; 947 | tree > t2; 948 | 949 | BOOST_CHECK_EQUAL(t1 < t2, false); 950 | 951 | t2.insert(2); 952 | BOOST_CHECK_EQUAL(t1 < t2, true); 953 | BOOST_CHECK_EQUAL(t2 < t1, false); 954 | 955 | t1.insert(2); 956 | BOOST_CHECK_EQUAL(t1 < t2, false); 957 | 958 | t2.root().data() = 3; 959 | BOOST_CHECK_EQUAL(t1 < t2, true); 960 | BOOST_CHECK_EQUAL(t2 < t1, false); 961 | 962 | BOOST_CHECK_EQUAL(t1 < t1, false); 963 | } 964 | 965 | 966 | BOOST_AUTO_TEST_CASE(tree_derived_comp_ops) { 967 | tree > t1; 968 | tree > t2; 969 | 970 | t1.insert(2); 971 | t2.insert(2); 972 | BOOST_CHECK_EQUAL(t1 != t2, false); 973 | BOOST_CHECK_EQUAL(t2 != t1, false); 974 | BOOST_CHECK_EQUAL(t1 > t2, false); 975 | BOOST_CHECK_EQUAL(t2 > t1, false); 976 | BOOST_CHECK_EQUAL(t1 <= t2, true); 977 | BOOST_CHECK_EQUAL(t2 <= t1, true); 978 | BOOST_CHECK_EQUAL(t1 >= t2, true); 979 | BOOST_CHECK_EQUAL(t2 >= t1, true); 980 | 981 | t2.root().data() = 3; 982 | BOOST_CHECK_EQUAL(t1 != t2, true); 983 | BOOST_CHECK_EQUAL(t2 != t1, true); 984 | BOOST_CHECK_EQUAL(t1 > t2, false); 985 | BOOST_CHECK_EQUAL(t2 > t1, true); 986 | BOOST_CHECK_EQUAL(t1 <= t2, true); 987 | BOOST_CHECK_EQUAL(t2 <= t1, false); 988 | BOOST_CHECK_EQUAL(t1 >= t2, false); 989 | BOOST_CHECK_EQUAL(t2 >= t1, true); 990 | } 991 | 992 | 993 | BOOST_AUTO_TEST_CASE(tree_op_equal_lhs_n_rhs_e) { 994 | tree > t1; 995 | tree > t2; 996 | 997 | t1.insert(2); 998 | t1.root().insert("0",3); 999 | 1000 | t1 = t2; 1001 | 1002 | BOOST_CHECK_EQUAL(t1.empty(), true); 1003 | BOOST_CHECK_EQUAL(t2.empty(), true); 1004 | 1005 | CHECK_TREE(t1, data(), ""); 1006 | } 1007 | 1008 | BOOST_AUTO_TEST_CASE(tree_op_equal_lhs_e_rhs_n) { 1009 | tree > t1; 1010 | tree > t2; 1011 | 1012 | t2.insert(2); 1013 | t2.root().insert("0",3); 1014 | 1015 | t1 = t2; 1016 | 1017 | BOOST_CHECK_EQUAL(t1.empty(), false); 1018 | BOOST_CHECK_EQUAL(t2.empty(), false); 1019 | 1020 | CHECK_TREE(t1, data(), "2 3"); 1021 | CHECK_TREE(t1, ply(), "0 1"); 1022 | CHECK_TREE(t1, subtree_size(), "2 1"); 1023 | } 1024 | 1025 | BOOST_AUTO_TEST_CASE(tree_op_equal_lhs_n_rhs_n) { 1026 | tree > t1; 1027 | tree > t2; 1028 | 1029 | t1.insert(31); 1030 | t1.root().insert("0",41); 1031 | 1032 | t2.insert(2); 1033 | t2.root().insert("0",3); 1034 | 1035 | t1 = t2; 1036 | 1037 | BOOST_CHECK_EQUAL(t1.empty(), false); 1038 | BOOST_CHECK_EQUAL(t2.empty(), false); 1039 | 1040 | CHECK_TREE(t1, data(), "2 3"); 1041 | CHECK_TREE(t1, ply(), "0 1"); 1042 | CHECK_TREE(t1, subtree_size(), "2 1"); 1043 | } 1044 | 1045 | 1046 | BOOST_AUTO_TEST_CASE(tree_swap) { 1047 | tree > t1; 1048 | tree > t2; 1049 | 1050 | t1.insert(2); 1051 | t2.insert(3); 1052 | 1053 | // method version 1054 | t1.swap(t2); 1055 | 1056 | CHECK_TREE(t1, data(), "3"); 1057 | CHECK_TREE(t2, data(), "2"); 1058 | 1059 | // function version 1060 | swap(t1, t2); 1061 | 1062 | CHECK_TREE(t1, data(), "2"); 1063 | CHECK_TREE(t2, data(), "3"); 1064 | } 1065 | 1066 | BOOST_AUTO_TEST_CASE(count) { 1067 | tree > t1; 1068 | t1.insert(2); 1069 | t1.root().insert("5",5); 1070 | t1.root().insert("3",3); 1071 | t1.root().insert("5",5); 1072 | CHECK_TREE(t1, data(), "2 3 5"); 1073 | BOOST_CHECK_EQUAL(t1.root().count("3"), (unsigned)1); 1074 | BOOST_CHECK_EQUAL(t1.root().count("5"), (unsigned)1); 1075 | BOOST_CHECK_EQUAL(t1.root().count("7"), (unsigned)0); 1076 | } 1077 | 1078 | BOOST_AUTO_TEST_CASE(find) { 1079 | tree > t1; 1080 | typedef tree >::node_type::iterator iterator; 1081 | typedef tree >::node_type::const_iterator const_iterator; 1082 | t1.insert(2); 1083 | t1.root().insert("5",5); 1084 | t1.root().insert("3",3); 1085 | t1.root().insert("5",5); 1086 | CHECK_TREE(t1, data(), "2 3 5"); 1087 | 1088 | iterator j1 = t1.root().find("3"); 1089 | BOOST_CHECK(j1 != t1.root().end() && j1->data() == 3); 1090 | j1 = t1.root().find("5"); 1091 | BOOST_CHECK(j1 != t1.root().end() && j1->data() == 5); 1092 | j1 = t1.root().find("7"); 1093 | BOOST_CHECK(j1 == t1.root().end()); 1094 | 1095 | tree > const& tc = t1; 1096 | const_iterator jc = tc.root().find("3"); 1097 | BOOST_CHECK(jc != tc.root().end() && jc->data() == 3); 1098 | jc = tc.root().find("5"); 1099 | BOOST_CHECK(jc != tc.root().end() && jc->data() == 5); 1100 | jc = tc.root().find("7"); 1101 | BOOST_CHECK(jc == tc.root().end()); 1102 | } 1103 | 1104 | BOOST_AUTO_TEST_CASE(lower_upper_equal) { 1105 | tree > t1; 1106 | typedef tree >::node_type::iterator iterator; 1107 | typedef tree >::node_type::const_iterator const_iterator; 1108 | 1109 | t1.insert(2); 1110 | t1.root().insert("5", 5); 1111 | t1.root().insert("3", 3); 1112 | t1.root().insert("7", 7); 1113 | 1114 | CHECK_TREE(t1, data(), "2 3 5 7"); 1115 | 1116 | iterator l1 = t1.root().lower_bound("5"); 1117 | iterator u1 = t1.root().upper_bound("5"); 1118 | pair r1 = t1.root().equal_range("5"); 1119 | BOOST_CHECK_EQUAL(l1->data(), 5); 1120 | BOOST_CHECK_EQUAL(u1->data(), 7); 1121 | BOOST_CHECK(r1.first == l1); 1122 | BOOST_CHECK(r1.second == u1); 1123 | ++l1; 1124 | BOOST_CHECK_EQUAL(l1->data(), 7); 1125 | 1126 | const tree >& tc = t1; 1127 | const_iterator lc = tc.root().lower_bound("5"); 1128 | const_iterator uc = tc.root().upper_bound("5"); 1129 | pair rc = tc.root().equal_range("5"); 1130 | BOOST_CHECK_EQUAL(lc->data(), 5); 1131 | BOOST_CHECK_EQUAL(uc->data(), 7); 1132 | BOOST_CHECK(rc.first == lc); 1133 | BOOST_CHECK(rc.second == uc); 1134 | ++lc; 1135 | BOOST_CHECK_EQUAL(lc->data(), 7); 1136 | } 1137 | 1138 | BOOST_AUTO_TEST_CASE(erase_key) { 1139 | tree > t1; 1140 | 1141 | t1.insert(2); 1142 | t1.root().insert("3",3); 1143 | t1.root().insert("5",5); 1144 | t1.root().insert("7",7); 1145 | 1146 | CHECK_TREE(t1, data(), "2 3 5 7"); 1147 | 1148 | unsigned c = t1.root().erase("11"); 1149 | BOOST_CHECK_EQUAL(c, unsigned(0)); 1150 | CHECK_TREE(t1, data(), "2 3 5 7"); 1151 | 1152 | c = t1.root().erase("5"); 1153 | BOOST_CHECK_EQUAL(c, unsigned(1)); 1154 | CHECK_TREE(t1, data(), "2 3 7"); 1155 | } 1156 | 1157 | BOOST_AUTO_TEST_SUITE_END() 1158 | -------------------------------------------------------------------------------- /tests/ut_ordered.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "st_tree.h" 4 | #include "ut_common.h" 5 | 6 | 7 | BOOST_AUTO_TEST_SUITE(ut_ordered) 8 | 9 | 10 | BOOST_AUTO_TEST_CASE(default_ctor) { 11 | tree > t1; 12 | BOOST_CHECK(t1.empty()); 13 | BOOST_CHECK_EQUAL(t1.size(), 0); 14 | BOOST_CHECK_EQUAL(t1.depth(), 0); 15 | BOOST_CHECK_THROW(t1.root(), st_tree::exception); 16 | } 17 | 18 | BOOST_AUTO_TEST_CASE(insert_root) { 19 | tree > t1; 20 | t1.insert(7); 21 | BOOST_CHECK_EQUAL(t1.empty(), false); 22 | BOOST_CHECK_EQUAL(t1.size(), 1); 23 | BOOST_CHECK_EQUAL(t1.depth(), 1); 24 | BOOST_CHECK_EQUAL(t1.root().is_root(), true); 25 | BOOST_CHECK_EQUAL(t1.root().data(), 7); 26 | BOOST_CHECK_THROW(t1.root().parent(), st_tree::exception); 27 | } 28 | 29 | 30 | BOOST_AUTO_TEST_CASE(insert_subnodes) { 31 | tree > t1; 32 | 33 | t1.insert(7); 34 | BOOST_CHECK_EQUAL(t1.empty(), false); 35 | BOOST_CHECK_EQUAL(t1.size(), 1); 36 | BOOST_CHECK_EQUAL(t1.depth(), 1); 37 | BOOST_CHECK_EQUAL(t1.root().size(), 0); 38 | 39 | t1.root().insert(8); 40 | BOOST_CHECK_EQUAL(t1.size(), 2); 41 | BOOST_CHECK_EQUAL(t1.depth(), 2); 42 | BOOST_CHECK_EQUAL(t1.empty(), false); 43 | BOOST_CHECK_EQUAL(t1.root().size(), 1); 44 | 45 | t1.root().insert(9); 46 | BOOST_CHECK_EQUAL(t1.size(), 3); 47 | BOOST_CHECK_EQUAL(t1.depth(), 2); 48 | BOOST_CHECK_EQUAL(t1.empty(), false); 49 | BOOST_CHECK_EQUAL(t1.root().size(), 2); 50 | 51 | CHECK_TREE(t1, data(), "7 8 9"); 52 | CHECK_TREE(t1, ply(), "0 1 1"); 53 | CHECK_TREE(t1, depth(), "2 1 1"); 54 | CHECK_TREE(t1, subtree_size(), "3 1 1"); 55 | } 56 | 57 | BOOST_AUTO_TEST_CASE(emplace_subnodes){ 58 | struct str1 { 59 | int i1; 60 | std::string s1; 61 | str1() { 62 | i1 = 0; 63 | s1 = ""; 64 | } 65 | str1(int i, const std::string s) { 66 | i1 = i; 67 | s1 = s; 68 | } 69 | bool operator<(const str1& b) const { 70 | return i1 < b.i1; 71 | } 72 | }; 73 | 74 | tree> t1; 75 | 76 | t1.emplace(7, "7"); 77 | BOOST_CHECK_EQUAL(t1.empty(), false); 78 | BOOST_CHECK_EQUAL(t1.size(), 1); 79 | BOOST_CHECK_EQUAL(t1.depth(), 1); 80 | BOOST_CHECK_EQUAL(t1.root().size(), 0); 81 | 82 | t1.root().emplace_insert(9, "9"); 83 | BOOST_CHECK_EQUAL(t1.size(), 2); 84 | BOOST_CHECK_EQUAL(t1.depth(), 2); 85 | BOOST_CHECK_EQUAL(t1.empty(), false); 86 | BOOST_CHECK_EQUAL(t1.root().size(), 1); 87 | 88 | t1.root().emplace_insert(8, "8"); 89 | BOOST_CHECK_EQUAL(t1.size(), 3); 90 | BOOST_CHECK_EQUAL(t1.depth(), 2); 91 | BOOST_CHECK_EQUAL(t1.empty(), false); 92 | BOOST_CHECK_EQUAL(t1.root().size(), 2); 93 | 94 | CHECK_TREE(t1, ply(), "0 1 1"); 95 | CHECK_TREE(t1, depth(), "2 1 1"); 96 | CHECK_TREE(t1, subtree_size(), "3 1 1"); 97 | } 98 | 99 | 100 | BOOST_AUTO_TEST_CASE(clear) { 101 | tree > t1; 102 | 103 | t1.insert(7); 104 | t1.root().insert(8); 105 | t1.root().insert(9); 106 | BOOST_CHECK_EQUAL(t1.size(), 3); 107 | BOOST_CHECK_EQUAL(t1.depth(), 2); 108 | BOOST_CHECK_EQUAL(t1.empty(), false); 109 | BOOST_CHECK_EQUAL(t1.root().size(), 2); 110 | 111 | t1.clear(); 112 | BOOST_CHECK_EQUAL(t1.size(), 0); 113 | BOOST_CHECK_EQUAL(t1.depth(), 0); 114 | BOOST_CHECK_EQUAL(t1.empty(), true); 115 | BOOST_CHECK_THROW(t1.root(), st_tree::exception); 116 | } 117 | 118 | 119 | BOOST_AUTO_TEST_CASE(reinsert) { 120 | tree > t1; 121 | 122 | t1.insert(7); 123 | t1.root().insert(8); 124 | t1.root().insert(9); 125 | BOOST_CHECK_EQUAL(t1.size(), 3); 126 | BOOST_CHECK_EQUAL(t1.depth(), 2); 127 | BOOST_CHECK_EQUAL(t1.empty(), false); 128 | BOOST_CHECK_EQUAL(t1.root().size(), 2); 129 | 130 | t1.insert(3); 131 | BOOST_CHECK_EQUAL(t1.size(), 1); 132 | BOOST_CHECK_EQUAL(t1.depth(), 1); 133 | BOOST_CHECK_EQUAL(t1.empty(), false); 134 | BOOST_CHECK_EQUAL(t1.root().size(), 0); 135 | BOOST_CHECK_EQUAL(t1.root().data(), 3); 136 | } 137 | 138 | 139 | BOOST_AUTO_TEST_CASE(erase) { 140 | tree > t1; 141 | 142 | t1.insert(7); 143 | t1.root().insert(8); 144 | 145 | t1.root().erase(t1.root().begin()); 146 | BOOST_CHECK_EQUAL(t1.size(), 1); 147 | BOOST_CHECK_EQUAL(t1.depth(), 1); 148 | BOOST_CHECK_EQUAL(t1.empty(), false); 149 | BOOST_CHECK_EQUAL(t1.root().size(), 0); 150 | BOOST_CHECK_EQUAL(t1.root().data(), 7); 151 | } 152 | 153 | 154 | BOOST_AUTO_TEST_CASE(erase_noarg) { 155 | tree > t1; 156 | typedef tree >::node_type node_type; 157 | 158 | t1.insert(2); 159 | node_type& n3 = *t1.root().insert(3); 160 | node_type& n5 = *t1.root().insert(5); 161 | 162 | n3.insert(7); 163 | node_type& n11 = *n3.insert(11); 164 | n5.insert(13); 165 | n5.insert(17); 166 | 167 | CHECK_TREE(t1, data(), "2 3 5 7 11 13 17"); 168 | 169 | n5.erase(); 170 | CHECK_TREE(t1, data(), "2 3 7 11"); 171 | 172 | n11.erase(); 173 | CHECK_TREE(t1, data(), "2 3 7"); 174 | 175 | t1.root().erase(); 176 | BOOST_CHECK_EQUAL(t1.empty(), true); 177 | CHECK_TREE(t1, data(), ""); 178 | } 179 | 180 | 181 | 182 | 183 | BOOST_AUTO_TEST_CASE(bf_iterator_empty) { 184 | tree > t1; 185 | BOOST_CHECK_EQUAL(t1.bf_begin() == t1.bf_end(), true); 186 | BOOST_CHECK_EQUAL(t1.bf_begin() != t1.bf_end(), false); 187 | } 188 | 189 | 190 | BOOST_AUTO_TEST_CASE(bf_iterator) { 191 | tree > t1; 192 | typedef tree >::node_type node_type; 193 | CHECK_TREE(t1, data(), ""); 194 | 195 | t1.insert(2); 196 | CHECK_TREE(t1, data(), "2"); 197 | 198 | node_type& n3 = *t1.root().insert(3); 199 | node_type& n5 = *t1.root().insert(5); 200 | CHECK_TREE(t1, data(), "2 3 5"); 201 | 202 | n3.insert(7); 203 | n5.insert(13); 204 | n3.insert(11); 205 | n5.insert(17); 206 | CHECK_TREE(t1, data(), "2 3 5 7 11 13 17"); 207 | CHECK_TREE(t1.root(), data(), "2 3 5 7 11 13 17"); 208 | } 209 | 210 | 211 | BOOST_AUTO_TEST_CASE(df_post_iterator_empty) { 212 | tree > t1; 213 | BOOST_CHECK_EQUAL(t1.df_post_begin() == t1.df_post_end(), true); 214 | BOOST_CHECK_EQUAL(t1.df_post_begin() != t1.df_post_end(), false); 215 | } 216 | 217 | 218 | BOOST_AUTO_TEST_CASE(df_post_iterator) { 219 | tree > t1; 220 | typedef tree >::node_type node_type; 221 | 222 | CHECK_TREE_DF_POST(t1, data(), ""); 223 | 224 | t1.insert(2); 225 | CHECK_TREE_DF_POST(t1, data(), "2"); 226 | 227 | node_type& n3 = *t1.root().insert(3); 228 | node_type& n5 = *t1.root().insert(5); 229 | CHECK_TREE_DF_POST(t1, data(), "3 5 2"); 230 | 231 | n3.insert(7); 232 | n5.insert(13); 233 | n3.insert(11); 234 | n5.insert(17); 235 | CHECK_TREE_DF_POST(t1, data(), "7 11 3 13 17 5 2"); 236 | CHECK_TREE_DF_POST(t1.root(), data(), "7 11 3 13 17 5 2"); 237 | } 238 | 239 | 240 | BOOST_AUTO_TEST_CASE(df_pre_iterator_empty) { 241 | tree > t1; 242 | BOOST_CHECK_EQUAL(t1.df_pre_begin() == t1.df_pre_end(), true); 243 | BOOST_CHECK_EQUAL(t1.df_pre_begin() != t1.df_pre_end(), false); 244 | } 245 | 246 | 247 | BOOST_AUTO_TEST_CASE(df_pre_iterator) { 248 | tree > t1; 249 | typedef tree >::node_type node_type; 250 | 251 | CHECK_TREE_DF_PRE(t1, data(), ""); 252 | 253 | t1.insert(2); 254 | CHECK_TREE_DF_PRE(t1, data(), "2"); 255 | 256 | node_type& n3 = *t1.root().insert(3); 257 | node_type& n5 = *t1.root().insert(5); 258 | CHECK_TREE_DF_PRE(t1, data(), "2 3 5"); 259 | 260 | n3.insert(7); 261 | n5.insert(13); 262 | n3.insert(11); 263 | n5.insert(17); 264 | CHECK_TREE_DF_PRE(t1, data(), "2 3 7 11 5 13 17"); 265 | CHECK_TREE_DF_PRE(t1.root(), data(), "2 3 7 11 5 13 17"); 266 | } 267 | 268 | 269 | BOOST_AUTO_TEST_CASE(node_ply) { 270 | tree > t1; 271 | typedef tree >::node_type node_type; 272 | 273 | t1.insert(2); 274 | CHECK_TREE(t1, data(), "2"); 275 | CHECK_TREE(t1, ply(), "0"); 276 | 277 | node_type& n3 = *t1.root().insert(3); 278 | node_type& n5 = *t1.root().insert(5); 279 | CHECK_TREE(t1, data(), "2 3 5"); 280 | CHECK_TREE(t1, ply(), "0 1 1"); 281 | 282 | n3.insert(7); 283 | n3.insert(11); 284 | n5.insert(13); 285 | n5.insert(17); 286 | CHECK_TREE(t1, data(), "2 3 5 7 11 13 17"); 287 | CHECK_TREE(t1, ply(), "0 1 1 2 2 2 2"); 288 | 289 | t1.root().insert(77); 290 | CHECK_TREE(t1, data(), "2 3 5 77 7 11 13 17"); 291 | CHECK_TREE(t1, ply(), "0 1 1 1 2 2 2 2"); 292 | 293 | t1.root().erase(t1.root().begin()); 294 | CHECK_TREE(t1, data(), "2 5 77 13 17"); 295 | CHECK_TREE(t1, ply(), "0 1 1 2 2"); 296 | 297 | t1.root().erase(t1.root().begin()); 298 | CHECK_TREE(t1, data(), "2 77"); 299 | CHECK_TREE(t1, ply(), "0 1"); 300 | 301 | t1.root().erase(t1.root().begin()); 302 | CHECK_TREE(t1, data(), "2"); 303 | CHECK_TREE(t1, ply(), "0"); 304 | } 305 | 306 | 307 | BOOST_AUTO_TEST_CASE(node_depth) { 308 | tree > t1; 309 | typedef tree >::node_type node_type; 310 | 311 | t1.insert(2); 312 | CHECK_TREE(t1, data(), "2"); 313 | CHECK_TREE(t1, depth(), "1"); 314 | CHECK_TREE(t1, ply(), "0"); 315 | 316 | node_type& n3 = *t1.root().insert(3); 317 | node_type& n5 = *t1.root().insert(5); 318 | CHECK_TREE(t1, data(), "2 3 5"); 319 | CHECK_TREE(t1, depth(), "2 1 1"); 320 | CHECK_TREE(t1, ply(), "0 1 1"); 321 | 322 | n3.insert(7); 323 | n3.insert(11); 324 | n5.insert(13); 325 | n5.insert(17); 326 | CHECK_TREE(t1, data(), "2 3 5 7 11 13 17"); 327 | CHECK_TREE(t1, depth(), "3 2 2 1 1 1 1"); 328 | CHECK_TREE(t1, ply(), "0 1 1 2 2 2 2"); 329 | 330 | t1.root().insert(77); 331 | CHECK_TREE(t1, data(), "2 3 5 77 7 11 13 17"); 332 | CHECK_TREE(t1, depth(), "3 2 2 1 1 1 1 1"); 333 | CHECK_TREE(t1, ply(), "0 1 1 1 2 2 2 2"); 334 | 335 | t1.root().erase(t1.root().begin()); 336 | CHECK_TREE(t1, data(), "2 5 77 13 17"); 337 | CHECK_TREE(t1, depth(), "3 2 1 1 1"); 338 | 339 | t1.root().erase(t1.root().begin()); 340 | CHECK_TREE(t1, data(), "2 77"); 341 | CHECK_TREE(t1, depth(), "2 1"); 342 | 343 | t1.root().erase(t1.root().begin()); 344 | CHECK_TREE(t1, data(), "2"); 345 | CHECK_TREE(t1, depth(), "1"); 346 | } 347 | 348 | 349 | BOOST_AUTO_TEST_CASE(node_subtree_size) { 350 | tree > t1; 351 | typedef tree >::node_type node_type; 352 | 353 | t1.insert(2); 354 | CHECK_TREE(t1, data(), "2"); 355 | CHECK_TREE(t1, subtree_size(), "1"); 356 | 357 | node_type& n3 = *t1.root().insert(3); 358 | node_type& n5 = *t1.root().insert(5); 359 | CHECK_TREE(t1, data(), "2 3 5"); 360 | CHECK_TREE(t1, subtree_size(), "3 1 1"); 361 | 362 | n3.insert(7); 363 | n3.insert(11); 364 | n5.insert(13); 365 | n5.insert(17); 366 | CHECK_TREE(t1, data(), "2 3 5 7 11 13 17"); 367 | CHECK_TREE(t1, subtree_size(), "7 3 3 1 1 1 1"); 368 | 369 | t1.root().insert(77); 370 | CHECK_TREE(t1, data(), "2 3 5 77 7 11 13 17"); 371 | CHECK_TREE(t1, subtree_size(), "8 3 3 1 1 1 1 1"); 372 | 373 | t1.root().erase(t1.root().begin()); 374 | CHECK_TREE(t1, data(), "2 5 77 13 17"); 375 | CHECK_TREE(t1, subtree_size(), "5 3 1 1 1"); 376 | 377 | t1.root().erase(t1.root().begin()); 378 | CHECK_TREE(t1, data(), "2 77"); 379 | CHECK_TREE(t1, subtree_size(), "2 1"); 380 | 381 | t1.root().erase(t1.root().begin()); 382 | CHECK_TREE(t1, data(), "2"); 383 | CHECK_TREE(t1, subtree_size(), "1"); 384 | } 385 | 386 | 387 | BOOST_AUTO_TEST_CASE(node_parent) { 388 | tree > t1; 389 | typedef tree >::node_type node_type; 390 | 391 | t1.insert(2); 392 | BOOST_CHECK_THROW(t1.root().parent(), st_tree::exception); 393 | 394 | node_type& n3 = *t1.root().insert(3); 395 | BOOST_CHECK_EQUAL(n3.parent().data(), 2); 396 | 397 | const node_type& n3c = n3; 398 | BOOST_CHECK_EQUAL(n3c.parent().data(), 2); 399 | } 400 | 401 | 402 | BOOST_AUTO_TEST_CASE(node_tree) { 403 | tree > t1; 404 | typedef tree >::node_type node_type; 405 | 406 | t1.insert(2); 407 | node_type& n3 = *t1.root().insert(3); 408 | node_type& n5 = *t1.root().insert(5); 409 | 410 | tree >& t2 = t1.root().tree(); 411 | BOOST_CHECK_EQUAL(t1 == t2, true); 412 | 413 | t2 = n3.tree(); 414 | BOOST_CHECK_EQUAL(t1 == t2, true); 415 | 416 | const node_type& n5c = n5; 417 | const tree >& t3 = t1; 418 | const tree >& t4 = n5c.tree(); 419 | BOOST_CHECK_EQUAL(t3 == t4, true); 420 | BOOST_CHECK_EQUAL(t1 == t4, true); 421 | } 422 | 423 | 424 | 425 | BOOST_AUTO_TEST_CASE(erase_node) { 426 | tree > t1; 427 | typedef tree >::node_type node_type; 428 | 429 | t1.insert(2); 430 | node_type& n3 = *t1.root().insert(3); 431 | node_type& n5 = *t1.root().insert(5); 432 | n3.insert(7); 433 | n5.insert(13); 434 | n3.insert(11); 435 | n5.insert(17); 436 | BOOST_CHECK_EQUAL(t1.size(), 7); 437 | BOOST_CHECK_EQUAL(t1.depth(), 3); 438 | 439 | t1.root().erase(t1.root().begin()); 440 | BOOST_CHECK_EQUAL(t1.size(), 4); 441 | BOOST_CHECK_EQUAL(t1.depth(), 3); 442 | 443 | CHECK_TREE(t1, data(), "2 5 13 17"); 444 | CHECK_TREE(t1, ply(), "0 1 2 2"); 445 | CHECK_TREE(t1, subtree_size(), "4 3 1 1"); 446 | } 447 | 448 | 449 | BOOST_AUTO_TEST_CASE(clear_node) { 450 | tree > t1; 451 | typedef tree >::node_type node_type; 452 | 453 | t1.insert(2); 454 | node_type& n3 = *t1.root().insert(3); 455 | node_type& n5 = *t1.root().insert(5); 456 | n3.insert(7); 457 | n5.insert(13); 458 | n3.insert(11); 459 | n5.insert(17); 460 | 461 | BOOST_CHECK_EQUAL(t1.size(), 7); 462 | BOOST_CHECK_EQUAL(t1.depth(), 3); 463 | 464 | t1.root().clear(); 465 | BOOST_CHECK_EQUAL(t1.size(), 1); 466 | BOOST_CHECK_EQUAL(t1.depth(), 1); 467 | 468 | CHECK_TREE(t1, data(), "2"); 469 | CHECK_TREE(t1, ply(), "0"); 470 | CHECK_TREE(t1, subtree_size(), "1"); 471 | } 472 | 473 | 474 | BOOST_AUTO_TEST_CASE(node_assign_op) { 475 | tree > t1; 476 | typedef tree >::node_type node_type; 477 | 478 | t1.insert(2); 479 | node_type& n3 = *t1.root().insert(3); 480 | 481 | tree > t2; 482 | t2.insert(5); 483 | node_type& n7 = *t2.root().insert(7); 484 | node_type& n11 = *t2.root().insert(11); 485 | 486 | BOOST_CHECK_EQUAL(t1.root().data(), 2); 487 | 488 | n3 = t2.root(); 489 | BOOST_CHECK_EQUAL(t1.size(), 4); 490 | BOOST_CHECK_EQUAL(t1.depth(), 3); 491 | 492 | CHECK_TREE(t1, data(), "2 5 7 11"); 493 | CHECK_TREE(t1, ply(), "0 1 2 2"); 494 | CHECK_TREE(t1, subtree_size(), "4 3 1 1"); 495 | 496 | CHECK_TREE(t2, data(), "5 7 11"); 497 | CHECK_TREE(t2, ply(), "0 1 1"); 498 | CHECK_TREE(t2, subtree_size(), "3 1 1"); 499 | } 500 | 501 | 502 | BOOST_AUTO_TEST_CASE(node_op_equal_root) { 503 | tree > t1; 504 | typedef tree >::node_type node_type; 505 | t1.insert(2); 506 | t1.root().insert(3); 507 | 508 | tree > t2; 509 | t2.insert(5); 510 | t2.root().insert(7); 511 | t2.root().insert(11); 512 | 513 | t1.root() = t2.root(); 514 | BOOST_CHECK_EQUAL(t1.size(), 3); 515 | BOOST_CHECK_EQUAL(t1.depth(), 2); 516 | 517 | CHECK_TREE(t1, data(), "5 7 11"); 518 | CHECK_TREE(t1, ply(), "0 1 1"); 519 | CHECK_TREE(t1, subtree_size(), "3 1 1"); 520 | 521 | CHECK_TREE(t2, data(), "5 7 11"); 522 | CHECK_TREE(t2, ply(), "0 1 1"); 523 | CHECK_TREE(t1, subtree_size(), "3 1 1"); 524 | } 525 | 526 | 527 | 528 | BOOST_AUTO_TEST_CASE(node_op_equal_subtree) { 529 | tree > t1; 530 | typedef tree >::node_type node_type; 531 | 532 | t1.insert(2); 533 | node_type& n3 = *t1.root().insert(3); 534 | node_type& n5 = *t1.root().insert(5); 535 | n3.insert(7); 536 | node_type& n11 = *n3.insert(11); 537 | n5.insert(13); 538 | n5.insert(17); 539 | 540 | BOOST_CHECK_THROW(n3 = t1.root(), st_tree::exception); 541 | 542 | t1.root() = n3; 543 | CHECK_TREE(t1, data(), "3 7 11"); 544 | BOOST_CHECK_EQUAL(t1.size(), 3); 545 | BOOST_CHECK_EQUAL(t1.depth(), 2); 546 | 547 | node_type::iterator j11(t1.root().begin()); 548 | ++j11; 549 | j11->insert(13); 550 | node_type& n17 = *(j11->insert(17)); 551 | *j11 = n17; 552 | CHECK_TREE(t1, data(), "3 7 17"); 553 | } 554 | 555 | 556 | BOOST_AUTO_TEST_CASE(node_swap) { 557 | tree > t1; 558 | tree > t2; 559 | typedef tree >::node_type node_type; 560 | 561 | BOOST_TEST_CHECKPOINT("here 1"); 562 | t1.insert(2); 563 | node_type& n2 = t1.root(); 564 | node_type& n3 = *t1.root().insert(3); 565 | node_type& n5 = *t1.root().insert(5); 566 | node_type& n7 = *n3.insert(7); 567 | n3.insert(11); 568 | 569 | BOOST_TEST_CHECKPOINT("here 2"); 570 | t2.insert(102); 571 | node_type& n102 = t2.root(); 572 | node_type& n103 = *t2.root().insert(103); 573 | node_type& n105 = *t2.root().insert(105); 574 | node_type& n107 = *n103.insert(107); 575 | n103.insert(111); 576 | 577 | CHECK_TREE(t1, data(), "2 3 5 7 11"); 578 | CHECK_TREE(t1, depth(), "3 2 1 1 1") 579 | CHECK_TREE(t2, data(), "102 103 105 107 111"); 580 | CHECK_TREE(t2, depth(), "3 2 1 1 1") 581 | 582 | // swap a leaf 583 | BOOST_TEST_CHECKPOINT("here 3"); 584 | swap(n7, n107); 585 | 586 | BOOST_TEST_CHECKPOINT("here 4"); 587 | BOOST_CHECK_EQUAL(t1.size(), 5); 588 | BOOST_CHECK_EQUAL(t1.depth(), 3); 589 | CHECK_TREE(t1, data(), "2 3 5 11 107"); 590 | CHECK_TREE(t1, ply(), "0 1 1 2 2"); 591 | CHECK_TREE(t1, depth(), "3 2 1 1 1"); 592 | CHECK_TREE(t1, subtree_size(), "5 3 1 1 1"); 593 | 594 | BOOST_TEST_CHECKPOINT("here 5"); 595 | BOOST_CHECK_EQUAL(t2.size(), 5); 596 | BOOST_CHECK_EQUAL(t2.depth(), 3); 597 | CHECK_TREE(t2, data(), "102 103 105 7 111"); 598 | CHECK_TREE(t2, ply(), "0 1 1 2 2"); 599 | CHECK_TREE(t2, depth(), "3 2 1 1 1"); 600 | CHECK_TREE(t2, subtree_size(), "5 3 1 1 1"); 601 | 602 | BOOST_TEST_CHECKPOINT("here 6"); 603 | 604 | // put it back 605 | swap(n7, n107); 606 | CHECK_TREE(t1, data(), "2 3 5 7 11"); 607 | CHECK_TREE(t1, depth(), "3 2 1 1 1") 608 | CHECK_TREE(t2, data(), "102 103 105 107 111"); 609 | CHECK_TREE(t2, depth(), "3 2 1 1 1") 610 | 611 | // swap an internal 612 | swap(n3, n103); 613 | BOOST_CHECK_EQUAL(t1.size(), 5); 614 | BOOST_CHECK_EQUAL(t1.depth(), 3); 615 | CHECK_TREE(t1, data(), "2 5 103 107 111"); 616 | CHECK_TREE(t1, ply(), "0 1 1 2 2"); 617 | CHECK_TREE(t1, depth(), "3 1 2 1 1"); 618 | CHECK_TREE(t1, subtree_size(), "5 1 3 1 1"); 619 | BOOST_CHECK_EQUAL(t2.size(), 5); 620 | BOOST_CHECK_EQUAL(t2.depth(), 3); 621 | CHECK_TREE(t2, data(), "102 3 105 7 11"); 622 | CHECK_TREE(t2, ply(), "0 1 1 2 2"); 623 | CHECK_TREE(t2, depth(), "3 2 1 1 1"); 624 | CHECK_TREE(t2, subtree_size(), "5 3 1 1 1"); 625 | 626 | // put it back 627 | swap(n3, n103); 628 | CHECK_TREE(t1, data(), "2 3 5 7 11"); 629 | CHECK_TREE(t1, depth(), "3 2 1 1 1") 630 | CHECK_TREE(t2, data(), "102 103 105 107 111"); 631 | CHECK_TREE(t2, depth(), "3 2 1 1 1") 632 | 633 | // swap the root 634 | swap(t1.root(), t2.root()); 635 | BOOST_CHECK_EQUAL(t1.size(), 5); 636 | BOOST_CHECK_EQUAL(t1.depth(), 3); 637 | CHECK_TREE(t1, data(), "102 103 105 107 111"); 638 | CHECK_TREE(t1, ply(), "0 1 1 2 2"); 639 | CHECK_TREE(t1, depth(), "3 2 1 1 1"); 640 | CHECK_TREE(t1, subtree_size(), "5 3 1 1 1"); 641 | BOOST_CHECK_EQUAL(t2.size(), 5); 642 | BOOST_CHECK_EQUAL(t2.depth(), 3); 643 | CHECK_TREE(t2, data(), "2 3 5 7 11"); 644 | CHECK_TREE(t2, ply(), "0 1 1 2 2"); 645 | CHECK_TREE(t2, depth(), "3 2 1 1 1"); 646 | CHECK_TREE(t2, subtree_size(), "5 3 1 1 1"); 647 | 648 | // put it back 649 | swap(t1.root(), t2.root()); 650 | CHECK_TREE(t1, data(), "2 3 5 7 11"); 651 | CHECK_TREE(t1, depth(), "3 2 1 1 1") 652 | CHECK_TREE(t2, data(), "102 103 105 107 111"); 653 | CHECK_TREE(t2, depth(), "3 2 1 1 1") 654 | 655 | // swap different plies 656 | swap(n2, n103); 657 | BOOST_CHECK_EQUAL(t1.size(), 3); 658 | BOOST_CHECK_EQUAL(t1.depth(), 2); 659 | CHECK_TREE(t1, data(), "103 107 111"); 660 | CHECK_TREE(t1, ply(), "0 1 1"); 661 | CHECK_TREE(t1, depth(), "2 1 1"); 662 | CHECK_TREE(t1, subtree_size(), "3 1 1"); 663 | BOOST_CHECK_EQUAL(t2.size(), 7); 664 | BOOST_CHECK_EQUAL(t2.depth(), 4); 665 | CHECK_TREE(t2, data(), "102 2 105 3 5 7 11"); 666 | CHECK_TREE(t2, ply(), "0 1 1 2 2 3 3"); 667 | CHECK_TREE(t2, depth(), "4 3 1 2 1 1 1"); 668 | CHECK_TREE(t2, subtree_size(), "7 5 1 3 1 1 1"); 669 | 670 | // put them back 671 | swap(n2, n103); 672 | CHECK_TREE(t1, data(), "2 3 5 7 11"); 673 | CHECK_TREE(t1, depth(), "3 2 1 1 1") 674 | CHECK_TREE(t2, data(), "102 103 105 107 111"); 675 | CHECK_TREE(t2, depth(), "3 2 1 1 1") 676 | 677 | // on same tree 678 | swap(n3, n5); 679 | BOOST_CHECK_EQUAL(t1.size(), 5); 680 | BOOST_CHECK_EQUAL(t1.depth(), 3); 681 | CHECK_TREE(t1, data(), "2 3 5 7 11"); 682 | CHECK_TREE(t1, ply(), "0 1 1 2 2"); 683 | CHECK_TREE(t1, depth(), "3 2 1 1 1"); 684 | CHECK_TREE(t1, subtree_size(), "5 3 1 1 1"); 685 | 686 | // put them back 687 | swap(n3, n5); 688 | CHECK_TREE(t1, data(), "2 3 5 7 11"); 689 | CHECK_TREE(t1, depth(), "3 2 1 1 1") 690 | CHECK_TREE(t2, data(), "102 103 105 107 111"); 691 | CHECK_TREE(t2, depth(), "3 2 1 1 1") 692 | 693 | // no-no 694 | BOOST_CHECK_THROW(swap(n2, n3), st_tree::exception); 695 | BOOST_CHECK_THROW(swap(n3, n2), st_tree::exception); 696 | } 697 | 698 | 699 | BOOST_AUTO_TEST_CASE(graft) { 700 | tree > t1; 701 | tree > t2; 702 | typedef tree >::node_type node_type; 703 | 704 | // start with the node/tree overloadings 705 | // graft node -> tree 706 | t1.insert(2); 707 | t2.insert(1); 708 | t2.graft(t1.root()); 709 | CHECK_TREE(t1, data(), ""); 710 | CHECK_TREE(t2, data(), "2"); 711 | CHECK_TREE(t2, depth(), "1"); 712 | CHECK_TREE(t2, ply(), "0"); 713 | CHECK_TREE(t2, subtree_size(), "1"); 714 | 715 | t1.insert(2); 716 | t1.root().insert(3); 717 | t1.root().insert(5); 718 | t2.graft(t1.root()); 719 | CHECK_TREE(t1, data(), ""); 720 | CHECK_TREE(t2, data(), "2 3 5"); 721 | CHECK_TREE(t2, depth(), "2 1 1"); 722 | CHECK_TREE(t2, ply(), "0 1 1"); 723 | CHECK_TREE(t2, subtree_size(), "3 1 1"); 724 | 725 | t1.insert(2); 726 | t1.root().insert(3); 727 | node_type& n5 = *t1.root().insert(5); 728 | t2.graft(n5); 729 | CHECK_TREE(t1, data(), "2 3"); 730 | CHECK_TREE(t1, depth(), "2 1"); 731 | CHECK_TREE(t1, ply(), "0 1"); 732 | CHECK_TREE(t1, subtree_size(), "2 1"); 733 | CHECK_TREE(t2, data(), "5"); 734 | CHECK_TREE(t2, depth(), "1"); 735 | CHECK_TREE(t2, ply(), "0"); 736 | CHECK_TREE(t2, subtree_size(), "1"); 737 | 738 | // graft tree -> tree (empty) 739 | t1.clear(); 740 | t2.graft(t1); 741 | CHECK_TREE(t1, data(), ""); 742 | CHECK_TREE(t2, data(), ""); 743 | 744 | // graft tree -> tree (non-empty) 745 | t1.insert(2); 746 | t2.graft(t1); 747 | CHECK_TREE(t1, data(), ""); 748 | CHECK_TREE(t2, data(), "2"); 749 | 750 | // graft tree -> node (empty) 751 | t2.root().graft(t1); 752 | CHECK_TREE(t1, data(), ""); 753 | CHECK_TREE(t2, data(), "2"); 754 | 755 | // graft tree -> node (non-empty) 756 | t1.insert(2); 757 | t2.insert(1); 758 | t2.root().graft(t1); 759 | CHECK_TREE(t1, data(), ""); 760 | CHECK_TREE(t2, data(), "1 2"); 761 | 762 | // node --> node 763 | t1.insert(2); 764 | t2.insert(1); 765 | t2.root().graft(t1.root()); 766 | CHECK_TREE(t1, data(), ""); 767 | CHECK_TREE(t2, data(), "1 2"); 768 | CHECK_TREE(t2, depth(), "2 1"); 769 | CHECK_TREE(t2, ply(), "0 1"); 770 | CHECK_TREE(t2, subtree_size(), "2 1"); 771 | 772 | t1.insert(2); 773 | t1.root().insert(3); 774 | t1.root().insert(5); 775 | t2.insert(1); 776 | t2.root().graft(t1.root()); 777 | CHECK_TREE(t1, data(), ""); 778 | CHECK_TREE(t2, data(), "1 2 3 5"); 779 | CHECK_TREE(t2, depth(), "3 2 1 1"); 780 | CHECK_TREE(t2, ply(), "0 1 2 2"); 781 | CHECK_TREE(t2, subtree_size(), "4 3 1 1"); 782 | 783 | t1.insert(2); 784 | t1.root().insert(3); 785 | node_type& n5b = *t1.root().insert(5); 786 | t2.insert(1); 787 | t2.root().graft(n5b); 788 | CHECK_TREE(t1, data(), "2 3"); 789 | CHECK_TREE(t1, depth(), "2 1"); 790 | CHECK_TREE(t1, ply(), "0 1"); 791 | CHECK_TREE(t1, subtree_size(), "2 1"); 792 | CHECK_TREE(t2, data(), "1 5"); 793 | CHECK_TREE(t2, depth(), "2 1"); 794 | CHECK_TREE(t2, ply(), "0 1"); 795 | CHECK_TREE(t2, subtree_size(), "2 1"); 796 | } 797 | 798 | 799 | BOOST_AUTO_TEST_CASE(insert_node) { 800 | tree > t1; 801 | tree > t2; 802 | typedef tree >::node_type node_type; 803 | 804 | // start with the node/tree overloadings 805 | // insert node -> tree 806 | t1.insert(2); 807 | t2.insert(1); 808 | t2.insert(t1.root()); 809 | CHECK_TREE(t1, data(), "2"); 810 | CHECK_TREE(t2, data(), "2"); 811 | CHECK_TREE(t2, depth(), "1"); 812 | CHECK_TREE(t2, ply(), "0"); 813 | CHECK_TREE(t2, subtree_size(), "1"); 814 | 815 | t1.insert(2); 816 | t1.root().insert(3); 817 | t1.root().insert(5); 818 | t2.insert(t1.root()); 819 | CHECK_TREE(t1, data(), "2 3 5"); 820 | CHECK_TREE(t2, data(), "2 3 5"); 821 | CHECK_TREE(t2, depth(), "2 1 1"); 822 | CHECK_TREE(t2, ply(), "0 1 1"); 823 | CHECK_TREE(t2, subtree_size(), "3 1 1"); 824 | 825 | t1.insert(2); 826 | t1.root().insert(3); 827 | node_type& n5a = *t1.root().insert(5); 828 | t2.insert(n5a); 829 | CHECK_TREE(t1, data(), "2 3 5"); 830 | CHECK_TREE(t1, depth(), "2 1 1"); 831 | CHECK_TREE(t1, ply(), "0 1 1"); 832 | CHECK_TREE(t1, subtree_size(), "3 1 1"); 833 | CHECK_TREE(t2, data(), "5"); 834 | CHECK_TREE(t2, depth(), "1"); 835 | CHECK_TREE(t2, ply(), "0"); 836 | CHECK_TREE(t2, subtree_size(), "1"); 837 | 838 | // insert tree -> tree (empty) 839 | t1.clear(); 840 | t2.insert(t1); 841 | CHECK_TREE(t1, data(), ""); 842 | CHECK_TREE(t2, data(), ""); 843 | 844 | // insert tree -> tree (non-empty) 845 | t1.insert(2); 846 | t2.insert(t1); 847 | CHECK_TREE(t1, data(), "2"); 848 | CHECK_TREE(t2, data(), "2"); 849 | 850 | // insert tree -> node (empty) 851 | t1.clear(); 852 | t2.root().insert(t1); 853 | CHECK_TREE(t1, data(), ""); 854 | CHECK_TREE(t2, data(), "2"); 855 | 856 | // insert tree -> node (non-empty) 857 | t1.insert(2); 858 | t2.insert(1); 859 | t2.root().insert(t1); 860 | CHECK_TREE(t1, data(), "2"); 861 | CHECK_TREE(t2, data(), "1 2"); 862 | 863 | // node --> node 864 | t1.insert(2); 865 | t2.insert(1); 866 | t2.root().insert(t1.root()); 867 | CHECK_TREE(t1, data(), "2"); 868 | CHECK_TREE(t2, data(), "1 2"); 869 | CHECK_TREE(t2, depth(), "2 1"); 870 | CHECK_TREE(t2, ply(), "0 1"); 871 | CHECK_TREE(t2, subtree_size(), "2 1"); 872 | 873 | t1.insert(2); 874 | t1.root().insert(3); 875 | t1.root().insert(5); 876 | t2.insert(1); 877 | t2.root().insert(t1.root()); 878 | CHECK_TREE(t1, data(), "2 3 5"); 879 | CHECK_TREE(t2, data(), "1 2 3 5"); 880 | CHECK_TREE(t2, depth(), "3 2 1 1"); 881 | CHECK_TREE(t2, ply(), "0 1 2 2"); 882 | CHECK_TREE(t2, subtree_size(), "4 3 1 1"); 883 | 884 | t1.insert(2); 885 | t1.root().insert(3); 886 | node_type& n5b = *t1.root().insert(5); 887 | t2.insert(1); 888 | t2.root().insert(n5b); 889 | CHECK_TREE(t1, data(), "2 3 5"); 890 | CHECK_TREE(t1, depth(), "2 1 1"); 891 | CHECK_TREE(t1, ply(), "0 1 1"); 892 | CHECK_TREE(t1, subtree_size(), "3 1 1"); 893 | CHECK_TREE(t2, data(), "1 5"); 894 | CHECK_TREE(t2, depth(), "2 1"); 895 | CHECK_TREE(t2, ply(), "0 1"); 896 | CHECK_TREE(t2, subtree_size(), "2 1"); 897 | } 898 | 899 | 900 | BOOST_AUTO_TEST_CASE(node_op_equality) { 901 | tree > t1; 902 | typedef tree >::node_type node_type; 903 | 904 | t1.insert(2); 905 | node_type& n3a = *t1.root().insert(3); 906 | node_type& n5a = *t1.root().insert(5); 907 | node_type& n7a = *n3a.insert(7); 908 | n5a.insert(13); 909 | n3a.insert(11); 910 | n5a.insert(17); 911 | 912 | tree > t2; 913 | 914 | t2.insert(2); 915 | node_type& n3b = *t2.root().insert(3); 916 | node_type& n5b = *t2.root().insert(5); 917 | node_type& n7b = *n3b.insert(7); 918 | n5b.insert(13); 919 | node_type& n11b = *n3b.insert(11); 920 | n5b.insert(17); 921 | 922 | BOOST_CHECK_EQUAL(t1.root() == t1.root(), true); 923 | BOOST_CHECK_EQUAL(n3a == n3a, true); 924 | BOOST_CHECK_EQUAL(n7a == n7a, true); 925 | 926 | BOOST_CHECK_EQUAL(t1.root() == t2.root(), true); 927 | BOOST_CHECK_EQUAL(n3a == n3b, true); 928 | BOOST_CHECK_EQUAL(n7a == n7b, true); 929 | 930 | BOOST_CHECK_EQUAL(n3a == n5b, false); 931 | BOOST_CHECK_EQUAL(n7a == n11b, false); 932 | } 933 | 934 | 935 | BOOST_AUTO_TEST_CASE(node_op_lessthan) { 936 | tree > t1; 937 | tree > t2; 938 | typedef tree >::node_type node_type; 939 | 940 | t1.insert(2); 941 | t2.insert(2); 942 | 943 | BOOST_CHECK_EQUAL(t1.root() < t2.root(), false); 944 | 945 | t2.clear(); 946 | t2.insert(3); 947 | BOOST_CHECK_EQUAL(t1.root() < t2.root(), true); 948 | 949 | t2.clear(); 950 | t2.insert(2); 951 | t1.root().insert(3); 952 | t1.root().insert(5); 953 | t2.root().insert(3); 954 | node_type& n5b = *t2.root().insert(5); 955 | 956 | BOOST_CHECK_EQUAL(t1.root() < t2.root(), false); 957 | 958 | n5b.erase(); 959 | t2.root().insert(7); 960 | BOOST_CHECK_EQUAL(t1.root() < t2.root(), true); 961 | } 962 | 963 | 964 | BOOST_AUTO_TEST_CASE(node_derived_comp_ops) { 965 | tree > t1; 966 | tree > t2; 967 | typedef tree >::node_type node_type; 968 | 969 | t1.insert(2); 970 | t2.insert(2); 971 | BOOST_CHECK_EQUAL(t1.root() != t2.root(), false); 972 | BOOST_CHECK_EQUAL(t2.root() != t1.root(), false); 973 | BOOST_CHECK_EQUAL(t1.root() > t2.root(), false); 974 | BOOST_CHECK_EQUAL(t2.root() > t1.root(), false); 975 | BOOST_CHECK_EQUAL(t1.root() <= t2.root(), true); 976 | BOOST_CHECK_EQUAL(t2.root() <= t1.root(), true); 977 | BOOST_CHECK_EQUAL(t1.root() >= t2.root(), true); 978 | BOOST_CHECK_EQUAL(t2.root() >= t1.root(), true); 979 | 980 | t2.erase(); 981 | t2.insert(3); 982 | BOOST_CHECK_EQUAL(t1.root() != t2.root(), true); 983 | BOOST_CHECK_EQUAL(t2.root() != t1.root(), true); 984 | BOOST_CHECK_EQUAL(t1.root() > t2.root(), false); 985 | BOOST_CHECK_EQUAL(t2.root() > t1.root(), true); 986 | BOOST_CHECK_EQUAL(t1.root() <= t2.root(), true); 987 | BOOST_CHECK_EQUAL(t2.root() <= t1.root(), false); 988 | BOOST_CHECK_EQUAL(t1.root() >= t2.root(), false); 989 | BOOST_CHECK_EQUAL(t2.root() >= t1.root(), true); 990 | } 991 | 992 | 993 | BOOST_AUTO_TEST_CASE(tree_op_equality) { 994 | tree > t1; 995 | tree > t2; 996 | typedef tree >::node_type node_type; 997 | 998 | BOOST_CHECK_EQUAL(t1 == t2, true); 999 | 1000 | t2.insert(2); 1001 | BOOST_CHECK_EQUAL(t1 == t2, false); 1002 | 1003 | t1.insert(2); 1004 | BOOST_CHECK_EQUAL(t1 == t2, true); 1005 | 1006 | t2.clear(); 1007 | t2.insert(3); 1008 | BOOST_CHECK_EQUAL(t1 == t2, false); 1009 | } 1010 | 1011 | 1012 | BOOST_AUTO_TEST_CASE(tree_op_lessthan) { 1013 | tree > t1; 1014 | tree > t2; 1015 | typedef tree >::node_type node_type; 1016 | BOOST_CHECK_EQUAL(t1 < t2, false); 1017 | 1018 | t2.insert(2); 1019 | BOOST_CHECK_EQUAL(t1 < t2, true); 1020 | BOOST_CHECK_EQUAL(t2 < t1, false); 1021 | 1022 | t1.insert(2); 1023 | BOOST_CHECK_EQUAL(t1 < t2, false); 1024 | 1025 | t2.clear(); 1026 | t2.insert(3); 1027 | BOOST_CHECK_EQUAL(t1 < t2, true); 1028 | BOOST_CHECK_EQUAL(t2 < t1, false); 1029 | 1030 | BOOST_CHECK_EQUAL(t1 < t1, false); 1031 | } 1032 | 1033 | 1034 | BOOST_AUTO_TEST_CASE(tree_derived_comp_ops) { 1035 | tree > t1; 1036 | tree > t2; 1037 | typedef tree >::node_type node_type; 1038 | 1039 | t1.insert(2); 1040 | t2.insert(2); 1041 | BOOST_CHECK_EQUAL(t1 != t2, false); 1042 | BOOST_CHECK_EQUAL(t2 != t1, false); 1043 | BOOST_CHECK_EQUAL(t1 > t2, false); 1044 | BOOST_CHECK_EQUAL(t2 > t1, false); 1045 | BOOST_CHECK_EQUAL(t1 <= t2, true); 1046 | BOOST_CHECK_EQUAL(t2 <= t1, true); 1047 | BOOST_CHECK_EQUAL(t1 >= t2, true); 1048 | BOOST_CHECK_EQUAL(t2 >= t1, true); 1049 | 1050 | t2.clear(); 1051 | t2.insert(3); 1052 | BOOST_CHECK_EQUAL(t1 != t2, true); 1053 | BOOST_CHECK_EQUAL(t2 != t1, true); 1054 | BOOST_CHECK_EQUAL(t1 > t2, false); 1055 | BOOST_CHECK_EQUAL(t2 > t1, true); 1056 | BOOST_CHECK_EQUAL(t1 <= t2, true); 1057 | BOOST_CHECK_EQUAL(t2 <= t1, false); 1058 | BOOST_CHECK_EQUAL(t1 >= t2, false); 1059 | BOOST_CHECK_EQUAL(t2 >= t1, true); 1060 | } 1061 | 1062 | 1063 | BOOST_AUTO_TEST_CASE(tree_op_equal_lhs_n_rhs_e) { 1064 | tree > t1; 1065 | typedef tree >::node_type node_type; 1066 | t1.insert(2); 1067 | t1.root().insert(3); 1068 | 1069 | tree > t2; 1070 | 1071 | t1 = t2; 1072 | 1073 | BOOST_CHECK_EQUAL(t1.empty(), true); 1074 | BOOST_CHECK_EQUAL(t2.empty(), true); 1075 | 1076 | CHECK_TREE(t1, data(), ""); 1077 | } 1078 | 1079 | BOOST_AUTO_TEST_CASE(tree_op_equal_lhs_e_rhs_n) { 1080 | tree > t1; 1081 | typedef tree >::node_type node_type; 1082 | 1083 | tree > t2; 1084 | t2.insert(2); 1085 | t2.root().insert(3); 1086 | 1087 | t1 = t2; 1088 | 1089 | BOOST_CHECK_EQUAL(t1.empty(), false); 1090 | BOOST_CHECK_EQUAL(t2.empty(), false); 1091 | 1092 | CHECK_TREE(t1, data(), "2 3"); 1093 | CHECK_TREE(t1, ply(), "0 1"); 1094 | CHECK_TREE(t1, subtree_size(), "2 1"); 1095 | } 1096 | 1097 | BOOST_AUTO_TEST_CASE(tree_op_equal_lhs_n_rhs_n) { 1098 | tree > t1; 1099 | typedef tree >::node_type node_type; 1100 | t1.insert(31); 1101 | t1.root().insert(41); 1102 | 1103 | tree > t2; 1104 | t2.insert(2); 1105 | t2.root().insert(3); 1106 | 1107 | t1 = t2; 1108 | 1109 | BOOST_CHECK_EQUAL(t1.empty(), false); 1110 | BOOST_CHECK_EQUAL(t2.empty(), false); 1111 | 1112 | CHECK_TREE(t1, data(), "2 3"); 1113 | CHECK_TREE(t1, ply(), "0 1"); 1114 | CHECK_TREE(t1, subtree_size(), "2 1"); 1115 | } 1116 | 1117 | 1118 | BOOST_AUTO_TEST_CASE(tree_swap) { 1119 | tree > t1; 1120 | tree > t2; 1121 | typedef tree >::node_type node_type; 1122 | 1123 | t1.insert(2); 1124 | t2.insert(3); 1125 | 1126 | // method version 1127 | t1.swap(t2); 1128 | 1129 | CHECK_TREE(t1, data(), "3"); 1130 | CHECK_TREE(t2, data(), "2"); 1131 | 1132 | // function version 1133 | swap(t1, t2); 1134 | 1135 | CHECK_TREE(t1, data(), "2"); 1136 | CHECK_TREE(t2, data(), "3"); 1137 | } 1138 | 1139 | 1140 | BOOST_AUTO_TEST_CASE(ordering_behavior) { 1141 | tree > t1; 1142 | typedef tree >::node_type node_type; 1143 | 1144 | t1.insert(2); 1145 | node_type& n5 = *t1.root().insert(5); 1146 | t1.root().insert(3); 1147 | t1.root().insert(7); 1148 | n5.insert(17); 1149 | n5.insert(13); 1150 | n5.insert(11); 1151 | 1152 | CHECK_TREE(t1, data(), "2 3 5 7 11 13 17"); 1153 | CHECK_TREE(t1, ply(), "0 1 1 1 2 2 2"); 1154 | CHECK_TREE(t1, depth(), "3 1 2 1 1 1 1"); 1155 | CHECK_TREE(t1, subtree_size(), "7 1 4 1 1 1 1") 1156 | } 1157 | 1158 | BOOST_AUTO_TEST_CASE(count) { 1159 | tree > t1; 1160 | t1.insert(2); 1161 | t1.root().insert(5); 1162 | t1.root().insert(3); 1163 | t1.root().insert(5); 1164 | CHECK_TREE(t1, data(), "2 3 5 5"); 1165 | BOOST_CHECK_EQUAL(t1.root().count(3), (unsigned)1); 1166 | BOOST_CHECK_EQUAL(t1.root().count(5), (unsigned)2); 1167 | BOOST_CHECK_EQUAL(t1.root().count(7), (unsigned)0); 1168 | } 1169 | 1170 | BOOST_AUTO_TEST_CASE(find) { 1171 | tree > t1; 1172 | typedef tree >::node_type::iterator iterator; 1173 | typedef tree >::node_type::const_iterator const_iterator; 1174 | t1.insert(2); 1175 | t1.root().insert(5); 1176 | t1.root().insert(3); 1177 | t1.root().insert(5); 1178 | CHECK_TREE(t1, data(), "2 3 5 5"); 1179 | 1180 | iterator j1 = t1.root().find(3); 1181 | BOOST_CHECK(j1 != t1.root().end() && j1->data() == 3); 1182 | j1 = t1.root().find(5); 1183 | BOOST_CHECK(j1 != t1.root().end() && j1->data() == 5); 1184 | j1 = t1.root().find(7); 1185 | BOOST_CHECK(j1 == t1.root().end()); 1186 | 1187 | tree > const& tc = t1; 1188 | const_iterator jc = tc.root().find(3); 1189 | BOOST_CHECK(jc != tc.root().end() && jc->data() == 3); 1190 | jc = tc.root().find(5); 1191 | BOOST_CHECK(jc != tc.root().end() && jc->data() == 5); 1192 | jc = tc.root().find(7); 1193 | BOOST_CHECK(jc == tc.root().end()); 1194 | } 1195 | 1196 | 1197 | BOOST_AUTO_TEST_CASE(lower_upper_equal) { 1198 | tree > t1; 1199 | typedef tree >::node_type::iterator iterator; 1200 | typedef tree >::node_type::const_iterator const_iterator; 1201 | 1202 | t1.insert(2); 1203 | t1.root().insert(5); 1204 | t1.root().insert(3); 1205 | t1.root().insert(7); 1206 | t1.root().insert(5); 1207 | 1208 | CHECK_TREE(t1, data(), "2 3 5 5 7"); 1209 | 1210 | iterator l1 = t1.root().lower_bound(5); 1211 | iterator u1 = t1.root().upper_bound(5); 1212 | pair r1 = t1.root().equal_range(5); 1213 | BOOST_CHECK_EQUAL(l1->data(), 5); 1214 | BOOST_CHECK_EQUAL(u1->data(), 7); 1215 | BOOST_CHECK(r1.first == l1); 1216 | BOOST_CHECK(r1.second == u1); 1217 | ++l1; 1218 | BOOST_CHECK_EQUAL(l1->data(), 5); 1219 | ++l1; 1220 | BOOST_CHECK_EQUAL(l1->data(), 7); 1221 | 1222 | const tree >& tc = t1; 1223 | const_iterator lc = tc.root().lower_bound(5); 1224 | const_iterator uc = tc.root().upper_bound(5); 1225 | pair rc = tc.root().equal_range(5); 1226 | BOOST_CHECK_EQUAL(lc->data(), 5); 1227 | BOOST_CHECK_EQUAL(uc->data(), 7); 1228 | BOOST_CHECK(rc.first == lc); 1229 | BOOST_CHECK(rc.second == uc); 1230 | ++lc; 1231 | BOOST_CHECK_EQUAL(lc->data(), 5); 1232 | ++lc; 1233 | BOOST_CHECK_EQUAL(lc->data(), 7); 1234 | } 1235 | 1236 | BOOST_AUTO_TEST_CASE(erase_key) { 1237 | tree > t1; 1238 | 1239 | t1.insert(2); 1240 | t1.root().insert(3); 1241 | t1.root().insert(5); 1242 | t1.root().insert(7); 1243 | t1.root().insert(5); 1244 | 1245 | CHECK_TREE(t1, data(), "2 3 5 5 7"); 1246 | 1247 | unsigned c = t1.root().erase(11); 1248 | BOOST_CHECK_EQUAL(c, unsigned(0)); 1249 | CHECK_TREE(t1, data(), "2 3 5 5 7"); 1250 | 1251 | c = t1.root().erase(5); 1252 | BOOST_CHECK_EQUAL(c, unsigned(2)); 1253 | CHECK_TREE(t1, data(), "2 3 7"); 1254 | } 1255 | 1256 | BOOST_AUTO_TEST_SUITE_END() 1257 | -------------------------------------------------------------------------------- /tests/ut_raw.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "st_tree.h" 4 | #include "ut_common.h" 5 | 6 | #include 7 | 8 | 9 | BOOST_AUTO_TEST_SUITE(ut_raw) 10 | 11 | 12 | BOOST_AUTO_TEST_CASE(default_ctor) { 13 | tree t1; 14 | BOOST_CHECK(t1.empty()); 15 | BOOST_CHECK_EQUAL(t1.size(), 0); 16 | BOOST_CHECK_EQUAL(t1.depth(), 0); 17 | BOOST_CHECK_THROW(t1.root(), st_tree::exception); 18 | } 19 | 20 | BOOST_AUTO_TEST_CASE(insert_root) { 21 | tree t1; 22 | t1.insert(7); 23 | BOOST_CHECK_EQUAL(t1.empty(), false); 24 | BOOST_CHECK_EQUAL(t1.size(), 1); 25 | BOOST_CHECK_EQUAL(t1.depth(), 1); 26 | BOOST_CHECK_EQUAL(t1.root().is_root(), true); 27 | BOOST_CHECK_EQUAL(t1.root().data(), 7); 28 | BOOST_CHECK_THROW(t1.root().parent(), st_tree::exception); 29 | } 30 | 31 | 32 | BOOST_AUTO_TEST_CASE(insert_subnodes) { 33 | tree t1; 34 | 35 | t1.insert(7); 36 | BOOST_CHECK_EQUAL(t1.empty(), false); 37 | BOOST_CHECK_EQUAL(t1.size(), 1); 38 | BOOST_CHECK_EQUAL(t1.depth(), 1); 39 | BOOST_CHECK_EQUAL(t1.root().size(), 0); 40 | 41 | t1.root().insert(8); 42 | BOOST_CHECK_EQUAL(t1.size(), 2); 43 | BOOST_CHECK_EQUAL(t1.depth(), 2); 44 | BOOST_CHECK_EQUAL(t1.empty(), false); 45 | BOOST_CHECK_EQUAL(t1.root().size(), 1); 46 | 47 | t1.root().insert(9); 48 | BOOST_CHECK_EQUAL(t1.size(), 3); 49 | BOOST_CHECK_EQUAL(t1.depth(), 2); 50 | BOOST_CHECK_EQUAL(t1.empty(), false); 51 | BOOST_CHECK_EQUAL(t1.root().size(), 2); 52 | 53 | BOOST_CHECK_EQUAL(t1.root().data(), 7); 54 | BOOST_CHECK_EQUAL(t1.root()[0].data(), 8); 55 | BOOST_CHECK_EQUAL(t1.root()[1].data(), 9); 56 | } 57 | 58 | BOOST_AUTO_TEST_CASE(emplace_subnodes) { 59 | struct str1 { 60 | int i1; 61 | std::string s1; 62 | str1() { 63 | i1 = 0; 64 | s1 = ""; 65 | } 66 | str1(int i, const std::string s) { 67 | i1 = i; 68 | s1 = s; 69 | } 70 | }; 71 | 72 | tree t1; 73 | 74 | t1.emplace(7, "7"); 75 | BOOST_CHECK_EQUAL(t1.empty(), false); 76 | BOOST_CHECK_EQUAL(t1.size(), 1); 77 | BOOST_CHECK_EQUAL(t1.depth(), 1); 78 | BOOST_CHECK_EQUAL(t1.root().size(), 0); 79 | 80 | t1.root().emplace_back(8, "8"); 81 | BOOST_CHECK_EQUAL(t1.size(), 2); 82 | BOOST_CHECK_EQUAL(t1.depth(), 2); 83 | BOOST_CHECK_EQUAL(t1.empty(), false); 84 | BOOST_CHECK_EQUAL(t1.root().size(), 1); 85 | 86 | t1.root().emplace_insert(9, "9"); 87 | BOOST_CHECK_EQUAL(t1.size(), 3); 88 | BOOST_CHECK_EQUAL(t1.depth(), 2); 89 | BOOST_CHECK_EQUAL(t1.empty(), false); 90 | BOOST_CHECK_EQUAL(t1.root().size(), 2); 91 | 92 | BOOST_CHECK_EQUAL(t1.root().data().i1, 7); 93 | BOOST_CHECK_EQUAL(t1.root()[0].data().i1, 8); 94 | BOOST_CHECK_EQUAL(t1.root()[1].data().i1, 9); 95 | BOOST_CHECK_EQUAL(t1.root().data().s1, "7"); 96 | BOOST_CHECK_EQUAL(t1.root()[0].data().s1, "8"); 97 | BOOST_CHECK_EQUAL(t1.root()[1].data().s1, "9"); 98 | } 99 | 100 | 101 | BOOST_AUTO_TEST_CASE(clear) { 102 | tree t1; 103 | 104 | t1.insert(7); 105 | t1.root().insert(8); 106 | t1.root().insert(9); 107 | BOOST_CHECK_EQUAL(t1.size(), 3); 108 | BOOST_CHECK_EQUAL(t1.depth(), 2); 109 | BOOST_CHECK_EQUAL(t1.empty(), false); 110 | BOOST_CHECK_EQUAL(t1.root().size(), 2); 111 | 112 | t1.clear(); 113 | BOOST_CHECK_EQUAL(t1.size(), 0); 114 | BOOST_CHECK_EQUAL(t1.depth(), 0); 115 | BOOST_CHECK_EQUAL(t1.empty(), true); 116 | BOOST_CHECK_THROW(t1.root(), st_tree::exception); 117 | } 118 | 119 | 120 | BOOST_AUTO_TEST_CASE(reinsert) { 121 | tree t1; 122 | 123 | t1.insert(7); 124 | t1.root().insert(8); 125 | t1.root().insert(9); 126 | BOOST_CHECK_EQUAL(t1.size(), 3); 127 | BOOST_CHECK_EQUAL(t1.depth(), 2); 128 | BOOST_CHECK_EQUAL(t1.empty(), false); 129 | BOOST_CHECK_EQUAL(t1.root().size(), 2); 130 | 131 | t1.insert(3); 132 | BOOST_CHECK_EQUAL(t1.size(), 1); 133 | BOOST_CHECK_EQUAL(t1.depth(), 1); 134 | BOOST_CHECK_EQUAL(t1.empty(), false); 135 | BOOST_CHECK_EQUAL(t1.root().size(), 0); 136 | BOOST_CHECK_EQUAL(t1.root().data(), 3); 137 | } 138 | 139 | 140 | BOOST_AUTO_TEST_CASE(erase) { 141 | tree t1; 142 | 143 | t1.insert(7); 144 | t1.root().insert(8); 145 | 146 | t1.root().erase(t1.root().begin()); 147 | BOOST_CHECK_EQUAL(t1.size(), 1); 148 | BOOST_CHECK_EQUAL(t1.depth(), 1); 149 | BOOST_CHECK_EQUAL(t1.empty(), false); 150 | BOOST_CHECK_EQUAL(t1.root().size(), 0); 151 | BOOST_CHECK_EQUAL(t1.root().data(), 7); 152 | } 153 | 154 | 155 | BOOST_AUTO_TEST_CASE(erase_noarg) { 156 | tree t1; 157 | 158 | t1.insert(2); 159 | t1.root().insert(3); 160 | t1.root().insert(5); 161 | t1.root()[0].insert(7); 162 | t1.root()[0].insert(11); 163 | t1.root()[1].insert(13); 164 | t1.root()[1].insert(17); 165 | 166 | CHECK_TREE(t1, data(), "2 3 5 7 11 13 17"); 167 | t1.root()[1].erase(); 168 | CHECK_TREE(t1, data(), "2 3 7 11"); 169 | 170 | t1.root()[0][1].erase(); 171 | CHECK_TREE(t1, data(), "2 3 7"); 172 | 173 | t1.root().erase(); 174 | BOOST_CHECK_EQUAL(t1.empty(), true); 175 | CHECK_TREE(t1, data(), ""); 176 | } 177 | 178 | 179 | BOOST_AUTO_TEST_CASE(bf_iterator_empty) { 180 | tree t1; 181 | BOOST_CHECK_EQUAL(t1.bf_begin() == t1.bf_end(), true); 182 | BOOST_CHECK_EQUAL(t1.bf_begin() != t1.bf_end(), false); 183 | } 184 | 185 | 186 | BOOST_AUTO_TEST_CASE(bf_iterator) { 187 | tree t1; 188 | CHECK_TREE(t1, data(), ""); 189 | 190 | t1.insert(2); 191 | CHECK_TREE(t1, data(), "2"); 192 | 193 | t1.root().insert(3); 194 | t1.root().insert(5); 195 | CHECK_TREE(t1, data(), "2 3 5"); 196 | 197 | t1.root()[0].insert(7); 198 | t1.root()[1].insert(13); 199 | t1.root()[0].insert(11); 200 | t1.root()[1].insert(17); 201 | CHECK_TREE(t1, data(), "2 3 5 7 11 13 17"); 202 | CHECK_TREE(t1.root(), data(), "2 3 5 7 11 13 17"); 203 | tree const& ct1 = t1; 204 | CHECK_TREE(ct1, data(), "2 3 5 7 11 13 17"); 205 | CHECK_TREE(ct1.root(), data(), "2 3 5 7 11 13 17"); 206 | } 207 | 208 | 209 | BOOST_AUTO_TEST_CASE(df_post_iterator_empty) { 210 | tree t1; 211 | BOOST_CHECK_EQUAL(t1.df_post_begin() == t1.df_post_end(), true); 212 | BOOST_CHECK_EQUAL(t1.df_post_begin() != t1.df_post_end(), false); 213 | } 214 | 215 | 216 | BOOST_AUTO_TEST_CASE(df_post_iterator) { 217 | tree t1; 218 | CHECK_TREE_DF_POST(t1, data(), ""); 219 | 220 | t1.insert(2); 221 | CHECK_TREE_DF_POST(t1, data(), "2"); 222 | 223 | t1.root().insert(3); 224 | t1.root().insert(5); 225 | CHECK_TREE_DF_POST(t1, data(), "3 5 2"); 226 | 227 | t1.root()[0].insert(7); 228 | t1.root()[1].insert(13); 229 | t1.root()[0].insert(11); 230 | t1.root()[1].insert(17); 231 | CHECK_TREE_DF_POST(t1, data(), "7 11 3 13 17 5 2"); 232 | CHECK_TREE_DF_POST(t1.root(), data(), "7 11 3 13 17 5 2"); 233 | tree const& ct1 = t1; 234 | CHECK_TREE_DF_POST(ct1, data(), "7 11 3 13 17 5 2"); 235 | CHECK_TREE_DF_POST(ct1.root(), data(), "7 11 3 13 17 5 2"); 236 | } 237 | 238 | 239 | BOOST_AUTO_TEST_CASE(df_pre_iterator_empty) { 240 | tree t1; 241 | BOOST_CHECK_EQUAL(t1.df_pre_begin() == t1.df_pre_end(), true); 242 | BOOST_CHECK_EQUAL(t1.df_pre_begin() != t1.df_pre_end(), false); 243 | } 244 | 245 | 246 | BOOST_AUTO_TEST_CASE(df_pre_iterator) { 247 | tree t1; 248 | CHECK_TREE_DF_PRE(t1, data(), ""); 249 | 250 | t1.insert(2); 251 | CHECK_TREE_DF_PRE(t1, data(), "2"); 252 | 253 | t1.root().insert(3); 254 | t1.root().insert(5); 255 | CHECK_TREE_DF_PRE(t1, data(), "2 3 5"); 256 | 257 | t1.root()[0].insert(7); 258 | t1.root()[1].insert(13); 259 | t1.root()[0].insert(11); 260 | t1.root()[1].insert(17); 261 | CHECK_TREE_DF_PRE(t1, data(), "2 3 7 11 5 13 17"); 262 | CHECK_TREE_DF_PRE(t1.root(), data(), "2 3 7 11 5 13 17"); 263 | tree const& ct1 = t1; 264 | CHECK_TREE_DF_PRE(ct1, data(), "2 3 7 11 5 13 17"); 265 | CHECK_TREE_DF_PRE(ct1.root(), data(), "2 3 7 11 5 13 17"); 266 | } 267 | 268 | 269 | 270 | BOOST_AUTO_TEST_CASE(node_ply) { 271 | tree t1; 272 | 273 | t1.insert(2); 274 | CHECK_TREE(t1, data(), "2"); 275 | CHECK_TREE(t1, ply(), "0"); 276 | 277 | t1.root().insert(3); 278 | t1.root().insert(5); 279 | CHECK_TREE(t1, data(), "2 3 5"); 280 | CHECK_TREE(t1, ply(), "0 1 1"); 281 | 282 | t1.root()[0].insert(7); 283 | t1.root()[0].insert(11); 284 | t1.root()[1].insert(13); 285 | t1.root()[1].insert(17); 286 | CHECK_TREE(t1, data(), "2 3 5 7 11 13 17"); 287 | CHECK_TREE(t1, ply(), "0 1 1 2 2 2 2"); 288 | 289 | t1.root().insert(77); 290 | CHECK_TREE(t1, data(), "2 3 5 77 7 11 13 17"); 291 | CHECK_TREE(t1, ply(), "0 1 1 1 2 2 2 2"); 292 | 293 | t1.root().erase(t1.root().begin()); 294 | CHECK_TREE(t1, data(), "2 5 77 13 17"); 295 | CHECK_TREE(t1, ply(), "0 1 1 2 2"); 296 | 297 | t1.root().erase(t1.root().begin()); 298 | CHECK_TREE(t1, data(), "2 77"); 299 | CHECK_TREE(t1, ply(), "0 1"); 300 | 301 | t1.root().erase(t1.root().begin()); 302 | CHECK_TREE(t1, data(), "2"); 303 | CHECK_TREE(t1, ply(), "0"); 304 | } 305 | 306 | BOOST_AUTO_TEST_CASE(node_depth) { 307 | tree t1; 308 | 309 | t1.insert(2); 310 | CHECK_TREE(t1, data(), "2"); 311 | CHECK_TREE(t1, depth(), "1"); 312 | CHECK_TREE(t1, ply(), "0"); 313 | 314 | t1.root().insert(3); 315 | t1.root().insert(5); 316 | CHECK_TREE(t1, data(), "2 3 5"); 317 | CHECK_TREE(t1, depth(), "2 1 1"); 318 | CHECK_TREE(t1, ply(), "0 1 1"); 319 | 320 | t1.root()[0].insert(7); 321 | t1.root()[0].insert(11); 322 | t1.root()[1].insert(13); 323 | t1.root()[1].insert(17); 324 | CHECK_TREE(t1, data(), "2 3 5 7 11 13 17"); 325 | CHECK_TREE(t1, depth(), "3 2 2 1 1 1 1"); 326 | CHECK_TREE(t1, ply(), "0 1 1 2 2 2 2"); 327 | 328 | t1.root().insert(77); 329 | CHECK_TREE(t1, data(), "2 3 5 77 7 11 13 17"); 330 | CHECK_TREE(t1, depth(), "3 2 2 1 1 1 1 1"); 331 | CHECK_TREE(t1, ply(), "0 1 1 1 2 2 2 2"); 332 | 333 | t1.root().erase(t1.root().begin()); 334 | CHECK_TREE(t1, data(), "2 5 77 13 17"); 335 | CHECK_TREE(t1, depth(), "3 2 1 1 1"); 336 | 337 | t1.root().erase(t1.root().begin()); 338 | CHECK_TREE(t1, data(), "2 77"); 339 | CHECK_TREE(t1, depth(), "2 1"); 340 | 341 | t1.root().erase(t1.root().begin()); 342 | CHECK_TREE(t1, data(), "2"); 343 | CHECK_TREE(t1, depth(), "1"); 344 | } 345 | 346 | BOOST_AUTO_TEST_CASE(node_subtree_size) { 347 | tree t1; 348 | 349 | t1.insert(2); 350 | CHECK_TREE(t1, data(), "2"); 351 | CHECK_TREE(t1, subtree_size(), "1"); 352 | 353 | t1.root().insert(3); 354 | t1.root().insert(5); 355 | CHECK_TREE(t1, data(), "2 3 5"); 356 | CHECK_TREE(t1, subtree_size(), "3 1 1"); 357 | 358 | t1.root()[0].insert(7); 359 | t1.root()[0].insert(11); 360 | t1.root()[1].insert(13); 361 | t1.root()[1].insert(17); 362 | CHECK_TREE(t1, data(), "2 3 5 7 11 13 17"); 363 | CHECK_TREE(t1, subtree_size(), "7 3 3 1 1 1 1"); 364 | 365 | t1.root().insert(77); 366 | CHECK_TREE(t1, data(), "2 3 5 77 7 11 13 17"); 367 | CHECK_TREE(t1, subtree_size(), "8 3 3 1 1 1 1 1"); 368 | 369 | t1.root().erase(t1.root().begin()); 370 | CHECK_TREE(t1, data(), "2 5 77 13 17"); 371 | CHECK_TREE(t1, subtree_size(), "5 3 1 1 1"); 372 | 373 | t1.root().erase(t1.root().begin()); 374 | CHECK_TREE(t1, data(), "2 77"); 375 | CHECK_TREE(t1, subtree_size(), "2 1"); 376 | 377 | t1.root().erase(t1.root().begin()); 378 | CHECK_TREE(t1, data(), "2"); 379 | CHECK_TREE(t1, subtree_size(), "1"); 380 | } 381 | 382 | 383 | BOOST_AUTO_TEST_CASE(node_parent) { 384 | tree t1; 385 | t1.insert(2); 386 | BOOST_CHECK_THROW(t1.root().parent(), st_tree::exception); 387 | t1.root().insert(3); 388 | BOOST_CHECK_EQUAL(t1.root()[0].parent().data(), 2); 389 | const tree& t2 = t1; 390 | BOOST_CHECK_EQUAL(t2.root()[0].parent().data(), 2); 391 | } 392 | 393 | 394 | BOOST_AUTO_TEST_CASE(node_tree) { 395 | tree t1; 396 | t1.insert(2); 397 | t1.root().insert(3); 398 | t1.root().insert(5); 399 | tree& t2 = t1.root().tree(); 400 | BOOST_CHECK_EQUAL(t1 == t2, true); 401 | t2 = t1.root()[0].tree(); 402 | BOOST_CHECK_EQUAL(t1 == t2, true); 403 | const tree& t3 = t1; 404 | const tree& t4 = t3.root().tree(); 405 | BOOST_CHECK_EQUAL(t1 == t4, true); 406 | } 407 | 408 | 409 | BOOST_AUTO_TEST_CASE(erase_node) { 410 | tree t1; 411 | t1.insert(2); 412 | t1.root().insert(3); 413 | t1.root().insert(5); 414 | t1.root()[0].insert(7); 415 | t1.root()[1].insert(13); 416 | t1.root()[0].insert(11); 417 | t1.root()[1].insert(17); 418 | BOOST_CHECK_EQUAL(t1.size(), 7); 419 | BOOST_CHECK_EQUAL(t1.depth(), 3); 420 | 421 | t1.root().erase(t1.root().begin()); 422 | BOOST_CHECK_EQUAL(t1.size(), 4); 423 | BOOST_CHECK_EQUAL(t1.depth(), 3); 424 | 425 | CHECK_TREE(t1, data(), "2 5 13 17"); 426 | CHECK_TREE(t1, ply(), "0 1 2 2"); 427 | CHECK_TREE(t1, subtree_size(), "4 3 1 1"); 428 | } 429 | 430 | BOOST_AUTO_TEST_CASE(clear_node) { 431 | tree t1; 432 | t1.insert(2); 433 | t1.root().insert(3); 434 | t1.root().insert(5); 435 | t1.root()[0].insert(7); 436 | t1.root()[1].insert(13); 437 | t1.root()[0].insert(11); 438 | t1.root()[1].insert(17); 439 | BOOST_CHECK_EQUAL(t1.size(), 7); 440 | BOOST_CHECK_EQUAL(t1.depth(), 3); 441 | 442 | t1.root().clear(); 443 | BOOST_CHECK_EQUAL(t1.size(), 1); 444 | BOOST_CHECK_EQUAL(t1.depth(), 1); 445 | 446 | CHECK_TREE(t1, data(), "2"); 447 | CHECK_TREE(t1, ply(), "0"); 448 | CHECK_TREE(t1, subtree_size(), "1"); 449 | } 450 | 451 | BOOST_AUTO_TEST_CASE(node_op_equal) { 452 | tree t1; 453 | t1.insert(2); 454 | t1.root().insert(3); 455 | 456 | tree t2; 457 | t2.insert(5); 458 | t2.root().insert(7); 459 | t2.root().insert(11); 460 | 461 | BOOST_CHECK_EQUAL(t1.root().data(), 2); 462 | 463 | t1.root()[0] = t2.root(); 464 | BOOST_CHECK_EQUAL(t1.size(), 4); 465 | BOOST_CHECK_EQUAL(t1.depth(), 3); 466 | 467 | CHECK_TREE(t1, data(), "2 5 7 11"); 468 | CHECK_TREE(t1, ply(), "0 1 2 2"); 469 | CHECK_TREE(t1, subtree_size(), "4 3 1 1"); 470 | 471 | CHECK_TREE(t2, data(), "5 7 11"); 472 | CHECK_TREE(t2, ply(), "0 1 1"); 473 | CHECK_TREE(t2, subtree_size(), "3 1 1"); 474 | } 475 | 476 | 477 | BOOST_AUTO_TEST_CASE(node_op_equal_root) { 478 | tree t1; 479 | t1.insert(2); 480 | t1.root().insert(3); 481 | 482 | tree t2; 483 | t2.insert(5); 484 | t2.root().insert(7); 485 | t2.root().insert(11); 486 | 487 | t1.root() = t2.root(); 488 | BOOST_CHECK_EQUAL(t1.size(), 3); 489 | BOOST_CHECK_EQUAL(t1.depth(), 2); 490 | 491 | CHECK_TREE(t1, data(), "5 7 11"); 492 | CHECK_TREE(t1, ply(), "0 1 1"); 493 | CHECK_TREE(t1, subtree_size(), "3 1 1"); 494 | 495 | CHECK_TREE(t2, data(), "5 7 11"); 496 | CHECK_TREE(t2, ply(), "0 1 1"); 497 | CHECK_TREE(t1, subtree_size(), "3 1 1"); 498 | } 499 | 500 | 501 | BOOST_AUTO_TEST_CASE(node_op_equal_subtree) { 502 | tree t1; 503 | 504 | t1.insert(2); 505 | t1.root().insert(3); 506 | t1.root().insert(5); 507 | t1.root()[0].insert(7); 508 | t1.root()[0].insert(11); 509 | t1.root()[1].insert(13); 510 | t1.root()[1].insert(17); 511 | 512 | BOOST_CHECK_THROW(t1.root()[0] = t1.root(), st_tree::exception); 513 | 514 | t1.root() = t1.root()[0]; 515 | CHECK_TREE(t1, data(), "3 7 11"); 516 | BOOST_CHECK_EQUAL(t1.size(), 3); 517 | BOOST_CHECK_EQUAL(t1.depth(), 2); 518 | 519 | t1.root()[1].insert(13); 520 | t1.root()[1].insert(17); 521 | t1.root()[1] = t1.root()[1][1]; 522 | CHECK_TREE(t1, data(), "3 7 17"); 523 | } 524 | 525 | 526 | BOOST_AUTO_TEST_CASE(node_swap) { 527 | tree t1; 528 | tree t2; 529 | 530 | t1.insert(2); 531 | t1.root().insert(3); 532 | t1.root().insert(5); 533 | t1.root()[0].insert(7); 534 | t1.root()[0].insert(11); 535 | 536 | t2.insert(102); 537 | t2.root().insert(103); 538 | t2.root().insert(105); 539 | t2.root()[0].insert(107); 540 | t2.root()[0].insert(111); 541 | 542 | // swap a leaf 543 | swap(t1.root()[0][0], t2.root()[0][0]); 544 | BOOST_CHECK_EQUAL(t1.size(), 5); 545 | BOOST_CHECK_EQUAL(t1.depth(), 3); 546 | CHECK_TREE(t1, data(), "2 3 5 107 11"); 547 | CHECK_TREE(t1, ply(), "0 1 1 2 2"); 548 | CHECK_TREE(t1, depth(), "3 2 1 1 1"); 549 | CHECK_TREE(t1, subtree_size(), "5 3 1 1 1"); 550 | 551 | BOOST_CHECK_EQUAL(t2.size(), 5); 552 | BOOST_CHECK_EQUAL(t2.depth(), 3); 553 | CHECK_TREE(t2, data(), "102 103 105 7 111"); 554 | CHECK_TREE(t2, ply(), "0 1 1 2 2"); 555 | CHECK_TREE(t2, depth(), "3 2 1 1 1"); 556 | CHECK_TREE(t2, subtree_size(), "5 3 1 1 1"); 557 | 558 | // put it back 559 | swap(t1.root()[0][0], t2.root()[0][0]); 560 | 561 | // swap an internal 562 | swap(t1.root()[0], t2.root()[0]); 563 | BOOST_CHECK_EQUAL(t1.size(), 5); 564 | BOOST_CHECK_EQUAL(t1.depth(), 3); 565 | CHECK_TREE(t1, data(), "2 103 5 107 111"); 566 | CHECK_TREE(t1, ply(), "0 1 1 2 2"); 567 | CHECK_TREE(t1, depth(), "3 2 1 1 1"); 568 | CHECK_TREE(t1, subtree_size(), "5 3 1 1 1"); 569 | BOOST_CHECK_EQUAL(t2.size(), 5); 570 | BOOST_CHECK_EQUAL(t2.depth(), 3); 571 | CHECK_TREE(t2, data(), "102 3 105 7 11"); 572 | CHECK_TREE(t2, ply(), "0 1 1 2 2"); 573 | CHECK_TREE(t2, depth(), "3 2 1 1 1"); 574 | CHECK_TREE(t2, subtree_size(), "5 3 1 1 1"); 575 | 576 | // put it back 577 | swap(t1.root()[0], t2.root()[0]); 578 | 579 | // swap the root 580 | swap(t1.root(), t2.root()); 581 | BOOST_CHECK_EQUAL(t1.size(), 5); 582 | BOOST_CHECK_EQUAL(t1.depth(), 3); 583 | CHECK_TREE(t1, data(), "102 103 105 107 111"); 584 | CHECK_TREE(t1, ply(), "0 1 1 2 2"); 585 | CHECK_TREE(t1, depth(), "3 2 1 1 1"); 586 | CHECK_TREE(t1, subtree_size(), "5 3 1 1 1"); 587 | BOOST_CHECK_EQUAL(t2.size(), 5); 588 | BOOST_CHECK_EQUAL(t2.depth(), 3); 589 | CHECK_TREE(t2, data(), "2 3 5 7 11"); 590 | CHECK_TREE(t2, ply(), "0 1 1 2 2"); 591 | CHECK_TREE(t2, depth(), "3 2 1 1 1"); 592 | CHECK_TREE(t2, subtree_size(), "5 3 1 1 1"); 593 | 594 | // put it back 595 | swap(t1.root(), t2.root()); 596 | 597 | // swap different plies 598 | swap(t1.root(), t2.root()[0]); 599 | BOOST_CHECK_EQUAL(t1.size(), 3); 600 | BOOST_CHECK_EQUAL(t1.depth(), 2); 601 | CHECK_TREE(t1, data(), "103 107 111"); 602 | CHECK_TREE(t1, ply(), "0 1 1"); 603 | CHECK_TREE(t1, depth(), "2 1 1"); 604 | CHECK_TREE(t1, subtree_size(), "3 1 1"); 605 | BOOST_CHECK_EQUAL(t2.size(), 7); 606 | BOOST_CHECK_EQUAL(t2.depth(), 4); 607 | CHECK_TREE(t2, data(), "102 2 105 3 5 7 11"); 608 | CHECK_TREE(t2, ply(), "0 1 1 2 2 3 3"); 609 | CHECK_TREE(t2, depth(), "4 3 1 2 1 1 1"); 610 | CHECK_TREE(t2, subtree_size(), "7 5 1 3 1 1 1"); 611 | 612 | // put them back 613 | swap(t1.root(), t2.root()[0]); 614 | 615 | // on same tree 616 | swap(t1.root()[0], t1.root()[1]); 617 | BOOST_CHECK_EQUAL(t1.size(), 5); 618 | BOOST_CHECK_EQUAL(t1.depth(), 3); 619 | CHECK_TREE(t1, data(), "2 5 3 7 11"); 620 | CHECK_TREE(t1, ply(), "0 1 1 2 2"); 621 | CHECK_TREE(t1, depth(), "3 1 2 1 1"); 622 | CHECK_TREE(t1, subtree_size(), "5 1 3 1 1"); 623 | 624 | // put them back 625 | swap(t1.root()[0], t1.root()[1]); 626 | 627 | // no-no 628 | BOOST_CHECK_THROW(swap(t1.root(), t1.root()[0]), st_tree::exception); 629 | BOOST_CHECK_THROW(swap(t1.root()[1], t1.root()), st_tree::exception); 630 | } 631 | 632 | 633 | BOOST_AUTO_TEST_CASE(graft) { 634 | tree t1; 635 | tree t2; 636 | 637 | // start with the node/tree overloadings 638 | // graft node -> tree 639 | t1.insert(2); 640 | t2.insert(1); 641 | t2.graft(t1.root()); 642 | CHECK_TREE(t1, data(), ""); 643 | CHECK_TREE(t2, data(), "2"); 644 | CHECK_TREE(t2, depth(), "1"); 645 | CHECK_TREE(t2, ply(), "0"); 646 | CHECK_TREE(t2, subtree_size(), "1"); 647 | 648 | t1.insert(2); 649 | t1.root().insert(3); 650 | t1.root().insert(5); 651 | t2.graft(t1.root()); 652 | CHECK_TREE(t1, data(), ""); 653 | CHECK_TREE(t2, data(), "2 3 5"); 654 | CHECK_TREE(t2, depth(), "2 1 1"); 655 | CHECK_TREE(t2, ply(), "0 1 1"); 656 | CHECK_TREE(t2, subtree_size(), "3 1 1"); 657 | 658 | t1.insert(2); 659 | t1.root().insert(3); 660 | t1.root().insert(5); 661 | t2.graft(t1.root()[1]); 662 | CHECK_TREE(t1, data(), "2 3"); 663 | CHECK_TREE(t1, depth(), "2 1"); 664 | CHECK_TREE(t1, ply(), "0 1"); 665 | CHECK_TREE(t1, subtree_size(), "2 1"); 666 | CHECK_TREE(t2, data(), "5"); 667 | CHECK_TREE(t2, depth(), "1"); 668 | CHECK_TREE(t2, ply(), "0"); 669 | CHECK_TREE(t2, subtree_size(), "1"); 670 | 671 | // graft tree -> tree (empty) 672 | t1.clear(); 673 | t2.graft(t1); 674 | CHECK_TREE(t1, data(), ""); 675 | CHECK_TREE(t2, data(), ""); 676 | 677 | // graft tree -> tree (non-empty) 678 | t1.insert(2); 679 | t2.graft(t1); 680 | CHECK_TREE(t1, data(), ""); 681 | CHECK_TREE(t2, data(), "2"); 682 | 683 | // graft tree -> node (empty) 684 | t2.root().graft(t1); 685 | CHECK_TREE(t1, data(), ""); 686 | CHECK_TREE(t2, data(), "2"); 687 | 688 | // graft tree -> node (non-empty) 689 | t1.insert(2); 690 | t2.insert(1); 691 | t2.root().graft(t1); 692 | CHECK_TREE(t1, data(), ""); 693 | CHECK_TREE(t2, data(), "1 2"); 694 | 695 | // node --> node 696 | t1.insert(2); 697 | t2.insert(1); 698 | t2.root().graft(t1.root()); 699 | CHECK_TREE(t1, data(), ""); 700 | CHECK_TREE(t2, data(), "1 2"); 701 | CHECK_TREE(t2, depth(), "2 1"); 702 | CHECK_TREE(t2, ply(), "0 1"); 703 | CHECK_TREE(t2, subtree_size(), "2 1"); 704 | 705 | t1.insert(2); 706 | t1.root().insert(3); 707 | t1.root().insert(5); 708 | t2.insert(1); 709 | t2.root().graft(t1.root()); 710 | CHECK_TREE(t1, data(), ""); 711 | CHECK_TREE(t2, data(), "1 2 3 5"); 712 | CHECK_TREE(t2, depth(), "3 2 1 1"); 713 | CHECK_TREE(t2, ply(), "0 1 2 2"); 714 | CHECK_TREE(t2, subtree_size(), "4 3 1 1"); 715 | 716 | t1.insert(2); 717 | t1.root().insert(3); 718 | t1.root().insert(5); 719 | t2.insert(1); 720 | t2.root().graft(t1.root()[1]); 721 | CHECK_TREE(t1, data(), "2 3"); 722 | CHECK_TREE(t1, depth(), "2 1"); 723 | CHECK_TREE(t1, ply(), "0 1"); 724 | CHECK_TREE(t1, subtree_size(), "2 1"); 725 | CHECK_TREE(t2, data(), "1 5"); 726 | CHECK_TREE(t2, depth(), "2 1"); 727 | CHECK_TREE(t2, ply(), "0 1"); 728 | CHECK_TREE(t2, subtree_size(), "2 1"); 729 | } 730 | 731 | 732 | BOOST_AUTO_TEST_CASE(insert_node) { 733 | tree t1; 734 | tree t2; 735 | 736 | // start with the node/tree overloadings 737 | // insert node -> tree 738 | t1.insert(2); 739 | t2.insert(1); 740 | t2.insert(t1.root()); 741 | CHECK_TREE(t1, data(), "2"); 742 | CHECK_TREE(t2, data(), "2"); 743 | CHECK_TREE(t2, depth(), "1"); 744 | CHECK_TREE(t2, ply(), "0"); 745 | CHECK_TREE(t2, subtree_size(), "1"); 746 | 747 | t1.insert(2); 748 | t1.root().insert(3); 749 | t1.root().insert(5); 750 | t2.insert(t1.root()); 751 | CHECK_TREE(t1, data(), "2 3 5"); 752 | CHECK_TREE(t2, data(), "2 3 5"); 753 | CHECK_TREE(t2, depth(), "2 1 1"); 754 | CHECK_TREE(t2, ply(), "0 1 1"); 755 | CHECK_TREE(t2, subtree_size(), "3 1 1"); 756 | 757 | t1.insert(2); 758 | t1.root().insert(3); 759 | t1.root().insert(5); 760 | t2.insert(t1.root()[1]); 761 | CHECK_TREE(t1, data(), "2 3 5"); 762 | CHECK_TREE(t1, depth(), "2 1 1"); 763 | CHECK_TREE(t1, ply(), "0 1 1"); 764 | CHECK_TREE(t1, subtree_size(), "3 1 1"); 765 | CHECK_TREE(t2, data(), "5"); 766 | CHECK_TREE(t2, depth(), "1"); 767 | CHECK_TREE(t2, ply(), "0"); 768 | CHECK_TREE(t2, subtree_size(), "1"); 769 | 770 | // insert tree -> tree (empty) 771 | t1.clear(); 772 | t2.insert(t1); 773 | CHECK_TREE(t1, data(), ""); 774 | CHECK_TREE(t2, data(), ""); 775 | 776 | // insert tree -> tree (non-empty) 777 | t1.insert(2); 778 | t2.insert(t1); 779 | CHECK_TREE(t1, data(), "2"); 780 | CHECK_TREE(t2, data(), "2"); 781 | 782 | // insert tree -> node (empty) 783 | t1.clear(); 784 | t2.root().insert(t1); 785 | CHECK_TREE(t1, data(), ""); 786 | CHECK_TREE(t2, data(), "2"); 787 | 788 | // insert tree -> node (non-empty) 789 | t1.insert(2); 790 | t2.insert(1); 791 | t2.root().insert(t1); 792 | CHECK_TREE(t1, data(), "2"); 793 | CHECK_TREE(t2, data(), "1 2"); 794 | 795 | // node --> node 796 | t1.insert(2); 797 | t2.insert(1); 798 | t2.root().insert(t1.root()); 799 | CHECK_TREE(t1, data(), "2"); 800 | CHECK_TREE(t2, data(), "1 2"); 801 | CHECK_TREE(t2, depth(), "2 1"); 802 | CHECK_TREE(t2, ply(), "0 1"); 803 | CHECK_TREE(t2, subtree_size(), "2 1"); 804 | 805 | t1.insert(2); 806 | t1.root().insert(3); 807 | t1.root().insert(5); 808 | t2.insert(1); 809 | t2.root().insert(t1.root()); 810 | CHECK_TREE(t1, data(), "2 3 5"); 811 | CHECK_TREE(t2, data(), "1 2 3 5"); 812 | CHECK_TREE(t2, depth(), "3 2 1 1"); 813 | CHECK_TREE(t2, ply(), "0 1 2 2"); 814 | CHECK_TREE(t2, subtree_size(), "4 3 1 1"); 815 | 816 | t1.insert(2); 817 | t1.root().insert(3); 818 | t1.root().insert(5); 819 | t2.insert(1); 820 | t2.root().insert(t1.root()[1]); 821 | CHECK_TREE(t1, data(), "2 3 5"); 822 | CHECK_TREE(t1, depth(), "2 1 1"); 823 | CHECK_TREE(t1, ply(), "0 1 1"); 824 | CHECK_TREE(t1, subtree_size(), "3 1 1"); 825 | CHECK_TREE(t2, data(), "1 5"); 826 | CHECK_TREE(t2, depth(), "2 1"); 827 | CHECK_TREE(t2, ply(), "0 1"); 828 | CHECK_TREE(t2, subtree_size(), "2 1"); 829 | } 830 | 831 | 832 | BOOST_AUTO_TEST_CASE(node_op_equality) { 833 | tree t1; 834 | 835 | t1.insert(2); 836 | t1.root().insert(3); 837 | t1.root().insert(5); 838 | t1.root()[0].insert(7); 839 | t1.root()[1].insert(13); 840 | t1.root()[0].insert(11); 841 | t1.root()[1].insert(17); 842 | 843 | tree t2; 844 | 845 | t2.insert(2); 846 | t2.root().insert(3); 847 | t2.root().insert(5); 848 | t2.root()[0].insert(7); 849 | t2.root()[1].insert(13); 850 | t2.root()[0].insert(11); 851 | t2.root()[1].insert(17); 852 | 853 | BOOST_CHECK_EQUAL(t1.root() == t1.root(), true); 854 | BOOST_CHECK_EQUAL(t1.root()[0] == t1.root()[0], true); 855 | BOOST_CHECK_EQUAL(t1.root()[0][0] == t1.root()[0][0], true); 856 | 857 | BOOST_CHECK_EQUAL(t1.root() == t2.root(), true); 858 | BOOST_CHECK_EQUAL(t1.root()[0] == t2.root()[0], true); 859 | BOOST_CHECK_EQUAL(t1.root()[0][0] == t2.root()[0][0], true); 860 | 861 | BOOST_CHECK_EQUAL(t1.root()[0] == t2.root()[1], false); 862 | BOOST_CHECK_EQUAL(t1.root()[0][0] == t2.root()[0][1], false); 863 | } 864 | 865 | BOOST_AUTO_TEST_CASE(node_op_lessthan) { 866 | tree t1; 867 | tree t2; 868 | 869 | t1.insert(2); 870 | t2.insert(2); 871 | 872 | BOOST_CHECK_EQUAL(t1.root() < t2.root(), false); 873 | 874 | t2.root().data() = 3; 875 | BOOST_CHECK_EQUAL(t1.root() < t2.root(), true); 876 | 877 | t2.root().data() = 2; 878 | t1.root().insert(3); 879 | t1.root().insert(5); 880 | t2.root().insert(3); 881 | t2.root().insert(5); 882 | 883 | BOOST_CHECK_EQUAL(t1.root() < t2.root(), false); 884 | 885 | t2.root()[1].data() = 7; 886 | BOOST_CHECK_EQUAL(t1.root() < t2.root(), true); 887 | } 888 | 889 | 890 | BOOST_AUTO_TEST_CASE(node_derived_comp_ops) { 891 | tree t1; 892 | tree t2; 893 | 894 | t1.insert(2); 895 | t2.insert(2); 896 | BOOST_CHECK_EQUAL(t1.root() != t2.root(), false); 897 | BOOST_CHECK_EQUAL(t2.root() != t1.root(), false); 898 | BOOST_CHECK_EQUAL(t1.root() > t2.root(), false); 899 | BOOST_CHECK_EQUAL(t2.root() > t1.root(), false); 900 | BOOST_CHECK_EQUAL(t1.root() <= t2.root(), true); 901 | BOOST_CHECK_EQUAL(t2.root() <= t1.root(), true); 902 | BOOST_CHECK_EQUAL(t1.root() >= t2.root(), true); 903 | BOOST_CHECK_EQUAL(t2.root() >= t1.root(), true); 904 | 905 | t2.root().data() = 3; 906 | BOOST_CHECK_EQUAL(t1.root() != t2.root(), true); 907 | BOOST_CHECK_EQUAL(t2.root() != t1.root(), true); 908 | BOOST_CHECK_EQUAL(t1.root() > t2.root(), false); 909 | BOOST_CHECK_EQUAL(t2.root() > t1.root(), true); 910 | BOOST_CHECK_EQUAL(t1.root() <= t2.root(), true); 911 | BOOST_CHECK_EQUAL(t2.root() <= t1.root(), false); 912 | BOOST_CHECK_EQUAL(t1.root() >= t2.root(), false); 913 | BOOST_CHECK_EQUAL(t2.root() >= t1.root(), true); 914 | } 915 | 916 | 917 | BOOST_AUTO_TEST_CASE(tree_op_equality) { 918 | tree t1; 919 | tree t2; 920 | 921 | BOOST_CHECK_EQUAL(t1 == t2, true); 922 | 923 | t2.insert(2); 924 | BOOST_CHECK_EQUAL(t1 == t2, false); 925 | 926 | t1.insert(2); 927 | BOOST_CHECK_EQUAL(t1 == t2, true); 928 | 929 | t2.root().data() = 3; 930 | BOOST_CHECK_EQUAL(t1 == t2, false); 931 | } 932 | 933 | 934 | BOOST_AUTO_TEST_CASE(tree_op_lessthan) { 935 | tree t1; 936 | tree t2; 937 | BOOST_CHECK_EQUAL(t1 < t2, false); 938 | 939 | t2.insert(2); 940 | BOOST_CHECK_EQUAL(t1 < t2, true); 941 | BOOST_CHECK_EQUAL(t2 < t1, false); 942 | 943 | t1.insert(2); 944 | BOOST_CHECK_EQUAL(t1 < t2, false); 945 | 946 | t2.root().data() = 3; 947 | BOOST_CHECK_EQUAL(t1 < t2, true); 948 | BOOST_CHECK_EQUAL(t2 < t1, false); 949 | 950 | BOOST_CHECK_EQUAL(t1 < t1, false); 951 | } 952 | 953 | 954 | BOOST_AUTO_TEST_CASE(tree_derived_comp_ops) { 955 | tree t1; 956 | tree t2; 957 | 958 | t1.insert(2); 959 | t2.insert(2); 960 | BOOST_CHECK_EQUAL(t1 != t2, false); 961 | BOOST_CHECK_EQUAL(t2 != t1, false); 962 | BOOST_CHECK_EQUAL(t1 > t2, false); 963 | BOOST_CHECK_EQUAL(t2 > t1, false); 964 | BOOST_CHECK_EQUAL(t1 <= t2, true); 965 | BOOST_CHECK_EQUAL(t2 <= t1, true); 966 | BOOST_CHECK_EQUAL(t1 >= t2, true); 967 | BOOST_CHECK_EQUAL(t2 >= t1, true); 968 | 969 | t2.root().data() = 3; 970 | BOOST_CHECK_EQUAL(t1 != t2, true); 971 | BOOST_CHECK_EQUAL(t2 != t1, true); 972 | BOOST_CHECK_EQUAL(t1 > t2, false); 973 | BOOST_CHECK_EQUAL(t2 > t1, true); 974 | BOOST_CHECK_EQUAL(t1 <= t2, true); 975 | BOOST_CHECK_EQUAL(t2 <= t1, false); 976 | BOOST_CHECK_EQUAL(t1 >= t2, false); 977 | BOOST_CHECK_EQUAL(t2 >= t1, true); 978 | } 979 | 980 | 981 | BOOST_AUTO_TEST_CASE(tree_op_equal_lhs_n_rhs_e) { 982 | tree t1; 983 | t1.insert(2); 984 | t1.root().insert(3); 985 | 986 | tree t2; 987 | 988 | t1 = t2; 989 | 990 | BOOST_CHECK_EQUAL(t1.empty(), true); 991 | BOOST_CHECK_EQUAL(t2.empty(), true); 992 | 993 | CHECK_TREE(t1, data(), ""); 994 | } 995 | 996 | BOOST_AUTO_TEST_CASE(tree_op_equal_lhs_e_rhs_n) { 997 | tree t1; 998 | 999 | tree t2; 1000 | t2.insert(2); 1001 | t2.root().insert(3); 1002 | 1003 | t1 = t2; 1004 | 1005 | BOOST_CHECK_EQUAL(t1.empty(), false); 1006 | BOOST_CHECK_EQUAL(t2.empty(), false); 1007 | 1008 | CHECK_TREE(t1, data(), "2 3"); 1009 | CHECK_TREE(t1, ply(), "0 1"); 1010 | CHECK_TREE(t1, subtree_size(), "2 1"); 1011 | } 1012 | 1013 | BOOST_AUTO_TEST_CASE(tree_op_equal_lhs_n_rhs_n) { 1014 | tree t1; 1015 | t1.insert(31); 1016 | t1.root().insert(41); 1017 | 1018 | tree t2; 1019 | t2.insert(2); 1020 | t2.root().insert(3); 1021 | 1022 | t1 = t2; 1023 | 1024 | BOOST_CHECK_EQUAL(t1.empty(), false); 1025 | BOOST_CHECK_EQUAL(t2.empty(), false); 1026 | 1027 | CHECK_TREE(t1, data(), "2 3"); 1028 | CHECK_TREE(t1, ply(), "0 1"); 1029 | CHECK_TREE(t1, subtree_size(), "2 1"); 1030 | } 1031 | 1032 | 1033 | BOOST_AUTO_TEST_CASE(tree_swap) { 1034 | tree t1; 1035 | tree t2; 1036 | 1037 | t1.insert(2); 1038 | t2.insert(3); 1039 | 1040 | // method version 1041 | t1.swap(t2); 1042 | 1043 | CHECK_TREE(t1, data(), "3"); 1044 | CHECK_TREE(t2, data(), "2"); 1045 | 1046 | // function version 1047 | swap(t1, t2); 1048 | 1049 | CHECK_TREE(t1, data(), "2"); 1050 | CHECK_TREE(t2, data(), "3"); 1051 | } 1052 | 1053 | BOOST_AUTO_TEST_CASE(push_pop_back) { 1054 | tree t1; 1055 | t1.insert(2); 1056 | t1.root().push_back(3); 1057 | BOOST_CHECK_EQUAL(t1.root().back().data(), 3); 1058 | BOOST_CHECK_EQUAL(t1.root().front().data(), 3); 1059 | t1.root().push_back(5); 1060 | BOOST_CHECK_EQUAL(t1.root().back().data(), 5); 1061 | BOOST_CHECK_EQUAL(t1.root().front().data(), 3); 1062 | t1.root().push_back(7); 1063 | BOOST_CHECK_EQUAL(t1.root().back().data(), 7); 1064 | BOOST_CHECK_EQUAL(t1.root().front().data(), 3); 1065 | t1.root().pop_back(); 1066 | BOOST_CHECK_EQUAL(t1.root().back().data(), 5); 1067 | BOOST_CHECK_EQUAL(t1.root().front().data(), 3); 1068 | t1.root().pop_back(); 1069 | BOOST_CHECK_EQUAL(t1.root().back().data(), 3); 1070 | BOOST_CHECK_EQUAL(t1.root().front().data(), 3); 1071 | } 1072 | 1073 | BOOST_AUTO_TEST_CASE(random_access) { 1074 | tree t1; 1075 | typedef tree::node_type::iterator iterator; 1076 | 1077 | t1.insert(2); 1078 | t1.root().insert(3); 1079 | t1.root().insert(5); 1080 | t1.root().insert(7); 1081 | 1082 | CHECK_TREE(t1, data(), "2 3 5 7"); 1083 | 1084 | iterator j = t1.root().begin(); 1085 | BOOST_CHECK_EQUAL(j->data(), 3); 1086 | j++; 1087 | BOOST_CHECK_EQUAL(j->data(), 5); 1088 | j--; 1089 | BOOST_CHECK_EQUAL(j->data(), 3); 1090 | 1091 | j += 2; 1092 | BOOST_CHECK_EQUAL(j->data(), 7); 1093 | j -= 1; 1094 | BOOST_CHECK_EQUAL(j->data(), 5); 1095 | 1096 | BOOST_CHECK_EQUAL((j+1)->data(), 7); 1097 | BOOST_CHECK_EQUAL((j-1)->data(), 3); 1098 | 1099 | BOOST_CHECK_EQUAL((1+j)->data(), 7); 1100 | BOOST_CHECK_EQUAL((-1+j)->data(), 3); 1101 | 1102 | BOOST_CHECK_EQUAL((j+1)-(j-1), 2); 1103 | 1104 | BOOST_CHECK_EQUAL(j[1].data(), 7); 1105 | BOOST_CHECK_EQUAL(j[-1].data(), 3); 1106 | 1107 | BOOST_CHECK_EQUAL(j < j, false); 1108 | BOOST_CHECK_EQUAL(j < j+1, true); 1109 | 1110 | BOOST_CHECK_EQUAL(j <= j, true); 1111 | BOOST_CHECK_EQUAL(j <= j+1, true); 1112 | 1113 | BOOST_CHECK_EQUAL(j > j, false); 1114 | BOOST_CHECK_EQUAL(j > j-1, true); 1115 | 1116 | BOOST_CHECK_EQUAL(j >= j, true); 1117 | BOOST_CHECK_EQUAL(j >= j-1, true); 1118 | } 1119 | 1120 | BOOST_AUTO_TEST_CASE(sort_children) { 1121 | tree t1; 1122 | typedef tree::node_type::iterator iterator; 1123 | 1124 | t1.insert(2); 1125 | t1.root().push_back(3); 1126 | t1.root().push_back(7); 1127 | t1.root().push_back(5); 1128 | t1.root().push_back(13); 1129 | t1.root().push_back(11); 1130 | 1131 | CHECK_TREE(t1, data(), "2 3 7 5 13 11"); 1132 | 1133 | std::sort(t1.root().begin(), t1.root().end()); 1134 | 1135 | CHECK_TREE(t1, data(), "2 3 5 7 11 13"); 1136 | } 1137 | 1138 | BOOST_AUTO_TEST_SUITE_END() 1139 | -------------------------------------------------------------------------------- /tests/ut_vmap_iter.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "st_tree.h" 4 | using namespace st_tree; 5 | using st_tree::detail::valmap_iterator_dispatch; 6 | using st_tree::detail::dref_vmap; 7 | 8 | #include "ut_common.h" 9 | using std::vector; 10 | 11 | 12 | BOOST_AUTO_TEST_SUITE(ut_valmap_iterator_adaptor) 13 | 14 | template 15 | struct valmap_iterator_adaptor : public valmap_iterator_dispatch::adaptor_type { 16 | typedef typename valmap_iterator_dispatch::adaptor_type adaptor_type; 17 | 18 | typedef typename adaptor_type::iterator_category iterator_category; 19 | typedef typename adaptor_type::value_type value_type; 20 | typedef typename adaptor_type::difference_type difference_type; 21 | typedef typename adaptor_type::pointer pointer; 22 | typedef typename adaptor_type::reference reference; 23 | 24 | typedef Iterator base_iterator; 25 | 26 | valmap_iterator_adaptor() : adaptor_type() {} 27 | virtual ~valmap_iterator_adaptor() {} 28 | 29 | explicit valmap_iterator_adaptor(const valmap_iterator_adaptor& src) : adaptor_type(src) {} 30 | valmap_iterator_adaptor& operator=(const valmap_iterator_adaptor& src) { 31 | if (this == &src) return *this; 32 | adaptor_type::operator=(src); 33 | return *this; 34 | } 35 | 36 | operator base_iterator() const { return this->_base; } 37 | valmap_iterator_adaptor(const base_iterator& src) : adaptor_type(src) {} 38 | valmap_iterator_adaptor& operator=(const base_iterator& src) { 39 | adaptor_type::operator=(src); 40 | return *this; 41 | } 42 | }; 43 | 44 | BOOST_AUTO_TEST_CASE(dref_map) { 45 | int* t1 = new int(4); 46 | dref_vmap vmap; 47 | BOOST_CHECK_EQUAL(vmap(t1), *t1); 48 | delete t1; 49 | } 50 | 51 | BOOST_AUTO_TEST_CASE(dref_map_const) { 52 | const int* t1 = new int(4); 53 | dref_vmap vmap; 54 | BOOST_CHECK_EQUAL(vmap(t1), *t1); 55 | delete t1; 56 | } 57 | 58 | BOOST_AUTO_TEST_CASE(default_ctor) { 59 | typedef vector container_type; 60 | typedef container_type::iterator iterator; 61 | typedef valmap_iterator_adaptor > vm_iterator; 62 | 63 | vm_iterator j; 64 | } 65 | 66 | BOOST_AUTO_TEST_CASE(using_dref_map_int_pointer) { 67 | vector v; 68 | typedef vector::iterator iterator; 69 | typedef valmap_iterator_adaptor > vm_iterator; 70 | 71 | v.push_back(new int(1)); 72 | v.push_back(new int(2)); 73 | v.push_back(new int(3)); 74 | 75 | iterator r(v.begin()); 76 | for (vm_iterator j(v.begin()); j != vm_iterator(v.end()); ++j,++r) 77 | BOOST_CHECK_EQUAL(*j, **r); 78 | 79 | *(vm_iterator(v.begin())) = 42; 80 | r = v.begin(); 81 | for (vm_iterator j(v.begin()); j != vm_iterator(v.end()); ++j,++r) 82 | BOOST_CHECK_EQUAL(*j, **r); 83 | 84 | for (iterator j(v.begin()); j != v.end(); ++j) delete *j; 85 | } 86 | 87 | 88 | BOOST_AUTO_TEST_CASE(using_dref_map_int_pair_pointer) { 89 | vector*> v; 90 | typedef vector*>::iterator iterator; 91 | typedef valmap_iterator_adaptor > vm_iterator; 92 | 93 | v.push_back(new pair(1,4)); 94 | v.push_back(new pair(2,5)); 95 | v.push_back(new pair(3,6)); 96 | 97 | iterator r(v.begin()); 98 | for (vm_iterator j(v.begin()); j != vm_iterator(v.end()); ++j,++r) 99 | BOOST_CHECK(*j == **r); 100 | 101 | (vm_iterator(v.begin()))->first = 42; 102 | r = v.begin(); 103 | for (vm_iterator j(v.begin()); j != vm_iterator(v.end()); ++j,++r) 104 | BOOST_CHECK(*j == **r); 105 | 106 | for (iterator j(v.begin()); j != v.end(); ++j) delete *j; 107 | } 108 | 109 | BOOST_AUTO_TEST_SUITE_END() 110 | --------------------------------------------------------------------------------