@ladybugmem/icebug 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +14 -0
- package/binding.gyp +54 -0
- package/build/Release/.deps/Release/icebug.node.d +1 -0
- package/build/Release/.deps/Release/obj.target/icebug/src/addon.o.d +291 -0
- package/build/Release/icebug.node +0 -0
- package/build/Release/obj.target/icebug/src/addon.o +0 -0
- package/lib/index.d.ts +361 -0
- package/lib/index.js +102 -0
- package/package.json +42 -0
- package/src/addon.cpp +1253 -0
- package/vendor/include/networkit/GlobalState.hpp +86 -0
- package/vendor/include/networkit/Globals.hpp +41 -0
- package/vendor/include/networkit/algebraic/AlgebraicGlobals.hpp +27 -0
- package/vendor/include/networkit/algebraic/CSRGeneralMatrix.hpp +1292 -0
- package/vendor/include/networkit/algebraic/CSRMatrix.hpp +11 -0
- package/vendor/include/networkit/algebraic/DenseMatrix.hpp +537 -0
- package/vendor/include/networkit/algebraic/DynamicMatrix.hpp +514 -0
- package/vendor/include/networkit/algebraic/GraphBLAS.hpp +323 -0
- package/vendor/include/networkit/algebraic/MatrixTools.hpp +156 -0
- package/vendor/include/networkit/algebraic/Semirings.hpp +171 -0
- package/vendor/include/networkit/algebraic/SparseAccumulator.hpp +111 -0
- package/vendor/include/networkit/algebraic/Vector.hpp +371 -0
- package/vendor/include/networkit/algebraic/algorithms/AlgebraicBFS.hpp +72 -0
- package/vendor/include/networkit/algebraic/algorithms/AlgebraicBellmanFord.hpp +88 -0
- package/vendor/include/networkit/algebraic/algorithms/AlgebraicMatchingCoarsening.hpp +96 -0
- package/vendor/include/networkit/algebraic/algorithms/AlgebraicPageRank.hpp +145 -0
- package/vendor/include/networkit/algebraic/algorithms/AlgebraicSpanningEdgeCentrality.hpp +122 -0
- package/vendor/include/networkit/algebraic/algorithms/AlgebraicTriangleCounting.hpp +76 -0
- package/vendor/include/networkit/auxiliary/AlignedAllocator.hpp +113 -0
- package/vendor/include/networkit/auxiliary/ArrayTools.hpp +85 -0
- package/vendor/include/networkit/auxiliary/BloomFilter.hpp +70 -0
- package/vendor/include/networkit/auxiliary/BucketPQ.hpp +142 -0
- package/vendor/include/networkit/auxiliary/Enforce.hpp +117 -0
- package/vendor/include/networkit/auxiliary/FunctionTraits.hpp +74 -0
- package/vendor/include/networkit/auxiliary/HashUtils.hpp +28 -0
- package/vendor/include/networkit/auxiliary/IncrementalUniformRandomSelector.hpp +52 -0
- package/vendor/include/networkit/auxiliary/Log.hpp +119 -0
- package/vendor/include/networkit/auxiliary/MissingMath.hpp +48 -0
- package/vendor/include/networkit/auxiliary/Multiprecision.hpp +17 -0
- package/vendor/include/networkit/auxiliary/NumberParsing.hpp +307 -0
- package/vendor/include/networkit/auxiliary/NumericTools.hpp +57 -0
- package/vendor/include/networkit/auxiliary/Parallel.hpp +56 -0
- package/vendor/include/networkit/auxiliary/Parallelism.hpp +33 -0
- package/vendor/include/networkit/auxiliary/PrioQueue.hpp +252 -0
- package/vendor/include/networkit/auxiliary/Random.hpp +122 -0
- package/vendor/include/networkit/auxiliary/SetIntersector.hpp +72 -0
- package/vendor/include/networkit/auxiliary/SignalHandling.hpp +39 -0
- package/vendor/include/networkit/auxiliary/SortedList.hpp +128 -0
- package/vendor/include/networkit/auxiliary/SparseVector.hpp +215 -0
- package/vendor/include/networkit/auxiliary/SpinLock.hpp +23 -0
- package/vendor/include/networkit/auxiliary/StringBuilder.hpp +322 -0
- package/vendor/include/networkit/auxiliary/StringTools.hpp +76 -0
- package/vendor/include/networkit/auxiliary/TemplateUtils.hpp +76 -0
- package/vendor/include/networkit/auxiliary/Timer.hpp +145 -0
- package/vendor/include/networkit/auxiliary/VectorComparator.hpp +32 -0
- package/vendor/include/networkit/base/Algorithm.hpp +41 -0
- package/vendor/include/networkit/base/DynAlgorithm.hpp +31 -0
- package/vendor/include/networkit/centrality/ApproxBetweenness.hpp +62 -0
- package/vendor/include/networkit/centrality/ApproxCloseness.hpp +136 -0
- package/vendor/include/networkit/centrality/ApproxElectricalCloseness.hpp +156 -0
- package/vendor/include/networkit/centrality/ApproxGroupBetweenness.hpp +124 -0
- package/vendor/include/networkit/centrality/ApproxSpanningEdge.hpp +84 -0
- package/vendor/include/networkit/centrality/Betweenness.hpp +47 -0
- package/vendor/include/networkit/centrality/Centrality.hpp +98 -0
- package/vendor/include/networkit/centrality/Closeness.hpp +107 -0
- package/vendor/include/networkit/centrality/ComplexPaths.hpp +113 -0
- package/vendor/include/networkit/centrality/CoreDecomposition.hpp +161 -0
- package/vendor/include/networkit/centrality/DegreeCentrality.hpp +55 -0
- package/vendor/include/networkit/centrality/DynApproxBetweenness.hpp +95 -0
- package/vendor/include/networkit/centrality/DynBetweenness.hpp +99 -0
- package/vendor/include/networkit/centrality/DynBetweennessOneNode.hpp +98 -0
- package/vendor/include/networkit/centrality/DynKatzCentrality.hpp +115 -0
- package/vendor/include/networkit/centrality/DynTopHarmonicCloseness.hpp +223 -0
- package/vendor/include/networkit/centrality/EigenvectorCentrality.hpp +41 -0
- package/vendor/include/networkit/centrality/EstimateBetweenness.hpp +51 -0
- package/vendor/include/networkit/centrality/ForestCentrality.hpp +112 -0
- package/vendor/include/networkit/centrality/GedWalk.hpp +225 -0
- package/vendor/include/networkit/centrality/GroupCloseness.hpp +115 -0
- package/vendor/include/networkit/centrality/GroupClosenessGrowShrink.hpp +78 -0
- package/vendor/include/networkit/centrality/GroupClosenessLocalSearch.hpp +77 -0
- package/vendor/include/networkit/centrality/GroupClosenessLocalSwaps.hpp +106 -0
- package/vendor/include/networkit/centrality/GroupDegree.hpp +155 -0
- package/vendor/include/networkit/centrality/GroupHarmonicCloseness.hpp +83 -0
- package/vendor/include/networkit/centrality/HarmonicCloseness.hpp +48 -0
- package/vendor/include/networkit/centrality/KPathCentrality.hpp +52 -0
- package/vendor/include/networkit/centrality/KadabraBetweenness.hpp +242 -0
- package/vendor/include/networkit/centrality/KatzCentrality.hpp +62 -0
- package/vendor/include/networkit/centrality/LaplacianCentrality.hpp +44 -0
- package/vendor/include/networkit/centrality/LocalClusteringCoefficient.hpp +60 -0
- package/vendor/include/networkit/centrality/LocalPartitionCoverage.hpp +43 -0
- package/vendor/include/networkit/centrality/LocalSquareClusteringCoefficient.hpp +42 -0
- package/vendor/include/networkit/centrality/PageRank.hpp +101 -0
- package/vendor/include/networkit/centrality/PermanenceCentrality.hpp +48 -0
- package/vendor/include/networkit/centrality/Sfigality.hpp +45 -0
- package/vendor/include/networkit/centrality/SpanningEdgeCentrality.hpp +86 -0
- package/vendor/include/networkit/centrality/TopCloseness.hpp +136 -0
- package/vendor/include/networkit/centrality/TopHarmonicCloseness.hpp +151 -0
- package/vendor/include/networkit/clique/MaximalCliques.hpp +83 -0
- package/vendor/include/networkit/coarsening/ClusteringProjector.hpp +59 -0
- package/vendor/include/networkit/coarsening/CoarsenedGraphView.hpp +156 -0
- package/vendor/include/networkit/coarsening/GraphCoarsening.hpp +57 -0
- package/vendor/include/networkit/coarsening/MatchingCoarsening.hpp +43 -0
- package/vendor/include/networkit/coarsening/ParallelPartitionCoarsening.hpp +33 -0
- package/vendor/include/networkit/coarsening/ParallelPartitionCoarseningView.hpp +62 -0
- package/vendor/include/networkit/community/AdjustedRandMeasure.hpp +31 -0
- package/vendor/include/networkit/community/ClusteringGenerator.hpp +75 -0
- package/vendor/include/networkit/community/CommunityDetectionAlgorithm.hpp +58 -0
- package/vendor/include/networkit/community/Conductance.hpp +32 -0
- package/vendor/include/networkit/community/CoverF1Similarity.hpp +53 -0
- package/vendor/include/networkit/community/CoverHubDominance.hpp +38 -0
- package/vendor/include/networkit/community/Coverage.hpp +25 -0
- package/vendor/include/networkit/community/CutClustering.hpp +62 -0
- package/vendor/include/networkit/community/DissimilarityMeasure.hpp +31 -0
- package/vendor/include/networkit/community/DynamicNMIDistance.hpp +44 -0
- package/vendor/include/networkit/community/EdgeCut.hpp +24 -0
- package/vendor/include/networkit/community/GraphClusteringTools.hpp +103 -0
- package/vendor/include/networkit/community/GraphStructuralRandMeasure.hpp +28 -0
- package/vendor/include/networkit/community/HubDominance.hpp +46 -0
- package/vendor/include/networkit/community/IntrapartitionDensity.hpp +44 -0
- package/vendor/include/networkit/community/IsolatedInterpartitionConductance.hpp +40 -0
- package/vendor/include/networkit/community/IsolatedInterpartitionExpansion.hpp +40 -0
- package/vendor/include/networkit/community/JaccardMeasure.hpp +25 -0
- package/vendor/include/networkit/community/LFM.hpp +49 -0
- package/vendor/include/networkit/community/LPDegreeOrdered.hpp +48 -0
- package/vendor/include/networkit/community/LocalCommunityEvaluation.hpp +100 -0
- package/vendor/include/networkit/community/LocalCoverEvaluation.hpp +31 -0
- package/vendor/include/networkit/community/LocalPartitionEvaluation.hpp +31 -0
- package/vendor/include/networkit/community/LouvainMapEquation.hpp +135 -0
- package/vendor/include/networkit/community/Modularity.hpp +54 -0
- package/vendor/include/networkit/community/NMIDistance.hpp +28 -0
- package/vendor/include/networkit/community/NodeStructuralRandMeasure.hpp +27 -0
- package/vendor/include/networkit/community/OverlappingCommunityDetectionAlgorithm.hpp +51 -0
- package/vendor/include/networkit/community/OverlappingNMIDistance.hpp +175 -0
- package/vendor/include/networkit/community/PLM.hpp +89 -0
- package/vendor/include/networkit/community/PLP.hpp +83 -0
- package/vendor/include/networkit/community/ParallelAgglomerativeClusterer.hpp +37 -0
- package/vendor/include/networkit/community/ParallelLeiden.hpp +96 -0
- package/vendor/include/networkit/community/ParallelLeidenView.hpp +138 -0
- package/vendor/include/networkit/community/PartitionFragmentation.hpp +30 -0
- package/vendor/include/networkit/community/PartitionHubDominance.hpp +37 -0
- package/vendor/include/networkit/community/PartitionIntersection.hpp +25 -0
- package/vendor/include/networkit/community/QualityMeasure.hpp +27 -0
- package/vendor/include/networkit/community/SampledGraphStructuralRandMeasure.hpp +40 -0
- package/vendor/include/networkit/community/SampledNodeStructuralRandMeasure.hpp +40 -0
- package/vendor/include/networkit/community/StablePartitionNodes.hpp +48 -0
- package/vendor/include/networkit/components/BiconnectedComponents.hpp +116 -0
- package/vendor/include/networkit/components/ComponentDecomposition.hpp +72 -0
- package/vendor/include/networkit/components/ConnectedComponents.hpp +55 -0
- package/vendor/include/networkit/components/DynConnectedComponents.hpp +71 -0
- package/vendor/include/networkit/components/DynWeaklyConnectedComponents.hpp +73 -0
- package/vendor/include/networkit/components/ParallelConnectedComponents.hpp +44 -0
- package/vendor/include/networkit/components/RandomSpanningForest.hpp +36 -0
- package/vendor/include/networkit/components/StronglyConnectedComponents.hpp +50 -0
- package/vendor/include/networkit/components/WeaklyConnectedComponents.hpp +59 -0
- package/vendor/include/networkit/correlation/Assortativity.hpp +64 -0
- package/vendor/include/networkit/distance/APSP.hpp +70 -0
- package/vendor/include/networkit/distance/AStar.hpp +68 -0
- package/vendor/include/networkit/distance/AStarGeneral.hpp +110 -0
- package/vendor/include/networkit/distance/AdamicAdarDistance.hpp +52 -0
- package/vendor/include/networkit/distance/AffectedNodes.hpp +130 -0
- package/vendor/include/networkit/distance/AlgebraicDistance.hpp +63 -0
- package/vendor/include/networkit/distance/BFS.hpp +43 -0
- package/vendor/include/networkit/distance/BidirectionalBFS.hpp +51 -0
- package/vendor/include/networkit/distance/BidirectionalDijkstra.hpp +69 -0
- package/vendor/include/networkit/distance/CommuteTimeDistance.hpp +89 -0
- package/vendor/include/networkit/distance/Diameter.hpp +97 -0
- package/vendor/include/networkit/distance/Dijkstra.hpp +50 -0
- package/vendor/include/networkit/distance/DynAPSP.hpp +67 -0
- package/vendor/include/networkit/distance/DynBFS.hpp +56 -0
- package/vendor/include/networkit/distance/DynDijkstra.hpp +57 -0
- package/vendor/include/networkit/distance/DynPrunedLandmarkLabeling.hpp +67 -0
- package/vendor/include/networkit/distance/DynSSSP.hpp +87 -0
- package/vendor/include/networkit/distance/Eccentricity.hpp +32 -0
- package/vendor/include/networkit/distance/EffectiveDiameter.hpp +47 -0
- package/vendor/include/networkit/distance/EffectiveDiameterApproximation.hpp +57 -0
- package/vendor/include/networkit/distance/FloydWarshall.hpp +93 -0
- package/vendor/include/networkit/distance/GraphDistance.hpp +49 -0
- package/vendor/include/networkit/distance/HopPlotApproximation.hpp +62 -0
- package/vendor/include/networkit/distance/IncompleteDijkstra.hpp +66 -0
- package/vendor/include/networkit/distance/IncompleteSSSP.hpp +41 -0
- package/vendor/include/networkit/distance/JaccardDistance.hpp +57 -0
- package/vendor/include/networkit/distance/MultiTargetBFS.hpp +32 -0
- package/vendor/include/networkit/distance/MultiTargetDijkstra.hpp +40 -0
- package/vendor/include/networkit/distance/NeighborhoodFunction.hpp +47 -0
- package/vendor/include/networkit/distance/NeighborhoodFunctionApproximation.hpp +56 -0
- package/vendor/include/networkit/distance/NeighborhoodFunctionHeuristic.hpp +56 -0
- package/vendor/include/networkit/distance/NodeDistance.hpp +54 -0
- package/vendor/include/networkit/distance/PrunedLandmarkLabeling.hpp +76 -0
- package/vendor/include/networkit/distance/ReverseBFS.hpp +46 -0
- package/vendor/include/networkit/distance/SPSP.hpp +143 -0
- package/vendor/include/networkit/distance/SSSP.hpp +216 -0
- package/vendor/include/networkit/distance/STSP.hpp +193 -0
- package/vendor/include/networkit/distance/Volume.hpp +66 -0
- package/vendor/include/networkit/dynamics/DGSStreamParser.hpp +40 -0
- package/vendor/include/networkit/dynamics/DGSWriter.hpp +30 -0
- package/vendor/include/networkit/dynamics/GraphDifference.hpp +110 -0
- package/vendor/include/networkit/dynamics/GraphEvent.hpp +55 -0
- package/vendor/include/networkit/dynamics/GraphEventHandler.hpp +39 -0
- package/vendor/include/networkit/dynamics/GraphEventProxy.hpp +55 -0
- package/vendor/include/networkit/dynamics/GraphUpdater.hpp +38 -0
- package/vendor/include/networkit/edgescores/ChibaNishizekiQuadrangleEdgeScore.hpp +26 -0
- package/vendor/include/networkit/edgescores/ChibaNishizekiTriangleEdgeScore.hpp +33 -0
- package/vendor/include/networkit/edgescores/EdgeScore.hpp +50 -0
- package/vendor/include/networkit/edgescores/EdgeScoreAsWeight.hpp +33 -0
- package/vendor/include/networkit/edgescores/EdgeScoreBlender.hpp +33 -0
- package/vendor/include/networkit/edgescores/EdgeScoreLinearizer.hpp +32 -0
- package/vendor/include/networkit/edgescores/EdgeScoreNormalizer.hpp +35 -0
- package/vendor/include/networkit/edgescores/GeometricMeanScore.hpp +29 -0
- package/vendor/include/networkit/edgescores/PrefixJaccardScore.hpp +23 -0
- package/vendor/include/networkit/edgescores/TriangleEdgeScore.hpp +39 -0
- package/vendor/include/networkit/embedding/Node2Vec.hpp +83 -0
- package/vendor/include/networkit/flow/EdmondsKarp.hpp +112 -0
- package/vendor/include/networkit/generators/BarabasiAlbertGenerator.hpp +87 -0
- package/vendor/include/networkit/generators/ChungLuGenerator.hpp +46 -0
- package/vendor/include/networkit/generators/ChungLuGeneratorAlamEtAl.hpp +63 -0
- package/vendor/include/networkit/generators/ClusteredRandomGraphGenerator.hpp +56 -0
- package/vendor/include/networkit/generators/ConfigurationModel.hpp +36 -0
- package/vendor/include/networkit/generators/DorogovtsevMendesGenerator.hpp +33 -0
- package/vendor/include/networkit/generators/DynamicBarabasiAlbertGenerator.hpp +33 -0
- package/vendor/include/networkit/generators/DynamicDGSParser.hpp +51 -0
- package/vendor/include/networkit/generators/DynamicDorogovtsevMendesGenerator.hpp +34 -0
- package/vendor/include/networkit/generators/DynamicForestFireGenerator.hpp +55 -0
- package/vendor/include/networkit/generators/DynamicGraphGenerator.hpp +40 -0
- package/vendor/include/networkit/generators/DynamicGraphSource.hpp +79 -0
- package/vendor/include/networkit/generators/DynamicHyperbolicGenerator.hpp +143 -0
- package/vendor/include/networkit/generators/DynamicPathGenerator.hpp +26 -0
- package/vendor/include/networkit/generators/DynamicPubWebGenerator.hpp +54 -0
- package/vendor/include/networkit/generators/EdgeSwitchingMarkovChainGenerator.hpp +65 -0
- package/vendor/include/networkit/generators/ErdosRenyiEnumerator.hpp +318 -0
- package/vendor/include/networkit/generators/ErdosRenyiGenerator.hpp +56 -0
- package/vendor/include/networkit/generators/HavelHakimiGenerator.hpp +48 -0
- package/vendor/include/networkit/generators/HyperbolicGenerator.hpp +236 -0
- package/vendor/include/networkit/generators/LFRGenerator.hpp +175 -0
- package/vendor/include/networkit/generators/MocnikGenerator.hpp +147 -0
- package/vendor/include/networkit/generators/MocnikGeneratorBasic.hpp +58 -0
- package/vendor/include/networkit/generators/PowerlawDegreeSequence.hpp +128 -0
- package/vendor/include/networkit/generators/PubWebGenerator.hpp +94 -0
- package/vendor/include/networkit/generators/RegularRingLatticeGenerator.hpp +37 -0
- package/vendor/include/networkit/generators/RmatGenerator.hpp +67 -0
- package/vendor/include/networkit/generators/StaticDegreeSequenceGenerator.hpp +42 -0
- package/vendor/include/networkit/generators/StaticGraphGenerator.hpp +30 -0
- package/vendor/include/networkit/generators/StochasticBlockmodel.hpp +41 -0
- package/vendor/include/networkit/generators/WattsStrogatzGenerator.hpp +43 -0
- package/vendor/include/networkit/generators/quadtree/QuadNode.hpp +857 -0
- package/vendor/include/networkit/generators/quadtree/QuadNodeCartesianEuclid.hpp +587 -0
- package/vendor/include/networkit/generators/quadtree/QuadNodePolarEuclid.hpp +726 -0
- package/vendor/include/networkit/generators/quadtree/Quadtree.hpp +232 -0
- package/vendor/include/networkit/generators/quadtree/QuadtreeCartesianEuclid.hpp +149 -0
- package/vendor/include/networkit/generators/quadtree/QuadtreePolarEuclid.hpp +143 -0
- package/vendor/include/networkit/geometric/HyperbolicSpace.hpp +248 -0
- package/vendor/include/networkit/geometric/Point2DWithIndex.hpp +145 -0
- package/vendor/include/networkit/global/ClusteringCoefficient.hpp +42 -0
- package/vendor/include/networkit/global/GlobalClusteringCoefficient.hpp +24 -0
- package/vendor/include/networkit/graph/Attributes.hpp +568 -0
- package/vendor/include/networkit/graph/BFS.hpp +111 -0
- package/vendor/include/networkit/graph/DFS.hpp +71 -0
- package/vendor/include/networkit/graph/Dijkstra.hpp +83 -0
- package/vendor/include/networkit/graph/EdgeIterators.hpp +171 -0
- package/vendor/include/networkit/graph/Graph.hpp +2083 -0
- package/vendor/include/networkit/graph/GraphBuilder.hpp +289 -0
- package/vendor/include/networkit/graph/GraphR.hpp +133 -0
- package/vendor/include/networkit/graph/GraphTools.hpp +589 -0
- package/vendor/include/networkit/graph/GraphW.hpp +1236 -0
- package/vendor/include/networkit/graph/KruskalMSF.hpp +50 -0
- package/vendor/include/networkit/graph/NeighborIterators.hpp +163 -0
- package/vendor/include/networkit/graph/NodeIterators.hpp +127 -0
- package/vendor/include/networkit/graph/PrimMSF.hpp +66 -0
- package/vendor/include/networkit/graph/RandomMaximumSpanningForest.hpp +133 -0
- package/vendor/include/networkit/graph/SpanningForest.hpp +41 -0
- package/vendor/include/networkit/graph/TopologicalSort.hpp +87 -0
- package/vendor/include/networkit/graph/UnionMaximumSpanningForest.hpp +126 -0
- package/vendor/include/networkit/graph/test/GraphBuilderBenchmark.hpp +68 -0
- package/vendor/include/networkit/independentset/IndependentSetFinder.hpp +44 -0
- package/vendor/include/networkit/independentset/Luby.hpp +27 -0
- package/vendor/include/networkit/io/BinaryEdgeListPartitionReader.hpp +45 -0
- package/vendor/include/networkit/io/BinaryEdgeListPartitionWriter.hpp +47 -0
- package/vendor/include/networkit/io/BinaryPartitionReader.hpp +41 -0
- package/vendor/include/networkit/io/BinaryPartitionWriter.hpp +44 -0
- package/vendor/include/networkit/io/CoverReader.hpp +27 -0
- package/vendor/include/networkit/io/CoverWriter.hpp +21 -0
- package/vendor/include/networkit/io/DGSReader.hpp +39 -0
- package/vendor/include/networkit/io/DibapGraphReader.hpp +43 -0
- package/vendor/include/networkit/io/DotGraphWriter.hpp +39 -0
- package/vendor/include/networkit/io/DotPartitionWriter.hpp +23 -0
- package/vendor/include/networkit/io/DynamicGraphReader.hpp +29 -0
- package/vendor/include/networkit/io/EdgeListCoverReader.hpp +35 -0
- package/vendor/include/networkit/io/EdgeListPartitionReader.hpp +43 -0
- package/vendor/include/networkit/io/EdgeListReader.hpp +61 -0
- package/vendor/include/networkit/io/EdgeListWriter.hpp +48 -0
- package/vendor/include/networkit/io/GMLGraphReader.hpp +33 -0
- package/vendor/include/networkit/io/GMLGraphWriter.hpp +33 -0
- package/vendor/include/networkit/io/GraphIO.hpp +52 -0
- package/vendor/include/networkit/io/GraphReader.hpp +40 -0
- package/vendor/include/networkit/io/GraphToolBinaryReader.hpp +71 -0
- package/vendor/include/networkit/io/GraphToolBinaryWriter.hpp +61 -0
- package/vendor/include/networkit/io/GraphWriter.hpp +27 -0
- package/vendor/include/networkit/io/KONECTGraphReader.hpp +44 -0
- package/vendor/include/networkit/io/LineFileReader.hpp +42 -0
- package/vendor/include/networkit/io/METISGraphReader.hpp +36 -0
- package/vendor/include/networkit/io/METISGraphWriter.hpp +29 -0
- package/vendor/include/networkit/io/METISParser.hpp +63 -0
- package/vendor/include/networkit/io/MTXGraphReader.hpp +31 -0
- package/vendor/include/networkit/io/MTXParser.hpp +87 -0
- package/vendor/include/networkit/io/MatrixMarketReader.hpp +33 -0
- package/vendor/include/networkit/io/MatrixReader.hpp +33 -0
- package/vendor/include/networkit/io/MemoryMappedFile.hpp +80 -0
- package/vendor/include/networkit/io/NetworkitBinaryGraph.hpp +144 -0
- package/vendor/include/networkit/io/NetworkitBinaryReader.hpp +50 -0
- package/vendor/include/networkit/io/NetworkitBinaryWriter.hpp +71 -0
- package/vendor/include/networkit/io/PartitionReader.hpp +34 -0
- package/vendor/include/networkit/io/PartitionWriter.hpp +31 -0
- package/vendor/include/networkit/io/RBGraphReader.hpp +37 -0
- package/vendor/include/networkit/io/RBMatrixReader.hpp +49 -0
- package/vendor/include/networkit/io/RasterReader.hpp +40 -0
- package/vendor/include/networkit/io/SNAPEdgeListPartitionReader.hpp +28 -0
- package/vendor/include/networkit/io/SNAPGraphReader.hpp +53 -0
- package/vendor/include/networkit/io/SNAPGraphWriter.hpp +53 -0
- package/vendor/include/networkit/io/ThrillGraphBinaryReader.hpp +44 -0
- package/vendor/include/networkit/io/ThrillGraphBinaryWriter.hpp +27 -0
- package/vendor/include/networkit/layout/LayoutAlgorithm.hpp +39 -0
- package/vendor/include/networkit/linkprediction/AdamicAdarIndex.hpp +37 -0
- package/vendor/include/networkit/linkprediction/AdjustedRandIndex.hpp +36 -0
- package/vendor/include/networkit/linkprediction/AlgebraicDistanceIndex.hpp +70 -0
- package/vendor/include/networkit/linkprediction/CommonNeighborsIndex.hpp +39 -0
- package/vendor/include/networkit/linkprediction/EvaluationMetric.hpp +135 -0
- package/vendor/include/networkit/linkprediction/JaccardIndex.hpp +44 -0
- package/vendor/include/networkit/linkprediction/KatzIndex.hpp +84 -0
- package/vendor/include/networkit/linkprediction/LinkPredictor.hpp +98 -0
- package/vendor/include/networkit/linkprediction/LinkThresholder.hpp +56 -0
- package/vendor/include/networkit/linkprediction/MissingLinksFinder.hpp +60 -0
- package/vendor/include/networkit/linkprediction/NeighborhoodDistanceIndex.hpp +42 -0
- package/vendor/include/networkit/linkprediction/NeighborhoodUtility.hpp +54 -0
- package/vendor/include/networkit/linkprediction/NeighborsMeasureIndex.hpp +48 -0
- package/vendor/include/networkit/linkprediction/PrecisionRecallMetric.hpp +40 -0
- package/vendor/include/networkit/linkprediction/PredictionsSorter.hpp +66 -0
- package/vendor/include/networkit/linkprediction/PreferentialAttachmentIndex.hpp +37 -0
- package/vendor/include/networkit/linkprediction/ROCMetric.hpp +39 -0
- package/vendor/include/networkit/linkprediction/RandomLinkSampler.hpp +47 -0
- package/vendor/include/networkit/linkprediction/ResourceAllocationIndex.hpp +38 -0
- package/vendor/include/networkit/linkprediction/SameCommunityIndex.hpp +50 -0
- package/vendor/include/networkit/linkprediction/TotalNeighborsIndex.hpp +39 -0
- package/vendor/include/networkit/linkprediction/UDegreeIndex.hpp +35 -0
- package/vendor/include/networkit/linkprediction/VDegreeIndex.hpp +35 -0
- package/vendor/include/networkit/matching/BMatcher.hpp +52 -0
- package/vendor/include/networkit/matching/BMatching.hpp +115 -0
- package/vendor/include/networkit/matching/BSuitorMatcher.hpp +170 -0
- package/vendor/include/networkit/matching/DynamicBSuitorMatcher.hpp +78 -0
- package/vendor/include/networkit/matching/LocalMaxMatcher.hpp +35 -0
- package/vendor/include/networkit/matching/Matcher.hpp +55 -0
- package/vendor/include/networkit/matching/Matching.hpp +111 -0
- package/vendor/include/networkit/matching/PathGrowingMatcher.hpp +46 -0
- package/vendor/include/networkit/matching/SuitorMatcher.hpp +62 -0
- package/vendor/include/networkit/numerics/ConjugateGradient.hpp +163 -0
- package/vendor/include/networkit/numerics/GaussSeidelRelaxation.hpp +99 -0
- package/vendor/include/networkit/numerics/LAMG/LAMGSettings.hpp +70 -0
- package/vendor/include/networkit/numerics/LAMG/Lamg.hpp +460 -0
- package/vendor/include/networkit/numerics/LAMG/Level/EliminationStage.hpp +47 -0
- package/vendor/include/networkit/numerics/LAMG/Level/Level.hpp +56 -0
- package/vendor/include/networkit/numerics/LAMG/Level/LevelAggregation.hpp +52 -0
- package/vendor/include/networkit/numerics/LAMG/Level/LevelElimination.hpp +133 -0
- package/vendor/include/networkit/numerics/LAMG/Level/LevelFinest.hpp +28 -0
- package/vendor/include/networkit/numerics/LAMG/LevelHierarchy.hpp +165 -0
- package/vendor/include/networkit/numerics/LAMG/MultiLevelSetup.hpp +1090 -0
- package/vendor/include/networkit/numerics/LAMG/SolverLamg.hpp +316 -0
- package/vendor/include/networkit/numerics/LinearSolver.hpp +151 -0
- package/vendor/include/networkit/numerics/Preconditioner/DiagonalPreconditioner.hpp +61 -0
- package/vendor/include/networkit/numerics/Preconditioner/IdentityPreconditioner.hpp +36 -0
- package/vendor/include/networkit/numerics/Smoother.hpp +37 -0
- package/vendor/include/networkit/overlap/HashingOverlapper.hpp +28 -0
- package/vendor/include/networkit/overlap/Overlapper.hpp +27 -0
- package/vendor/include/networkit/planarity/LeftRightPlanarityCheck.hpp +113 -0
- package/vendor/include/networkit/randomization/Curveball.hpp +49 -0
- package/vendor/include/networkit/randomization/CurveballGlobalTradeGenerator.hpp +39 -0
- package/vendor/include/networkit/randomization/CurveballUniformTradeGenerator.hpp +39 -0
- package/vendor/include/networkit/randomization/DegreePreservingShuffle.hpp +82 -0
- package/vendor/include/networkit/randomization/EdgeSwitching.hpp +157 -0
- package/vendor/include/networkit/randomization/GlobalCurveball.hpp +69 -0
- package/vendor/include/networkit/randomization/GlobalTradeSequence.hpp +303 -0
- package/vendor/include/networkit/reachability/AllSimplePaths.hpp +122 -0
- package/vendor/include/networkit/reachability/ReachableNodes.hpp +83 -0
- package/vendor/include/networkit/scd/ApproximatePageRank.hpp +51 -0
- package/vendor/include/networkit/scd/CliqueDetect.hpp +55 -0
- package/vendor/include/networkit/scd/CombinedSCD.hpp +51 -0
- package/vendor/include/networkit/scd/GCE.hpp +42 -0
- package/vendor/include/networkit/scd/LFMLocal.hpp +54 -0
- package/vendor/include/networkit/scd/LocalT.hpp +40 -0
- package/vendor/include/networkit/scd/LocalTightnessExpansion.hpp +46 -0
- package/vendor/include/networkit/scd/PageRankNibble.hpp +55 -0
- package/vendor/include/networkit/scd/RandomBFS.hpp +33 -0
- package/vendor/include/networkit/scd/SCDGroundTruthComparison.hpp +121 -0
- package/vendor/include/networkit/scd/SelectiveCommunityDetector.hpp +76 -0
- package/vendor/include/networkit/scd/SetConductance.hpp +47 -0
- package/vendor/include/networkit/scd/TCE.hpp +41 -0
- package/vendor/include/networkit/scd/TwoPhaseL.hpp +40 -0
- package/vendor/include/networkit/scoring/EdgeScoring.hpp +44 -0
- package/vendor/include/networkit/scoring/ModularityScoring.hpp +79 -0
- package/vendor/include/networkit/simulation/EpidemicSimulationSEIR.hpp +59 -0
- package/vendor/include/networkit/sparsification/ChanceCorrectedTriangleScore.hpp +28 -0
- package/vendor/include/networkit/sparsification/ForestFireScore.hpp +34 -0
- package/vendor/include/networkit/sparsification/GlobalThresholdFilter.hpp +40 -0
- package/vendor/include/networkit/sparsification/LocalDegreeScore.hpp +30 -0
- package/vendor/include/networkit/sparsification/LocalFilterScore.hpp +124 -0
- package/vendor/include/networkit/sparsification/LocalSimilarityScore.hpp +63 -0
- package/vendor/include/networkit/sparsification/MultiscaleScore.hpp +38 -0
- package/vendor/include/networkit/sparsification/RandomEdgeScore.hpp +33 -0
- package/vendor/include/networkit/sparsification/RandomNodeEdgeScore.hpp +29 -0
- package/vendor/include/networkit/sparsification/SCANStructuralSimilarityScore.hpp +23 -0
- package/vendor/include/networkit/sparsification/SimmelianOverlapScore.hpp +35 -0
- package/vendor/include/networkit/sparsification/SimmelianScore.hpp +92 -0
- package/vendor/include/networkit/sparsification/Sparsifiers.hpp +166 -0
- package/vendor/include/networkit/structures/Cover.hpp +248 -0
- package/vendor/include/networkit/structures/LocalCommunity.hpp +363 -0
- package/vendor/include/networkit/structures/Partition.hpp +335 -0
- package/vendor/include/networkit/structures/UnionFind.hpp +66 -0
- package/vendor/include/networkit/viz/GraphLayoutAlgorithm.hpp +157 -0
- package/vendor/include/networkit/viz/MaxentStress.hpp +346 -0
- package/vendor/include/networkit/viz/Octree.hpp +428 -0
- package/vendor/include/networkit/viz/PivotMDS.hpp +63 -0
- package/vendor/include/networkit/viz/Point.hpp +415 -0
- package/vendor/include/networkit/viz/PostscriptWriter.hpp +78 -0
- package/vendor/include/tlx/algorithm/exclusive_scan.hpp +56 -0
- package/vendor/include/tlx/algorithm/is_sorted_cmp.hpp +56 -0
- package/vendor/include/tlx/algorithm/merge_advance.hpp +177 -0
- package/vendor/include/tlx/algorithm/merge_combine.hpp +76 -0
- package/vendor/include/tlx/algorithm/multisequence_partition.hpp +346 -0
- package/vendor/include/tlx/algorithm/multisequence_selection.hpp +351 -0
- package/vendor/include/tlx/algorithm/multiway_merge.hpp +1385 -0
- package/vendor/include/tlx/algorithm/multiway_merge_splitting.hpp +257 -0
- package/vendor/include/tlx/algorithm/parallel_multiway_merge.hpp +408 -0
- package/vendor/include/tlx/algorithm/random_bipartition_shuffle.hpp +116 -0
- package/vendor/include/tlx/algorithm.hpp +36 -0
- package/vendor/include/tlx/allocator_base.hpp +100 -0
- package/vendor/include/tlx/backtrace.hpp +54 -0
- package/vendor/include/tlx/cmdline_parser.hpp +498 -0
- package/vendor/include/tlx/container/btree.hpp +3977 -0
- package/vendor/include/tlx/container/btree_map.hpp +634 -0
- package/vendor/include/tlx/container/btree_multimap.hpp +627 -0
- package/vendor/include/tlx/container/btree_multiset.hpp +612 -0
- package/vendor/include/tlx/container/btree_set.hpp +612 -0
- package/vendor/include/tlx/container/d_ary_addressable_int_heap.hpp +416 -0
- package/vendor/include/tlx/container/d_ary_heap.hpp +311 -0
- package/vendor/include/tlx/container/loser_tree.hpp +1009 -0
- package/vendor/include/tlx/container/lru_cache.hpp +319 -0
- package/vendor/include/tlx/container/radix_heap.hpp +735 -0
- package/vendor/include/tlx/container/ring_buffer.hpp +428 -0
- package/vendor/include/tlx/container/simple_vector.hpp +304 -0
- package/vendor/include/tlx/container/splay_tree.hpp +399 -0
- package/vendor/include/tlx/container/string_view.hpp +805 -0
- package/vendor/include/tlx/container.hpp +40 -0
- package/vendor/include/tlx/counting_ptr.hpp +522 -0
- package/vendor/include/tlx/define/attribute_always_inline.hpp +34 -0
- package/vendor/include/tlx/define/attribute_fallthrough.hpp +36 -0
- package/vendor/include/tlx/define/attribute_format_printf.hpp +34 -0
- package/vendor/include/tlx/define/attribute_packed.hpp +34 -0
- package/vendor/include/tlx/define/attribute_warn_unused_result.hpp +34 -0
- package/vendor/include/tlx/define/constexpr.hpp +31 -0
- package/vendor/include/tlx/define/deprecated.hpp +39 -0
- package/vendor/include/tlx/define/endian.hpp +49 -0
- package/vendor/include/tlx/define/likely.hpp +33 -0
- package/vendor/include/tlx/define/visibility_hidden.hpp +34 -0
- package/vendor/include/tlx/define.hpp +36 -0
- package/vendor/include/tlx/delegate.hpp +524 -0
- package/vendor/include/tlx/die/core.hpp +311 -0
- package/vendor/include/tlx/die.hpp +106 -0
- package/vendor/include/tlx/digest/md5.hpp +81 -0
- package/vendor/include/tlx/digest/sha1.hpp +81 -0
- package/vendor/include/tlx/digest/sha256.hpp +81 -0
- package/vendor/include/tlx/digest/sha512.hpp +81 -0
- package/vendor/include/tlx/digest.hpp +30 -0
- package/vendor/include/tlx/logger/all.hpp +33 -0
- package/vendor/include/tlx/logger/array.hpp +43 -0
- package/vendor/include/tlx/logger/core.hpp +287 -0
- package/vendor/include/tlx/logger/deque.hpp +42 -0
- package/vendor/include/tlx/logger/map.hpp +65 -0
- package/vendor/include/tlx/logger/set.hpp +60 -0
- package/vendor/include/tlx/logger/tuple.hpp +66 -0
- package/vendor/include/tlx/logger/unordered_map.hpp +68 -0
- package/vendor/include/tlx/logger/unordered_set.hpp +64 -0
- package/vendor/include/tlx/logger/wrap_unprintable.hpp +75 -0
- package/vendor/include/tlx/logger.hpp +44 -0
- package/vendor/include/tlx/math/abs_diff.hpp +35 -0
- package/vendor/include/tlx/math/aggregate.hpp +231 -0
- package/vendor/include/tlx/math/aggregate_min_max.hpp +116 -0
- package/vendor/include/tlx/math/bswap.hpp +148 -0
- package/vendor/include/tlx/math/bswap_be.hpp +79 -0
- package/vendor/include/tlx/math/bswap_le.hpp +79 -0
- package/vendor/include/tlx/math/clz.hpp +174 -0
- package/vendor/include/tlx/math/ctz.hpp +174 -0
- package/vendor/include/tlx/math/div_ceil.hpp +36 -0
- package/vendor/include/tlx/math/ffs.hpp +123 -0
- package/vendor/include/tlx/math/integer_log2.hpp +189 -0
- package/vendor/include/tlx/math/is_power_of_two.hpp +74 -0
- package/vendor/include/tlx/math/polynomial_regression.hpp +243 -0
- package/vendor/include/tlx/math/popcount.hpp +173 -0
- package/vendor/include/tlx/math/power_to_the.hpp +44 -0
- package/vendor/include/tlx/math/rol.hpp +112 -0
- package/vendor/include/tlx/math/ror.hpp +112 -0
- package/vendor/include/tlx/math/round_to_power_of_two.hpp +121 -0
- package/vendor/include/tlx/math/round_up.hpp +36 -0
- package/vendor/include/tlx/math/sgn.hpp +38 -0
- package/vendor/include/tlx/math.hpp +46 -0
- package/vendor/include/tlx/meta/apply_tuple.hpp +55 -0
- package/vendor/include/tlx/meta/call_for_range.hpp +78 -0
- package/vendor/include/tlx/meta/call_foreach.hpp +60 -0
- package/vendor/include/tlx/meta/call_foreach_tuple.hpp +60 -0
- package/vendor/include/tlx/meta/call_foreach_tuple_with_index.hpp +61 -0
- package/vendor/include/tlx/meta/call_foreach_with_index.hpp +64 -0
- package/vendor/include/tlx/meta/enable_if.hpp +37 -0
- package/vendor/include/tlx/meta/fold_left.hpp +63 -0
- package/vendor/include/tlx/meta/fold_left_tuple.hpp +60 -0
- package/vendor/include/tlx/meta/fold_right.hpp +63 -0
- package/vendor/include/tlx/meta/fold_right_tuple.hpp +60 -0
- package/vendor/include/tlx/meta/function_chain.hpp +197 -0
- package/vendor/include/tlx/meta/function_stack.hpp +189 -0
- package/vendor/include/tlx/meta/has_member.hpp +80 -0
- package/vendor/include/tlx/meta/has_method.hpp +117 -0
- package/vendor/include/tlx/meta/index_sequence.hpp +66 -0
- package/vendor/include/tlx/meta/is_std_array.hpp +40 -0
- package/vendor/include/tlx/meta/is_std_pair.hpp +39 -0
- package/vendor/include/tlx/meta/is_std_tuple.hpp +39 -0
- package/vendor/include/tlx/meta/is_std_vector.hpp +39 -0
- package/vendor/include/tlx/meta/log2.hpp +101 -0
- package/vendor/include/tlx/meta/no_operation.hpp +55 -0
- package/vendor/include/tlx/meta/static_index.hpp +42 -0
- package/vendor/include/tlx/meta/vexpand.hpp +34 -0
- package/vendor/include/tlx/meta/vmap_for_range.hpp +84 -0
- package/vendor/include/tlx/meta/vmap_foreach.hpp +63 -0
- package/vendor/include/tlx/meta/vmap_foreach_tuple.hpp +59 -0
- package/vendor/include/tlx/meta/vmap_foreach_tuple_with_index.hpp +62 -0
- package/vendor/include/tlx/meta/vmap_foreach_with_index.hpp +70 -0
- package/vendor/include/tlx/meta.hpp +55 -0
- package/vendor/include/tlx/multi_timer.hpp +148 -0
- package/vendor/include/tlx/port/setenv.hpp +31 -0
- package/vendor/include/tlx/port.hpp +27 -0
- package/vendor/include/tlx/semaphore.hpp +119 -0
- package/vendor/include/tlx/simple_vector.hpp +20 -0
- package/vendor/include/tlx/siphash.hpp +282 -0
- package/vendor/include/tlx/sort/networks/best.hpp +611 -0
- package/vendor/include/tlx/sort/networks/bose_nelson.hpp +412 -0
- package/vendor/include/tlx/sort/networks/bose_nelson_parameter.hpp +507 -0
- package/vendor/include/tlx/sort/networks/cswap.hpp +60 -0
- package/vendor/include/tlx/sort/parallel_mergesort.hpp +398 -0
- package/vendor/include/tlx/sort/strings/insertion_sort.hpp +232 -0
- package/vendor/include/tlx/sort/strings/multikey_quicksort.hpp +185 -0
- package/vendor/include/tlx/sort/strings/parallel_sample_sort.hpp +1647 -0
- package/vendor/include/tlx/sort/strings/radix_sort.hpp +934 -0
- package/vendor/include/tlx/sort/strings/sample_sort_tools.hpp +756 -0
- package/vendor/include/tlx/sort/strings/string_ptr.hpp +426 -0
- package/vendor/include/tlx/sort/strings/string_set.hpp +800 -0
- package/vendor/include/tlx/sort/strings.hpp +329 -0
- package/vendor/include/tlx/sort/strings_parallel.hpp +325 -0
- package/vendor/include/tlx/sort.hpp +29 -0
- package/vendor/include/tlx/stack_allocator.hpp +226 -0
- package/vendor/include/tlx/string/appendline.hpp +35 -0
- package/vendor/include/tlx/string/base64.hpp +87 -0
- package/vendor/include/tlx/string/bitdump.hpp +139 -0
- package/vendor/include/tlx/string/compare_icase.hpp +42 -0
- package/vendor/include/tlx/string/contains.hpp +36 -0
- package/vendor/include/tlx/string/contains_word.hpp +42 -0
- package/vendor/include/tlx/string/ends_with.hpp +79 -0
- package/vendor/include/tlx/string/equal_icase.hpp +42 -0
- package/vendor/include/tlx/string/erase_all.hpp +70 -0
- package/vendor/include/tlx/string/escape_html.hpp +34 -0
- package/vendor/include/tlx/string/escape_uri.hpp +34 -0
- package/vendor/include/tlx/string/expand_environment_variables.hpp +49 -0
- package/vendor/include/tlx/string/extract_between.hpp +40 -0
- package/vendor/include/tlx/string/format_iec_units.hpp +32 -0
- package/vendor/include/tlx/string/format_si_iec_units.hpp +19 -0
- package/vendor/include/tlx/string/format_si_units.hpp +32 -0
- package/vendor/include/tlx/string/hash_djb2.hpp +87 -0
- package/vendor/include/tlx/string/hash_sdbm.hpp +86 -0
- package/vendor/include/tlx/string/hexdump.hpp +154 -0
- package/vendor/include/tlx/string/index_of.hpp +56 -0
- package/vendor/include/tlx/string/join.hpp +65 -0
- package/vendor/include/tlx/string/join_generic.hpp +89 -0
- package/vendor/include/tlx/string/join_quoted.hpp +46 -0
- package/vendor/include/tlx/string/less_icase.hpp +64 -0
- package/vendor/include/tlx/string/levenshtein.hpp +193 -0
- package/vendor/include/tlx/string/pad.hpp +39 -0
- package/vendor/include/tlx/string/parse_si_iec_units.hpp +46 -0
- package/vendor/include/tlx/string/parse_uri.hpp +66 -0
- package/vendor/include/tlx/string/parse_uri_form_data.hpp +136 -0
- package/vendor/include/tlx/string/replace.hpp +141 -0
- package/vendor/include/tlx/string/split.hpp +170 -0
- package/vendor/include/tlx/string/split_quoted.hpp +49 -0
- package/vendor/include/tlx/string/split_view.hpp +218 -0
- package/vendor/include/tlx/string/split_words.hpp +53 -0
- package/vendor/include/tlx/string/ssprintf.hpp +45 -0
- package/vendor/include/tlx/string/ssprintf_generic.hpp +95 -0
- package/vendor/include/tlx/string/starts_with.hpp +44 -0
- package/vendor/include/tlx/string/to_lower.hpp +47 -0
- package/vendor/include/tlx/string/to_upper.hpp +47 -0
- package/vendor/include/tlx/string/trim.hpp +298 -0
- package/vendor/include/tlx/string/union_words.hpp +33 -0
- package/vendor/include/tlx/string/word_wrap.hpp +35 -0
- package/vendor/include/tlx/string.hpp +68 -0
- package/vendor/include/tlx/thread_barrier_mutex.hpp +109 -0
- package/vendor/include/tlx/thread_barrier_spin.hpp +127 -0
- package/vendor/include/tlx/thread_pool.hpp +151 -0
- package/vendor/include/tlx/timestamp.hpp +23 -0
- package/vendor/include/tlx/unused.hpp +28 -0
- package/vendor/include/tlx/vector_free.hpp +30 -0
- package/vendor/include/tlx/version.hpp +49 -0
- package/vendor/include/ttmath/ttmath.h +2881 -0
- package/vendor/include/ttmath/ttmathbig.h +6111 -0
- package/vendor/include/ttmath/ttmathdec.h +419 -0
- package/vendor/include/ttmath/ttmathint.h +1923 -0
- package/vendor/include/ttmath/ttmathmisc.h +250 -0
- package/vendor/include/ttmath/ttmathobjects.h +812 -0
- package/vendor/include/ttmath/ttmathparser.h +2791 -0
- package/vendor/include/ttmath/ttmaththreads.h +252 -0
- package/vendor/include/ttmath/ttmathtypes.h +707 -0
- package/vendor/include/ttmath/ttmathuint.h +4190 -0
- package/vendor/include/ttmath/ttmathuint_noasm.h +1038 -0
- package/vendor/include/ttmath/ttmathuint_x86.h +1620 -0
- package/vendor/include/ttmath/ttmathuint_x86_64.h +1177 -0
- package/vendor/lib/cmake/tlx/tlx-config.cmake +51 -0
- package/vendor/lib/cmake/tlx/tlx-targets-release.cmake +19 -0
- package/vendor/lib/cmake/tlx/tlx-targets.cmake +106 -0
- package/vendor/lib/cmake/tlx/tlx-version.cmake +11 -0
- package/vendor/lib/libnetworkit.dylib +0 -0
- package/vendor/lib/libtlx.a +0 -0
- package/vendor/lib/pkgconfig/networkit.pc +11 -0
- package/vendor/lib/pkgconfig/tlx.pc +11 -0
|
@@ -0,0 +1,3977 @@
|
|
|
1
|
+
/*******************************************************************************
|
|
2
|
+
* tlx/container/btree.hpp
|
|
3
|
+
*
|
|
4
|
+
* Part of tlx - http://panthema.net/tlx
|
|
5
|
+
*
|
|
6
|
+
* Copyright (C) 2008-2017 Timo Bingmann <tb@panthema.net>
|
|
7
|
+
*
|
|
8
|
+
* All rights reserved. Published under the Boost Software License, Version 1.0
|
|
9
|
+
******************************************************************************/
|
|
10
|
+
|
|
11
|
+
#ifndef TLX_CONTAINER_BTREE_HEADER
|
|
12
|
+
#define TLX_CONTAINER_BTREE_HEADER
|
|
13
|
+
|
|
14
|
+
#include <tlx/die/core.hpp>
|
|
15
|
+
|
|
16
|
+
// *** Required Headers from the STL
|
|
17
|
+
|
|
18
|
+
#include <algorithm>
|
|
19
|
+
#include <cassert>
|
|
20
|
+
#include <cstddef>
|
|
21
|
+
#include <functional>
|
|
22
|
+
#include <iterator>
|
|
23
|
+
#include <memory>
|
|
24
|
+
#include <utility>
|
|
25
|
+
|
|
26
|
+
namespace tlx {
|
|
27
|
+
|
|
28
|
+
//! \addtogroup tlx_container
|
|
29
|
+
//! \{
|
|
30
|
+
//! \defgroup tlx_container_btree B+ Trees
|
|
31
|
+
//! B+ tree variants
|
|
32
|
+
//! \{
|
|
33
|
+
|
|
34
|
+
// *** Debugging Macros
|
|
35
|
+
|
|
36
|
+
#ifdef TLX_BTREE_DEBUG
|
|
37
|
+
|
|
38
|
+
#include <iostream>
|
|
39
|
+
|
|
40
|
+
//! Print out debug information to std::cout if TLX_BTREE_DEBUG is defined.
|
|
41
|
+
#define TLX_BTREE_PRINT(x) \
|
|
42
|
+
do \
|
|
43
|
+
{ \
|
|
44
|
+
if (debug) \
|
|
45
|
+
(std::cout << x << std::endl); \
|
|
46
|
+
} while (0)
|
|
47
|
+
|
|
48
|
+
//! Assertion only if TLX_BTREE_DEBUG is defined. This is not used in verify().
|
|
49
|
+
#define TLX_BTREE_ASSERT(x) \
|
|
50
|
+
do \
|
|
51
|
+
{ \
|
|
52
|
+
assert(x); \
|
|
53
|
+
} while (0)
|
|
54
|
+
|
|
55
|
+
#else
|
|
56
|
+
|
|
57
|
+
//! Print out debug information to std::cout if TLX_BTREE_DEBUG is defined.
|
|
58
|
+
#define TLX_BTREE_PRINT(x) \
|
|
59
|
+
do \
|
|
60
|
+
{ \
|
|
61
|
+
} while (0)
|
|
62
|
+
|
|
63
|
+
//! Assertion only if TLX_BTREE_DEBUG is defined. This is not used in verify().
|
|
64
|
+
#define TLX_BTREE_ASSERT(x) \
|
|
65
|
+
do \
|
|
66
|
+
{ \
|
|
67
|
+
} while (0)
|
|
68
|
+
|
|
69
|
+
#endif
|
|
70
|
+
|
|
71
|
+
//! The maximum of a and b. Used in some compile-time formulas.
|
|
72
|
+
#define TLX_BTREE_MAX(a, b) ((a) < (b) ? (b) : (a))
|
|
73
|
+
|
|
74
|
+
#ifndef TLX_BTREE_FRIENDS
|
|
75
|
+
//! The macro TLX_BTREE_FRIENDS can be used by outside class to access the B+
|
|
76
|
+
//! tree internals. This was added for wxBTreeDemo to be able to draw the
|
|
77
|
+
//! tree.
|
|
78
|
+
#define TLX_BTREE_FRIENDS friend class btree_friend
|
|
79
|
+
#endif
|
|
80
|
+
|
|
81
|
+
/*!
|
|
82
|
+
* Generates default traits for a B+ tree used as a set or map. It estimates
|
|
83
|
+
* leaf and inner node sizes by assuming a cache line multiple of 256 bytes.
|
|
84
|
+
*/
|
|
85
|
+
template <typename Key, typename Value>
|
|
86
|
+
struct btree_default_traits
|
|
87
|
+
{
|
|
88
|
+
//! If true, the tree will self verify its invariants after each insert() or
|
|
89
|
+
//! erase(). The header must have been compiled with TLX_BTREE_DEBUG
|
|
90
|
+
//! defined.
|
|
91
|
+
static const bool self_verify = false;
|
|
92
|
+
|
|
93
|
+
//! If true, the tree will print out debug information and a tree dump
|
|
94
|
+
//! during insert() or erase() operation. The header must have been
|
|
95
|
+
//! compiled with TLX_BTREE_DEBUG defined and key_type must be std::ostream
|
|
96
|
+
//! printable.
|
|
97
|
+
static const bool debug = false;
|
|
98
|
+
|
|
99
|
+
//! Number of slots in each leaf of the tree. Estimated so that each node
|
|
100
|
+
//! has a size of about 256 bytes.
|
|
101
|
+
static const int leaf_slots = TLX_BTREE_MAX(8, 256 / (sizeof(Value)));
|
|
102
|
+
|
|
103
|
+
//! Number of slots in each inner node of the tree. Estimated so that each
|
|
104
|
+
//! node has a size of about 256 bytes.
|
|
105
|
+
static const int inner_slots =
|
|
106
|
+
TLX_BTREE_MAX(8, 256 / (sizeof(Key) + sizeof(void*)));
|
|
107
|
+
|
|
108
|
+
//! As of stx-btree-0.9, the code does linear search in find_lower() and
|
|
109
|
+
//! find_upper() instead of binary_search, unless the node size is larger
|
|
110
|
+
//! than this threshold. See notes at
|
|
111
|
+
//! http://panthema.net/2013/0504-STX-B+Tree-Binary-vs-Linear-Search
|
|
112
|
+
static const size_t binsearch_threshold = 256;
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
/*!
|
|
116
|
+
* Basic class implementing a B+ tree data structure in memory.
|
|
117
|
+
*
|
|
118
|
+
* The base implementation of an in-memory B+ tree. It is based on the
|
|
119
|
+
* implementation in Cormen's Introduction into Algorithms, Jan Jannink's paper
|
|
120
|
+
* and other algorithm resources. Almost all STL-required function calls are
|
|
121
|
+
* implemented. The asymptotic time requirements of the STL are not always
|
|
122
|
+
* fulfilled in theory, however, in practice this B+ tree performs better than a
|
|
123
|
+
* red-black tree and almost always uses less memory. The insertion function
|
|
124
|
+
* splits the nodes on the recursion unroll. Erase is largely based on Jannink's
|
|
125
|
+
* ideas.
|
|
126
|
+
*
|
|
127
|
+
* This class is specialized into btree_set, btree_multiset, btree_map and
|
|
128
|
+
* btree_multimap using default template parameters and facade functions.
|
|
129
|
+
*/
|
|
130
|
+
template <typename Key, typename Value, typename KeyOfValue,
|
|
131
|
+
typename Compare = std::less<Key>,
|
|
132
|
+
typename Traits = btree_default_traits<Key, Value>,
|
|
133
|
+
bool Duplicates = false, typename Allocator = std::allocator<Value> >
|
|
134
|
+
class BTree
|
|
135
|
+
{
|
|
136
|
+
public:
|
|
137
|
+
//! \name Template Parameter Types
|
|
138
|
+
//! \{
|
|
139
|
+
|
|
140
|
+
//! First template parameter: The key type of the B+ tree. This is stored in
|
|
141
|
+
//! inner nodes.
|
|
142
|
+
typedef Key key_type;
|
|
143
|
+
|
|
144
|
+
//! Second template parameter: Composition pair of key and data types, or
|
|
145
|
+
//! just the key for set containers. This data type is stored in the leaves.
|
|
146
|
+
typedef Value value_type;
|
|
147
|
+
|
|
148
|
+
//! Third template: key extractor class to pull key_type from value_type.
|
|
149
|
+
typedef KeyOfValue key_of_value;
|
|
150
|
+
|
|
151
|
+
//! Fourth template parameter: key_type comparison function object
|
|
152
|
+
typedef Compare key_compare;
|
|
153
|
+
|
|
154
|
+
//! Fifth template parameter: Traits object used to define more parameters
|
|
155
|
+
//! of the B+ tree
|
|
156
|
+
typedef Traits traits;
|
|
157
|
+
|
|
158
|
+
//! Sixth template parameter: Allow duplicate keys in the B+ tree. Used to
|
|
159
|
+
//! implement multiset and multimap.
|
|
160
|
+
static const bool allow_duplicates = Duplicates;
|
|
161
|
+
|
|
162
|
+
//! Seventh template parameter: STL allocator for tree nodes
|
|
163
|
+
typedef Allocator allocator_type;
|
|
164
|
+
|
|
165
|
+
//! \}
|
|
166
|
+
|
|
167
|
+
// The macro TLX_BTREE_FRIENDS can be used by outside class to access the B+
|
|
168
|
+
// tree internals. This was added for wxBTreeDemo to be able to draw the
|
|
169
|
+
// tree.
|
|
170
|
+
TLX_BTREE_FRIENDS;
|
|
171
|
+
|
|
172
|
+
public:
|
|
173
|
+
//! \name Constructed Types
|
|
174
|
+
//! \{
|
|
175
|
+
|
|
176
|
+
//! Typedef of our own type
|
|
177
|
+
typedef BTree<key_type, value_type, key_of_value, key_compare, traits,
|
|
178
|
+
allow_duplicates, allocator_type>
|
|
179
|
+
Self;
|
|
180
|
+
|
|
181
|
+
//! Size type used to count keys
|
|
182
|
+
typedef size_t size_type;
|
|
183
|
+
|
|
184
|
+
//! \}
|
|
185
|
+
|
|
186
|
+
public:
|
|
187
|
+
//! \name Static Constant Options and Values of the B+ Tree
|
|
188
|
+
//! \{
|
|
189
|
+
|
|
190
|
+
//! Base B+ tree parameter: The number of key/data slots in each leaf
|
|
191
|
+
static const unsigned short leaf_slotmax = traits::leaf_slots;
|
|
192
|
+
|
|
193
|
+
//! Base B+ tree parameter: The number of key slots in each inner node,
|
|
194
|
+
//! this can differ from slots in each leaf.
|
|
195
|
+
static const unsigned short inner_slotmax = traits::inner_slots;
|
|
196
|
+
|
|
197
|
+
//! Computed B+ tree parameter: The minimum number of key/data slots used
|
|
198
|
+
//! in a leaf. If fewer slots are used, the leaf will be merged or slots
|
|
199
|
+
//! shifted from it's siblings.
|
|
200
|
+
static const unsigned short leaf_slotmin = (leaf_slotmax / 2);
|
|
201
|
+
|
|
202
|
+
//! Computed B+ tree parameter: The minimum number of key slots used
|
|
203
|
+
//! in an inner node. If fewer slots are used, the inner node will be
|
|
204
|
+
//! merged or slots shifted from it's siblings.
|
|
205
|
+
static const unsigned short inner_slotmin = (inner_slotmax / 2);
|
|
206
|
+
|
|
207
|
+
//! Debug parameter: Enables expensive and thorough checking of the B+ tree
|
|
208
|
+
//! invariants after each insert/erase operation.
|
|
209
|
+
static const bool self_verify = traits::self_verify;
|
|
210
|
+
|
|
211
|
+
//! Debug parameter: Prints out lots of debug information about how the
|
|
212
|
+
//! algorithms change the tree. Requires the header file to be compiled
|
|
213
|
+
//! with TLX_BTREE_DEBUG and the key type must be std::ostream printable.
|
|
214
|
+
static const bool debug = traits::debug;
|
|
215
|
+
|
|
216
|
+
//! \}
|
|
217
|
+
|
|
218
|
+
private:
|
|
219
|
+
//! \name Node Classes for In-Memory Nodes
|
|
220
|
+
//! \{
|
|
221
|
+
|
|
222
|
+
//! The header structure of each node in-memory. This structure is extended
|
|
223
|
+
//! by InnerNode or LeafNode.
|
|
224
|
+
struct node
|
|
225
|
+
{
|
|
226
|
+
//! Level in the b-tree, if level == 0 -> leaf node
|
|
227
|
+
unsigned short level;
|
|
228
|
+
|
|
229
|
+
//! Number of key slotuse use, so the number of valid children or data
|
|
230
|
+
//! pointers
|
|
231
|
+
unsigned short slotuse;
|
|
232
|
+
|
|
233
|
+
//! Delayed initialisation of constructed node.
|
|
234
|
+
void initialize(const unsigned short l)
|
|
235
|
+
{
|
|
236
|
+
level = l;
|
|
237
|
+
slotuse = 0;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
//! True if this is a leaf node.
|
|
241
|
+
bool is_leafnode() const
|
|
242
|
+
{
|
|
243
|
+
return (level == 0);
|
|
244
|
+
}
|
|
245
|
+
};
|
|
246
|
+
|
|
247
|
+
//! Extended structure of a inner node in-memory. Contains only keys and no
|
|
248
|
+
//! data items.
|
|
249
|
+
struct InnerNode : public node
|
|
250
|
+
{
|
|
251
|
+
//! Define an related allocator for the InnerNode structs.
|
|
252
|
+
typedef typename std::allocator_traits<
|
|
253
|
+
Allocator>::template rebind_alloc<InnerNode>
|
|
254
|
+
alloc_type;
|
|
255
|
+
|
|
256
|
+
//! Keys of children or data pointers
|
|
257
|
+
key_type slotkey[inner_slotmax];
|
|
258
|
+
|
|
259
|
+
//! Pointers to children
|
|
260
|
+
node* childid[inner_slotmax + 1];
|
|
261
|
+
|
|
262
|
+
//! Set variables to initial values.
|
|
263
|
+
void initialize(const unsigned short l)
|
|
264
|
+
{
|
|
265
|
+
node::initialize(l);
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
//! Return key in slot s
|
|
269
|
+
const key_type& key(size_t s) const
|
|
270
|
+
{
|
|
271
|
+
return slotkey[s];
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
//! True if the node's slots are full.
|
|
275
|
+
bool is_full() const
|
|
276
|
+
{
|
|
277
|
+
return (node::slotuse == inner_slotmax);
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
//! True if few used entries, less than half full.
|
|
281
|
+
bool is_few() const
|
|
282
|
+
{
|
|
283
|
+
return (node::slotuse <= inner_slotmin);
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
//! True if node has too few entries.
|
|
287
|
+
bool is_underflow() const
|
|
288
|
+
{
|
|
289
|
+
return (node::slotuse < inner_slotmin);
|
|
290
|
+
}
|
|
291
|
+
};
|
|
292
|
+
|
|
293
|
+
//! Extended structure of a leaf node in memory. Contains pairs of keys and
|
|
294
|
+
//! data items. Key and data slots are kept together in value_type.
|
|
295
|
+
struct LeafNode : public node
|
|
296
|
+
{
|
|
297
|
+
//! Define an related allocator for the LeafNode structs.
|
|
298
|
+
typedef typename std::allocator_traits<
|
|
299
|
+
Allocator>::template rebind_alloc<LeafNode>
|
|
300
|
+
alloc_type;
|
|
301
|
+
|
|
302
|
+
//! Double linked list pointers to traverse the leaves
|
|
303
|
+
LeafNode* prev_leaf;
|
|
304
|
+
|
|
305
|
+
//! Double linked list pointers to traverse the leaves
|
|
306
|
+
LeafNode* next_leaf;
|
|
307
|
+
|
|
308
|
+
//! Array of (key, data) pairs
|
|
309
|
+
value_type slotdata[leaf_slotmax];
|
|
310
|
+
|
|
311
|
+
//! Set variables to initial values
|
|
312
|
+
void initialize()
|
|
313
|
+
{
|
|
314
|
+
node::initialize(0);
|
|
315
|
+
prev_leaf = next_leaf = nullptr;
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
//! Return key in slot s.
|
|
319
|
+
const key_type& key(size_t s) const
|
|
320
|
+
{
|
|
321
|
+
return key_of_value::get(slotdata[s]);
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
//! True if the node's slots are full.
|
|
325
|
+
bool is_full() const
|
|
326
|
+
{
|
|
327
|
+
return (node::slotuse == leaf_slotmax);
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
//! True if few used entries, less than half full.
|
|
331
|
+
bool is_few() const
|
|
332
|
+
{
|
|
333
|
+
return (node::slotuse <= leaf_slotmin);
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
//! True if node has too few entries.
|
|
337
|
+
bool is_underflow() const
|
|
338
|
+
{
|
|
339
|
+
return (node::slotuse < leaf_slotmin);
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
//! Set the (key,data) pair in slot. Overloaded function used by
|
|
343
|
+
//! bulk_load().
|
|
344
|
+
void set_slot(unsigned short slot, const value_type& value)
|
|
345
|
+
{
|
|
346
|
+
TLX_BTREE_ASSERT(slot < node::slotuse);
|
|
347
|
+
slotdata[slot] = value;
|
|
348
|
+
}
|
|
349
|
+
};
|
|
350
|
+
|
|
351
|
+
//! \}
|
|
352
|
+
|
|
353
|
+
public:
|
|
354
|
+
//! \name Iterators and Reverse Iterators
|
|
355
|
+
//! \{
|
|
356
|
+
|
|
357
|
+
class iterator;
|
|
358
|
+
class const_iterator;
|
|
359
|
+
class reverse_iterator;
|
|
360
|
+
class const_reverse_iterator;
|
|
361
|
+
|
|
362
|
+
//! STL-like iterator object for B+ tree items. The iterator points to a
|
|
363
|
+
//! specific slot number in a leaf.
|
|
364
|
+
class iterator
|
|
365
|
+
{
|
|
366
|
+
public:
|
|
367
|
+
// *** Types
|
|
368
|
+
|
|
369
|
+
//! The key type of the btree. Returned by key().
|
|
370
|
+
typedef typename BTree::key_type key_type;
|
|
371
|
+
|
|
372
|
+
//! The value type of the btree. Returned by operator*().
|
|
373
|
+
typedef typename BTree::value_type value_type;
|
|
374
|
+
|
|
375
|
+
//! Reference to the value_type. STL required.
|
|
376
|
+
typedef value_type& reference;
|
|
377
|
+
|
|
378
|
+
//! Pointer to the value_type. STL required.
|
|
379
|
+
typedef value_type* pointer;
|
|
380
|
+
|
|
381
|
+
//! STL-magic iterator category
|
|
382
|
+
typedef std::bidirectional_iterator_tag iterator_category;
|
|
383
|
+
|
|
384
|
+
//! STL-magic
|
|
385
|
+
typedef ptrdiff_t difference_type;
|
|
386
|
+
|
|
387
|
+
//! Our own type
|
|
388
|
+
typedef iterator self;
|
|
389
|
+
|
|
390
|
+
private:
|
|
391
|
+
// *** Members
|
|
392
|
+
|
|
393
|
+
//! The currently referenced leaf node of the tree
|
|
394
|
+
typename BTree::LeafNode* curr_leaf;
|
|
395
|
+
|
|
396
|
+
//! Current key/data slot referenced
|
|
397
|
+
unsigned short curr_slot;
|
|
398
|
+
|
|
399
|
+
//! Friendly to the const_iterator, so it may access the two data items
|
|
400
|
+
//! directly.
|
|
401
|
+
friend class const_iterator;
|
|
402
|
+
|
|
403
|
+
//! Also friendly to the reverse_iterator, so it may access the two
|
|
404
|
+
//! data items directly.
|
|
405
|
+
friend class reverse_iterator;
|
|
406
|
+
|
|
407
|
+
//! Also friendly to the const_reverse_iterator, so it may access the
|
|
408
|
+
//! two data items directly.
|
|
409
|
+
friend class const_reverse_iterator;
|
|
410
|
+
|
|
411
|
+
//! Also friendly to the base btree class, because erase_iter() needs
|
|
412
|
+
//! to read the curr_leaf and curr_slot values directly.
|
|
413
|
+
friend class BTree<key_type, value_type, key_of_value, key_compare,
|
|
414
|
+
traits, allow_duplicates, allocator_type>;
|
|
415
|
+
|
|
416
|
+
// The macro TLX_BTREE_FRIENDS can be used by outside class to access
|
|
417
|
+
// the B+ tree internals. This was added for wxBTreeDemo to be able to
|
|
418
|
+
// draw the tree.
|
|
419
|
+
TLX_BTREE_FRIENDS;
|
|
420
|
+
|
|
421
|
+
public:
|
|
422
|
+
// *** Methods
|
|
423
|
+
|
|
424
|
+
//! Default-Constructor of a mutable iterator
|
|
425
|
+
iterator() : curr_leaf(nullptr), curr_slot(0)
|
|
426
|
+
{
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
//! Initializing-Constructor of a mutable iterator
|
|
430
|
+
iterator(typename BTree::LeafNode* l, unsigned short s)
|
|
431
|
+
: curr_leaf(l), curr_slot(s)
|
|
432
|
+
{
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
//! Copy-constructor from a reverse iterator
|
|
436
|
+
iterator(const reverse_iterator& it)
|
|
437
|
+
: curr_leaf(it.curr_leaf), curr_slot(it.curr_slot)
|
|
438
|
+
{
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
//! Dereference the iterator.
|
|
442
|
+
reference operator*() const
|
|
443
|
+
{
|
|
444
|
+
return curr_leaf->slotdata[curr_slot];
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
//! Dereference the iterator.
|
|
448
|
+
pointer operator->() const
|
|
449
|
+
{
|
|
450
|
+
return &curr_leaf->slotdata[curr_slot];
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
//! Key of the current slot.
|
|
454
|
+
const key_type& key() const
|
|
455
|
+
{
|
|
456
|
+
return curr_leaf->key(curr_slot);
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
//! Prefix++ advance the iterator to the next slot.
|
|
460
|
+
iterator& operator++()
|
|
461
|
+
{
|
|
462
|
+
if (curr_slot + 1U < curr_leaf->slotuse)
|
|
463
|
+
{
|
|
464
|
+
++curr_slot;
|
|
465
|
+
}
|
|
466
|
+
else if (curr_leaf->next_leaf != nullptr)
|
|
467
|
+
{
|
|
468
|
+
curr_leaf = curr_leaf->next_leaf;
|
|
469
|
+
curr_slot = 0;
|
|
470
|
+
}
|
|
471
|
+
else
|
|
472
|
+
{
|
|
473
|
+
// this is end()
|
|
474
|
+
curr_slot = curr_leaf->slotuse;
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
return *this;
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
//! Postfix++ advance the iterator to the next slot.
|
|
481
|
+
iterator operator++(int)
|
|
482
|
+
{
|
|
483
|
+
iterator tmp = *this; // copy ourselves
|
|
484
|
+
|
|
485
|
+
if (curr_slot + 1U < curr_leaf->slotuse)
|
|
486
|
+
{
|
|
487
|
+
++curr_slot;
|
|
488
|
+
}
|
|
489
|
+
else if (curr_leaf->next_leaf != nullptr)
|
|
490
|
+
{
|
|
491
|
+
curr_leaf = curr_leaf->next_leaf;
|
|
492
|
+
curr_slot = 0;
|
|
493
|
+
}
|
|
494
|
+
else
|
|
495
|
+
{
|
|
496
|
+
// this is end()
|
|
497
|
+
curr_slot = curr_leaf->slotuse;
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
return tmp;
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
//! Prefix-- backstep the iterator to the last slot.
|
|
504
|
+
iterator& operator--()
|
|
505
|
+
{
|
|
506
|
+
if (curr_slot > 0)
|
|
507
|
+
{
|
|
508
|
+
--curr_slot;
|
|
509
|
+
}
|
|
510
|
+
else if (curr_leaf->prev_leaf != nullptr)
|
|
511
|
+
{
|
|
512
|
+
curr_leaf = curr_leaf->prev_leaf;
|
|
513
|
+
curr_slot = curr_leaf->slotuse - 1;
|
|
514
|
+
}
|
|
515
|
+
else
|
|
516
|
+
{
|
|
517
|
+
// this is begin()
|
|
518
|
+
curr_slot = 0;
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
return *this;
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
//! Postfix-- backstep the iterator to the last slot.
|
|
525
|
+
iterator operator--(int)
|
|
526
|
+
{
|
|
527
|
+
iterator tmp = *this; // copy ourselves
|
|
528
|
+
|
|
529
|
+
if (curr_slot > 0)
|
|
530
|
+
{
|
|
531
|
+
--curr_slot;
|
|
532
|
+
}
|
|
533
|
+
else if (curr_leaf->prev_leaf != nullptr)
|
|
534
|
+
{
|
|
535
|
+
curr_leaf = curr_leaf->prev_leaf;
|
|
536
|
+
curr_slot = curr_leaf->slotuse - 1;
|
|
537
|
+
}
|
|
538
|
+
else
|
|
539
|
+
{
|
|
540
|
+
// this is begin()
|
|
541
|
+
curr_slot = 0;
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
return tmp;
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
//! Equality of iterators.
|
|
548
|
+
bool operator==(const iterator& x) const
|
|
549
|
+
{
|
|
550
|
+
return (x.curr_leaf == curr_leaf) && (x.curr_slot == curr_slot);
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
//! Inequality of iterators.
|
|
554
|
+
bool operator!=(const iterator& x) const
|
|
555
|
+
{
|
|
556
|
+
return (x.curr_leaf != curr_leaf) || (x.curr_slot != curr_slot);
|
|
557
|
+
}
|
|
558
|
+
};
|
|
559
|
+
|
|
560
|
+
//! STL-like read-only iterator object for B+ tree items. The iterator
|
|
561
|
+
//! points to a specific slot number in a leaf.
|
|
562
|
+
class const_iterator
|
|
563
|
+
{
|
|
564
|
+
public:
|
|
565
|
+
// *** Types
|
|
566
|
+
|
|
567
|
+
//! The key type of the btree. Returned by key().
|
|
568
|
+
typedef typename BTree::key_type key_type;
|
|
569
|
+
|
|
570
|
+
//! The value type of the btree. Returned by operator*().
|
|
571
|
+
typedef typename BTree::value_type value_type;
|
|
572
|
+
|
|
573
|
+
//! Reference to the value_type. STL required.
|
|
574
|
+
typedef const value_type& reference;
|
|
575
|
+
|
|
576
|
+
//! Pointer to the value_type. STL required.
|
|
577
|
+
typedef const value_type* pointer;
|
|
578
|
+
|
|
579
|
+
//! STL-magic iterator category
|
|
580
|
+
typedef std::bidirectional_iterator_tag iterator_category;
|
|
581
|
+
|
|
582
|
+
//! STL-magic
|
|
583
|
+
typedef ptrdiff_t difference_type;
|
|
584
|
+
|
|
585
|
+
//! Our own type
|
|
586
|
+
typedef const_iterator self;
|
|
587
|
+
|
|
588
|
+
private:
|
|
589
|
+
// *** Members
|
|
590
|
+
|
|
591
|
+
//! The currently referenced leaf node of the tree
|
|
592
|
+
const typename BTree::LeafNode* curr_leaf;
|
|
593
|
+
|
|
594
|
+
//! Current key/data slot referenced
|
|
595
|
+
unsigned short curr_slot;
|
|
596
|
+
|
|
597
|
+
//! Friendly to the reverse_const_iterator, so it may access the two
|
|
598
|
+
//! data items directly
|
|
599
|
+
friend class const_reverse_iterator;
|
|
600
|
+
|
|
601
|
+
// The macro TLX_BTREE_FRIENDS can be used by outside class to access
|
|
602
|
+
// the B+ tree internals. This was added for wxBTreeDemo to be able to
|
|
603
|
+
// draw the tree.
|
|
604
|
+
TLX_BTREE_FRIENDS;
|
|
605
|
+
|
|
606
|
+
public:
|
|
607
|
+
// *** Methods
|
|
608
|
+
|
|
609
|
+
//! Default-Constructor of a const iterator
|
|
610
|
+
const_iterator() : curr_leaf(nullptr), curr_slot(0)
|
|
611
|
+
{
|
|
612
|
+
}
|
|
613
|
+
|
|
614
|
+
//! Initializing-Constructor of a const iterator
|
|
615
|
+
const_iterator(const typename BTree::LeafNode* l, unsigned short s)
|
|
616
|
+
: curr_leaf(l), curr_slot(s)
|
|
617
|
+
{
|
|
618
|
+
}
|
|
619
|
+
|
|
620
|
+
//! Copy-constructor from a mutable iterator
|
|
621
|
+
const_iterator(const iterator& it)
|
|
622
|
+
: curr_leaf(it.curr_leaf), curr_slot(it.curr_slot)
|
|
623
|
+
{
|
|
624
|
+
}
|
|
625
|
+
|
|
626
|
+
//! Copy-constructor from a mutable reverse iterator
|
|
627
|
+
const_iterator(const reverse_iterator& it)
|
|
628
|
+
: curr_leaf(it.curr_leaf), curr_slot(it.curr_slot)
|
|
629
|
+
{
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
//! Copy-constructor from a const reverse iterator
|
|
633
|
+
const_iterator(const const_reverse_iterator& it)
|
|
634
|
+
: curr_leaf(it.curr_leaf), curr_slot(it.curr_slot)
|
|
635
|
+
{
|
|
636
|
+
}
|
|
637
|
+
|
|
638
|
+
//! Dereference the iterator.
|
|
639
|
+
reference operator*() const
|
|
640
|
+
{
|
|
641
|
+
return curr_leaf->slotdata[curr_slot];
|
|
642
|
+
}
|
|
643
|
+
|
|
644
|
+
//! Dereference the iterator.
|
|
645
|
+
pointer operator->() const
|
|
646
|
+
{
|
|
647
|
+
return &curr_leaf->slotdata[curr_slot];
|
|
648
|
+
}
|
|
649
|
+
|
|
650
|
+
//! Key of the current slot.
|
|
651
|
+
const key_type& key() const
|
|
652
|
+
{
|
|
653
|
+
return curr_leaf->key(curr_slot);
|
|
654
|
+
}
|
|
655
|
+
|
|
656
|
+
//! Prefix++ advance the iterator to the next slot.
|
|
657
|
+
const_iterator& operator++()
|
|
658
|
+
{
|
|
659
|
+
if (curr_slot + 1U < curr_leaf->slotuse)
|
|
660
|
+
{
|
|
661
|
+
++curr_slot;
|
|
662
|
+
}
|
|
663
|
+
else if (curr_leaf->next_leaf != nullptr)
|
|
664
|
+
{
|
|
665
|
+
curr_leaf = curr_leaf->next_leaf;
|
|
666
|
+
curr_slot = 0;
|
|
667
|
+
}
|
|
668
|
+
else
|
|
669
|
+
{
|
|
670
|
+
// this is end()
|
|
671
|
+
curr_slot = curr_leaf->slotuse;
|
|
672
|
+
}
|
|
673
|
+
|
|
674
|
+
return *this;
|
|
675
|
+
}
|
|
676
|
+
|
|
677
|
+
//! Postfix++ advance the iterator to the next slot.
|
|
678
|
+
const_iterator operator++(int)
|
|
679
|
+
{
|
|
680
|
+
const_iterator tmp = *this; // copy ourselves
|
|
681
|
+
|
|
682
|
+
if (curr_slot + 1U < curr_leaf->slotuse)
|
|
683
|
+
{
|
|
684
|
+
++curr_slot;
|
|
685
|
+
}
|
|
686
|
+
else if (curr_leaf->next_leaf != nullptr)
|
|
687
|
+
{
|
|
688
|
+
curr_leaf = curr_leaf->next_leaf;
|
|
689
|
+
curr_slot = 0;
|
|
690
|
+
}
|
|
691
|
+
else
|
|
692
|
+
{
|
|
693
|
+
// this is end()
|
|
694
|
+
curr_slot = curr_leaf->slotuse;
|
|
695
|
+
}
|
|
696
|
+
|
|
697
|
+
return tmp;
|
|
698
|
+
}
|
|
699
|
+
|
|
700
|
+
//! Prefix-- backstep the iterator to the last slot.
|
|
701
|
+
const_iterator& operator--()
|
|
702
|
+
{
|
|
703
|
+
if (curr_slot > 0)
|
|
704
|
+
{
|
|
705
|
+
--curr_slot;
|
|
706
|
+
}
|
|
707
|
+
else if (curr_leaf->prev_leaf != nullptr)
|
|
708
|
+
{
|
|
709
|
+
curr_leaf = curr_leaf->prev_leaf;
|
|
710
|
+
curr_slot = curr_leaf->slotuse - 1;
|
|
711
|
+
}
|
|
712
|
+
else
|
|
713
|
+
{
|
|
714
|
+
// this is begin()
|
|
715
|
+
curr_slot = 0;
|
|
716
|
+
}
|
|
717
|
+
|
|
718
|
+
return *this;
|
|
719
|
+
}
|
|
720
|
+
|
|
721
|
+
//! Postfix-- backstep the iterator to the last slot.
|
|
722
|
+
const_iterator operator--(int)
|
|
723
|
+
{
|
|
724
|
+
const_iterator tmp = *this; // copy ourselves
|
|
725
|
+
|
|
726
|
+
if (curr_slot > 0)
|
|
727
|
+
{
|
|
728
|
+
--curr_slot;
|
|
729
|
+
}
|
|
730
|
+
else if (curr_leaf->prev_leaf != nullptr)
|
|
731
|
+
{
|
|
732
|
+
curr_leaf = curr_leaf->prev_leaf;
|
|
733
|
+
curr_slot = curr_leaf->slotuse - 1;
|
|
734
|
+
}
|
|
735
|
+
else
|
|
736
|
+
{
|
|
737
|
+
// this is begin()
|
|
738
|
+
curr_slot = 0;
|
|
739
|
+
}
|
|
740
|
+
|
|
741
|
+
return tmp;
|
|
742
|
+
}
|
|
743
|
+
|
|
744
|
+
//! Equality of iterators.
|
|
745
|
+
bool operator==(const const_iterator& x) const
|
|
746
|
+
{
|
|
747
|
+
return (x.curr_leaf == curr_leaf) && (x.curr_slot == curr_slot);
|
|
748
|
+
}
|
|
749
|
+
|
|
750
|
+
//! Inequality of iterators.
|
|
751
|
+
bool operator!=(const const_iterator& x) const
|
|
752
|
+
{
|
|
753
|
+
return (x.curr_leaf != curr_leaf) || (x.curr_slot != curr_slot);
|
|
754
|
+
}
|
|
755
|
+
};
|
|
756
|
+
|
|
757
|
+
//! STL-like mutable reverse iterator object for B+ tree items. The
|
|
758
|
+
//! iterator points to a specific slot number in a leaf.
|
|
759
|
+
class reverse_iterator
|
|
760
|
+
{
|
|
761
|
+
public:
|
|
762
|
+
// *** Types
|
|
763
|
+
|
|
764
|
+
//! The key type of the btree. Returned by key().
|
|
765
|
+
typedef typename BTree::key_type key_type;
|
|
766
|
+
|
|
767
|
+
//! The value type of the btree. Returned by operator*().
|
|
768
|
+
typedef typename BTree::value_type value_type;
|
|
769
|
+
|
|
770
|
+
//! Reference to the value_type. STL required.
|
|
771
|
+
typedef value_type& reference;
|
|
772
|
+
|
|
773
|
+
//! Pointer to the value_type. STL required.
|
|
774
|
+
typedef value_type* pointer;
|
|
775
|
+
|
|
776
|
+
//! STL-magic iterator category
|
|
777
|
+
typedef std::bidirectional_iterator_tag iterator_category;
|
|
778
|
+
|
|
779
|
+
//! STL-magic
|
|
780
|
+
typedef ptrdiff_t difference_type;
|
|
781
|
+
|
|
782
|
+
//! Our own type
|
|
783
|
+
typedef reverse_iterator self;
|
|
784
|
+
|
|
785
|
+
private:
|
|
786
|
+
// *** Members
|
|
787
|
+
|
|
788
|
+
//! The currently referenced leaf node of the tree
|
|
789
|
+
typename BTree::LeafNode* curr_leaf;
|
|
790
|
+
|
|
791
|
+
//! One slot past the current key/data slot referenced.
|
|
792
|
+
unsigned short curr_slot;
|
|
793
|
+
|
|
794
|
+
//! Friendly to the const_iterator, so it may access the two data items
|
|
795
|
+
//! directly
|
|
796
|
+
friend class iterator;
|
|
797
|
+
|
|
798
|
+
//! Also friendly to the const_iterator, so it may access the two data
|
|
799
|
+
//! items directly
|
|
800
|
+
friend class const_iterator;
|
|
801
|
+
|
|
802
|
+
//! Also friendly to the const_iterator, so it may access the two data
|
|
803
|
+
//! items directly
|
|
804
|
+
friend class const_reverse_iterator;
|
|
805
|
+
|
|
806
|
+
// The macro TLX_BTREE_FRIENDS can be used by outside class to access
|
|
807
|
+
// the B+ tree internals. This was added for wxBTreeDemo to be able to
|
|
808
|
+
// draw the tree.
|
|
809
|
+
TLX_BTREE_FRIENDS;
|
|
810
|
+
|
|
811
|
+
public:
|
|
812
|
+
// *** Methods
|
|
813
|
+
|
|
814
|
+
//! Default-Constructor of a reverse iterator
|
|
815
|
+
reverse_iterator() : curr_leaf(nullptr), curr_slot(0)
|
|
816
|
+
{
|
|
817
|
+
}
|
|
818
|
+
|
|
819
|
+
//! Initializing-Constructor of a mutable reverse iterator
|
|
820
|
+
reverse_iterator(typename BTree::LeafNode* l, unsigned short s)
|
|
821
|
+
: curr_leaf(l), curr_slot(s)
|
|
822
|
+
{
|
|
823
|
+
}
|
|
824
|
+
|
|
825
|
+
//! Copy-constructor from a mutable iterator
|
|
826
|
+
reverse_iterator(const iterator& it)
|
|
827
|
+
: curr_leaf(it.curr_leaf), curr_slot(it.curr_slot)
|
|
828
|
+
{
|
|
829
|
+
}
|
|
830
|
+
|
|
831
|
+
//! Dereference the iterator.
|
|
832
|
+
reference operator*() const
|
|
833
|
+
{
|
|
834
|
+
TLX_BTREE_ASSERT(curr_slot > 0);
|
|
835
|
+
return curr_leaf->slotdata[curr_slot - 1];
|
|
836
|
+
}
|
|
837
|
+
|
|
838
|
+
//! Dereference the iterator.
|
|
839
|
+
pointer operator->() const
|
|
840
|
+
{
|
|
841
|
+
TLX_BTREE_ASSERT(curr_slot > 0);
|
|
842
|
+
return &curr_leaf->slotdata[curr_slot - 1];
|
|
843
|
+
}
|
|
844
|
+
|
|
845
|
+
//! Key of the current slot.
|
|
846
|
+
const key_type& key() const
|
|
847
|
+
{
|
|
848
|
+
TLX_BTREE_ASSERT(curr_slot > 0);
|
|
849
|
+
return curr_leaf->key(curr_slot - 1);
|
|
850
|
+
}
|
|
851
|
+
|
|
852
|
+
//! Prefix++ advance the iterator to the next slot.
|
|
853
|
+
reverse_iterator& operator++()
|
|
854
|
+
{
|
|
855
|
+
if (curr_slot > 1)
|
|
856
|
+
{
|
|
857
|
+
--curr_slot;
|
|
858
|
+
}
|
|
859
|
+
else if (curr_leaf->prev_leaf != nullptr)
|
|
860
|
+
{
|
|
861
|
+
curr_leaf = curr_leaf->prev_leaf;
|
|
862
|
+
curr_slot = curr_leaf->slotuse;
|
|
863
|
+
}
|
|
864
|
+
else
|
|
865
|
+
{
|
|
866
|
+
// this is begin() == rend()
|
|
867
|
+
curr_slot = 0;
|
|
868
|
+
}
|
|
869
|
+
|
|
870
|
+
return *this;
|
|
871
|
+
}
|
|
872
|
+
|
|
873
|
+
//! Postfix++ advance the iterator to the next slot.
|
|
874
|
+
reverse_iterator operator++(int)
|
|
875
|
+
{
|
|
876
|
+
reverse_iterator tmp = *this; // copy ourselves
|
|
877
|
+
|
|
878
|
+
if (curr_slot > 1)
|
|
879
|
+
{
|
|
880
|
+
--curr_slot;
|
|
881
|
+
}
|
|
882
|
+
else if (curr_leaf->prev_leaf != nullptr)
|
|
883
|
+
{
|
|
884
|
+
curr_leaf = curr_leaf->prev_leaf;
|
|
885
|
+
curr_slot = curr_leaf->slotuse;
|
|
886
|
+
}
|
|
887
|
+
else
|
|
888
|
+
{
|
|
889
|
+
// this is begin() == rend()
|
|
890
|
+
curr_slot = 0;
|
|
891
|
+
}
|
|
892
|
+
|
|
893
|
+
return tmp;
|
|
894
|
+
}
|
|
895
|
+
|
|
896
|
+
//! Prefix-- backstep the iterator to the last slot.
|
|
897
|
+
reverse_iterator& operator--()
|
|
898
|
+
{
|
|
899
|
+
if (curr_slot < curr_leaf->slotuse)
|
|
900
|
+
{
|
|
901
|
+
++curr_slot;
|
|
902
|
+
}
|
|
903
|
+
else if (curr_leaf->next_leaf != nullptr)
|
|
904
|
+
{
|
|
905
|
+
curr_leaf = curr_leaf->next_leaf;
|
|
906
|
+
curr_slot = 1;
|
|
907
|
+
}
|
|
908
|
+
else
|
|
909
|
+
{
|
|
910
|
+
// this is end() == rbegin()
|
|
911
|
+
curr_slot = curr_leaf->slotuse;
|
|
912
|
+
}
|
|
913
|
+
|
|
914
|
+
return *this;
|
|
915
|
+
}
|
|
916
|
+
|
|
917
|
+
//! Postfix-- backstep the iterator to the last slot.
|
|
918
|
+
reverse_iterator operator--(int)
|
|
919
|
+
{
|
|
920
|
+
reverse_iterator tmp = *this; // copy ourselves
|
|
921
|
+
|
|
922
|
+
if (curr_slot < curr_leaf->slotuse)
|
|
923
|
+
{
|
|
924
|
+
++curr_slot;
|
|
925
|
+
}
|
|
926
|
+
else if (curr_leaf->next_leaf != nullptr)
|
|
927
|
+
{
|
|
928
|
+
curr_leaf = curr_leaf->next_leaf;
|
|
929
|
+
curr_slot = 1;
|
|
930
|
+
}
|
|
931
|
+
else
|
|
932
|
+
{
|
|
933
|
+
// this is end() == rbegin()
|
|
934
|
+
curr_slot = curr_leaf->slotuse;
|
|
935
|
+
}
|
|
936
|
+
|
|
937
|
+
return tmp;
|
|
938
|
+
}
|
|
939
|
+
|
|
940
|
+
//! Equality of iterators.
|
|
941
|
+
bool operator==(const reverse_iterator& x) const
|
|
942
|
+
{
|
|
943
|
+
return (x.curr_leaf == curr_leaf) && (x.curr_slot == curr_slot);
|
|
944
|
+
}
|
|
945
|
+
|
|
946
|
+
//! Inequality of iterators.
|
|
947
|
+
bool operator!=(const reverse_iterator& x) const
|
|
948
|
+
{
|
|
949
|
+
return (x.curr_leaf != curr_leaf) || (x.curr_slot != curr_slot);
|
|
950
|
+
}
|
|
951
|
+
};
|
|
952
|
+
|
|
953
|
+
//! STL-like read-only reverse iterator object for B+ tree items. The
|
|
954
|
+
//! iterator points to a specific slot number in a leaf.
|
|
955
|
+
class const_reverse_iterator
|
|
956
|
+
{
|
|
957
|
+
public:
|
|
958
|
+
// *** Types
|
|
959
|
+
|
|
960
|
+
//! The key type of the btree. Returned by key().
|
|
961
|
+
typedef typename BTree::key_type key_type;
|
|
962
|
+
|
|
963
|
+
//! The value type of the btree. Returned by operator*().
|
|
964
|
+
typedef typename BTree::value_type value_type;
|
|
965
|
+
|
|
966
|
+
//! Reference to the value_type. STL required.
|
|
967
|
+
typedef const value_type& reference;
|
|
968
|
+
|
|
969
|
+
//! Pointer to the value_type. STL required.
|
|
970
|
+
typedef const value_type* pointer;
|
|
971
|
+
|
|
972
|
+
//! STL-magic iterator category
|
|
973
|
+
typedef std::bidirectional_iterator_tag iterator_category;
|
|
974
|
+
|
|
975
|
+
//! STL-magic
|
|
976
|
+
typedef ptrdiff_t difference_type;
|
|
977
|
+
|
|
978
|
+
//! Our own type
|
|
979
|
+
typedef const_reverse_iterator self;
|
|
980
|
+
|
|
981
|
+
private:
|
|
982
|
+
// *** Members
|
|
983
|
+
|
|
984
|
+
//! The currently referenced leaf node of the tree
|
|
985
|
+
const typename BTree::LeafNode* curr_leaf;
|
|
986
|
+
|
|
987
|
+
//! One slot past the current key/data slot referenced.
|
|
988
|
+
unsigned short curr_slot;
|
|
989
|
+
|
|
990
|
+
//! Friendly to the const_iterator, so it may access the two data items
|
|
991
|
+
//! directly.
|
|
992
|
+
friend class reverse_iterator;
|
|
993
|
+
|
|
994
|
+
// The macro TLX_BTREE_FRIENDS can be used by outside class to access
|
|
995
|
+
// the B+ tree internals. This was added for wxBTreeDemo to be able to
|
|
996
|
+
// draw the tree.
|
|
997
|
+
TLX_BTREE_FRIENDS;
|
|
998
|
+
|
|
999
|
+
public:
|
|
1000
|
+
// *** Methods
|
|
1001
|
+
|
|
1002
|
+
//! Default-Constructor of a const reverse iterator.
|
|
1003
|
+
const_reverse_iterator() : curr_leaf(nullptr), curr_slot(0)
|
|
1004
|
+
{
|
|
1005
|
+
}
|
|
1006
|
+
|
|
1007
|
+
//! Initializing-Constructor of a const reverse iterator.
|
|
1008
|
+
const_reverse_iterator(const typename BTree::LeafNode* l,
|
|
1009
|
+
unsigned short s)
|
|
1010
|
+
: curr_leaf(l), curr_slot(s)
|
|
1011
|
+
{
|
|
1012
|
+
}
|
|
1013
|
+
|
|
1014
|
+
//! Copy-constructor from a mutable iterator.
|
|
1015
|
+
const_reverse_iterator(const iterator& it)
|
|
1016
|
+
: curr_leaf(it.curr_leaf), curr_slot(it.curr_slot)
|
|
1017
|
+
{
|
|
1018
|
+
}
|
|
1019
|
+
|
|
1020
|
+
//! Copy-constructor from a const iterator.
|
|
1021
|
+
const_reverse_iterator(const const_iterator& it)
|
|
1022
|
+
: curr_leaf(it.curr_leaf), curr_slot(it.curr_slot)
|
|
1023
|
+
{
|
|
1024
|
+
}
|
|
1025
|
+
|
|
1026
|
+
//! Copy-constructor from a mutable reverse iterator.
|
|
1027
|
+
const_reverse_iterator(const reverse_iterator& it)
|
|
1028
|
+
: curr_leaf(it.curr_leaf), curr_slot(it.curr_slot)
|
|
1029
|
+
{
|
|
1030
|
+
}
|
|
1031
|
+
|
|
1032
|
+
//! Dereference the iterator.
|
|
1033
|
+
reference operator*() const
|
|
1034
|
+
{
|
|
1035
|
+
TLX_BTREE_ASSERT(curr_slot > 0);
|
|
1036
|
+
return curr_leaf->slotdata[curr_slot - 1];
|
|
1037
|
+
}
|
|
1038
|
+
|
|
1039
|
+
//! Dereference the iterator.
|
|
1040
|
+
pointer operator->() const
|
|
1041
|
+
{
|
|
1042
|
+
TLX_BTREE_ASSERT(curr_slot > 0);
|
|
1043
|
+
return &curr_leaf->slotdata[curr_slot - 1];
|
|
1044
|
+
}
|
|
1045
|
+
|
|
1046
|
+
//! Key of the current slot.
|
|
1047
|
+
const key_type& key() const
|
|
1048
|
+
{
|
|
1049
|
+
TLX_BTREE_ASSERT(curr_slot > 0);
|
|
1050
|
+
return curr_leaf->key(curr_slot - 1);
|
|
1051
|
+
}
|
|
1052
|
+
|
|
1053
|
+
//! Prefix++ advance the iterator to the previous slot.
|
|
1054
|
+
const_reverse_iterator& operator++()
|
|
1055
|
+
{
|
|
1056
|
+
if (curr_slot > 1)
|
|
1057
|
+
{
|
|
1058
|
+
--curr_slot;
|
|
1059
|
+
}
|
|
1060
|
+
else if (curr_leaf->prev_leaf != nullptr)
|
|
1061
|
+
{
|
|
1062
|
+
curr_leaf = curr_leaf->prev_leaf;
|
|
1063
|
+
curr_slot = curr_leaf->slotuse;
|
|
1064
|
+
}
|
|
1065
|
+
else
|
|
1066
|
+
{
|
|
1067
|
+
// this is begin() == rend()
|
|
1068
|
+
curr_slot = 0;
|
|
1069
|
+
}
|
|
1070
|
+
|
|
1071
|
+
return *this;
|
|
1072
|
+
}
|
|
1073
|
+
|
|
1074
|
+
//! Postfix++ advance the iterator to the previous slot.
|
|
1075
|
+
const_reverse_iterator operator++(int)
|
|
1076
|
+
{
|
|
1077
|
+
const_reverse_iterator tmp = *this; // copy ourselves
|
|
1078
|
+
|
|
1079
|
+
if (curr_slot > 1)
|
|
1080
|
+
{
|
|
1081
|
+
--curr_slot;
|
|
1082
|
+
}
|
|
1083
|
+
else if (curr_leaf->prev_leaf != nullptr)
|
|
1084
|
+
{
|
|
1085
|
+
curr_leaf = curr_leaf->prev_leaf;
|
|
1086
|
+
curr_slot = curr_leaf->slotuse;
|
|
1087
|
+
}
|
|
1088
|
+
else
|
|
1089
|
+
{
|
|
1090
|
+
// this is begin() == rend()
|
|
1091
|
+
curr_slot = 0;
|
|
1092
|
+
}
|
|
1093
|
+
|
|
1094
|
+
return tmp;
|
|
1095
|
+
}
|
|
1096
|
+
|
|
1097
|
+
//! Prefix-- backstep the iterator to the next slot.
|
|
1098
|
+
const_reverse_iterator& operator--()
|
|
1099
|
+
{
|
|
1100
|
+
if (curr_slot < curr_leaf->slotuse)
|
|
1101
|
+
{
|
|
1102
|
+
++curr_slot;
|
|
1103
|
+
}
|
|
1104
|
+
else if (curr_leaf->next_leaf != nullptr)
|
|
1105
|
+
{
|
|
1106
|
+
curr_leaf = curr_leaf->next_leaf;
|
|
1107
|
+
curr_slot = 1;
|
|
1108
|
+
}
|
|
1109
|
+
else
|
|
1110
|
+
{
|
|
1111
|
+
// this is end() == rbegin()
|
|
1112
|
+
curr_slot = curr_leaf->slotuse;
|
|
1113
|
+
}
|
|
1114
|
+
|
|
1115
|
+
return *this;
|
|
1116
|
+
}
|
|
1117
|
+
|
|
1118
|
+
//! Postfix-- backstep the iterator to the next slot.
|
|
1119
|
+
const_reverse_iterator operator--(int)
|
|
1120
|
+
{
|
|
1121
|
+
const_reverse_iterator tmp = *this; // copy ourselves
|
|
1122
|
+
|
|
1123
|
+
if (curr_slot < curr_leaf->slotuse)
|
|
1124
|
+
{
|
|
1125
|
+
++curr_slot;
|
|
1126
|
+
}
|
|
1127
|
+
else if (curr_leaf->next_leaf != nullptr)
|
|
1128
|
+
{
|
|
1129
|
+
curr_leaf = curr_leaf->next_leaf;
|
|
1130
|
+
curr_slot = 1;
|
|
1131
|
+
}
|
|
1132
|
+
else
|
|
1133
|
+
{
|
|
1134
|
+
// this is end() == rbegin()
|
|
1135
|
+
curr_slot = curr_leaf->slotuse;
|
|
1136
|
+
}
|
|
1137
|
+
|
|
1138
|
+
return tmp;
|
|
1139
|
+
}
|
|
1140
|
+
|
|
1141
|
+
//! Equality of iterators.
|
|
1142
|
+
bool operator==(const const_reverse_iterator& x) const
|
|
1143
|
+
{
|
|
1144
|
+
return (x.curr_leaf == curr_leaf) && (x.curr_slot == curr_slot);
|
|
1145
|
+
}
|
|
1146
|
+
|
|
1147
|
+
//! Inequality of iterators.
|
|
1148
|
+
bool operator!=(const const_reverse_iterator& x) const
|
|
1149
|
+
{
|
|
1150
|
+
return (x.curr_leaf != curr_leaf) || (x.curr_slot != curr_slot);
|
|
1151
|
+
}
|
|
1152
|
+
};
|
|
1153
|
+
|
|
1154
|
+
//! \}
|
|
1155
|
+
|
|
1156
|
+
public:
|
|
1157
|
+
//! \name Small Statistics Structure
|
|
1158
|
+
//! \{
|
|
1159
|
+
|
|
1160
|
+
/*!
|
|
1161
|
+
* A small struct containing basic statistics about the B+ tree. It can be
|
|
1162
|
+
* fetched using get_stats().
|
|
1163
|
+
*/
|
|
1164
|
+
struct tree_stats
|
|
1165
|
+
{
|
|
1166
|
+
//! Number of items in the B+ tree
|
|
1167
|
+
size_type size = 0;
|
|
1168
|
+
|
|
1169
|
+
//! Number of leaves in the B+ tree
|
|
1170
|
+
size_type leaves = 0;
|
|
1171
|
+
|
|
1172
|
+
//! Number of inner nodes in the B+ tree
|
|
1173
|
+
size_type inner_nodes = 0;
|
|
1174
|
+
|
|
1175
|
+
//! Base B+ tree parameter: The number of key/data slots in each leaf
|
|
1176
|
+
static const unsigned short leaf_slots = Self::leaf_slotmax;
|
|
1177
|
+
|
|
1178
|
+
//! Base B+ tree parameter: The number of key slots in each inner node.
|
|
1179
|
+
static const unsigned short inner_slots = Self::inner_slotmax;
|
|
1180
|
+
|
|
1181
|
+
//! Return the total number of nodes
|
|
1182
|
+
size_type nodes() const
|
|
1183
|
+
{
|
|
1184
|
+
return inner_nodes + leaves;
|
|
1185
|
+
}
|
|
1186
|
+
|
|
1187
|
+
//! Return the average fill of leaves
|
|
1188
|
+
double avgfill_leaves() const
|
|
1189
|
+
{
|
|
1190
|
+
return static_cast<double>(size) / (leaves * leaf_slots);
|
|
1191
|
+
}
|
|
1192
|
+
};
|
|
1193
|
+
|
|
1194
|
+
//! \}
|
|
1195
|
+
|
|
1196
|
+
private:
|
|
1197
|
+
//! \name Tree Object Data Members
|
|
1198
|
+
//! \{
|
|
1199
|
+
|
|
1200
|
+
//! Pointer to the B+ tree's root node, either leaf or inner node.
|
|
1201
|
+
node* root_;
|
|
1202
|
+
|
|
1203
|
+
//! Pointer to first leaf in the double linked leaf chain.
|
|
1204
|
+
LeafNode* head_leaf_;
|
|
1205
|
+
|
|
1206
|
+
//! Pointer to last leaf in the double linked leaf chain.
|
|
1207
|
+
LeafNode* tail_leaf_;
|
|
1208
|
+
|
|
1209
|
+
//! Other small statistics about the B+ tree.
|
|
1210
|
+
tree_stats stats_;
|
|
1211
|
+
|
|
1212
|
+
//! Key comparison object. More comparison functions are generated from
|
|
1213
|
+
//! this < relation.
|
|
1214
|
+
key_compare key_less_;
|
|
1215
|
+
|
|
1216
|
+
//! Memory allocator.
|
|
1217
|
+
allocator_type allocator_;
|
|
1218
|
+
|
|
1219
|
+
//! \}
|
|
1220
|
+
|
|
1221
|
+
public:
|
|
1222
|
+
//! \name Constructors and Destructor
|
|
1223
|
+
//! \{
|
|
1224
|
+
|
|
1225
|
+
//! Default constructor initializing an empty B+ tree with the standard key
|
|
1226
|
+
//! comparison function.
|
|
1227
|
+
explicit BTree(const allocator_type& alloc = allocator_type())
|
|
1228
|
+
: root_(nullptr),
|
|
1229
|
+
head_leaf_(nullptr),
|
|
1230
|
+
tail_leaf_(nullptr),
|
|
1231
|
+
allocator_(alloc)
|
|
1232
|
+
{
|
|
1233
|
+
}
|
|
1234
|
+
|
|
1235
|
+
//! Constructor initializing an empty B+ tree with a special key
|
|
1236
|
+
//! comparison object.
|
|
1237
|
+
explicit BTree(const key_compare& kcf,
|
|
1238
|
+
const allocator_type& alloc = allocator_type())
|
|
1239
|
+
: root_(nullptr),
|
|
1240
|
+
head_leaf_(nullptr),
|
|
1241
|
+
tail_leaf_(nullptr),
|
|
1242
|
+
key_less_(kcf),
|
|
1243
|
+
allocator_(alloc)
|
|
1244
|
+
{
|
|
1245
|
+
}
|
|
1246
|
+
|
|
1247
|
+
//! Constructor initializing a B+ tree with the range [first,last). The
|
|
1248
|
+
//! range need not be sorted. To create a B+ tree from a sorted range, use
|
|
1249
|
+
//! bulk_load().
|
|
1250
|
+
template <class InputIterator>
|
|
1251
|
+
BTree(InputIterator first, InputIterator last,
|
|
1252
|
+
const allocator_type& alloc = allocator_type())
|
|
1253
|
+
: root_(nullptr),
|
|
1254
|
+
head_leaf_(nullptr),
|
|
1255
|
+
tail_leaf_(nullptr),
|
|
1256
|
+
allocator_(alloc)
|
|
1257
|
+
{
|
|
1258
|
+
insert(first, last);
|
|
1259
|
+
}
|
|
1260
|
+
|
|
1261
|
+
//! Constructor initializing a B+ tree with the range [first,last) and a
|
|
1262
|
+
//! special key comparison object. The range need not be sorted. To create
|
|
1263
|
+
//! a B+ tree from a sorted range, use bulk_load().
|
|
1264
|
+
template <class InputIterator>
|
|
1265
|
+
BTree(InputIterator first, InputIterator last, const key_compare& kcf,
|
|
1266
|
+
const allocator_type& alloc = allocator_type())
|
|
1267
|
+
: root_(nullptr),
|
|
1268
|
+
head_leaf_(nullptr),
|
|
1269
|
+
tail_leaf_(nullptr),
|
|
1270
|
+
key_less_(kcf),
|
|
1271
|
+
allocator_(alloc)
|
|
1272
|
+
{
|
|
1273
|
+
insert(first, last);
|
|
1274
|
+
}
|
|
1275
|
+
|
|
1276
|
+
//! Frees up all used B+ tree memory pages
|
|
1277
|
+
~BTree()
|
|
1278
|
+
{
|
|
1279
|
+
clear();
|
|
1280
|
+
}
|
|
1281
|
+
|
|
1282
|
+
//! Fast swapping of two identical B+ tree objects.
|
|
1283
|
+
void swap(BTree& from) noexcept
|
|
1284
|
+
{
|
|
1285
|
+
std::swap(root_, from.root_);
|
|
1286
|
+
std::swap(head_leaf_, from.head_leaf_);
|
|
1287
|
+
std::swap(tail_leaf_, from.tail_leaf_);
|
|
1288
|
+
std::swap(stats_, from.stats_);
|
|
1289
|
+
std::swap(key_less_, from.key_less_);
|
|
1290
|
+
std::swap(allocator_, from.allocator_);
|
|
1291
|
+
}
|
|
1292
|
+
|
|
1293
|
+
//! \}
|
|
1294
|
+
|
|
1295
|
+
public:
|
|
1296
|
+
//! \name Key and Value Comparison Function Objects
|
|
1297
|
+
//! \{
|
|
1298
|
+
|
|
1299
|
+
//! Function class to compare value_type objects. Required by the STL
|
|
1300
|
+
class value_compare
|
|
1301
|
+
{
|
|
1302
|
+
private:
|
|
1303
|
+
//! Key comparison function from the template parameter
|
|
1304
|
+
key_compare key_comp;
|
|
1305
|
+
|
|
1306
|
+
//! Constructor called from BTree::value_comp()
|
|
1307
|
+
explicit value_compare(key_compare kc) : key_comp(kc)
|
|
1308
|
+
{
|
|
1309
|
+
}
|
|
1310
|
+
|
|
1311
|
+
//! Friendly to the btree class so it may call the constructor
|
|
1312
|
+
friend class BTree<key_type, value_type, key_of_value, key_compare,
|
|
1313
|
+
traits, allow_duplicates, allocator_type>;
|
|
1314
|
+
|
|
1315
|
+
public:
|
|
1316
|
+
//! Function call "less"-operator resulting in true if x < y.
|
|
1317
|
+
bool operator()(const value_type& x, const value_type& y) const
|
|
1318
|
+
{
|
|
1319
|
+
return key_comp(x.first, y.first);
|
|
1320
|
+
}
|
|
1321
|
+
};
|
|
1322
|
+
|
|
1323
|
+
//! Constant access to the key comparison object sorting the B+ tree.
|
|
1324
|
+
key_compare key_comp() const
|
|
1325
|
+
{
|
|
1326
|
+
return key_less_;
|
|
1327
|
+
}
|
|
1328
|
+
|
|
1329
|
+
//! Constant access to a constructed value_type comparison object. Required
|
|
1330
|
+
//! by the STL.
|
|
1331
|
+
value_compare value_comp() const
|
|
1332
|
+
{
|
|
1333
|
+
return value_compare(key_less_);
|
|
1334
|
+
}
|
|
1335
|
+
|
|
1336
|
+
//! \}
|
|
1337
|
+
|
|
1338
|
+
private:
|
|
1339
|
+
//! \name Convenient Key Comparison Functions Generated From key_less
|
|
1340
|
+
//! \{
|
|
1341
|
+
|
|
1342
|
+
//! True if a < b ? "constructed" from key_less_()
|
|
1343
|
+
bool key_less(const key_type& a, const key_type& b) const
|
|
1344
|
+
{
|
|
1345
|
+
return key_less_(a, b);
|
|
1346
|
+
}
|
|
1347
|
+
|
|
1348
|
+
//! True if a <= b ? constructed from key_less()
|
|
1349
|
+
bool key_lessequal(const key_type& a, const key_type& b) const
|
|
1350
|
+
{
|
|
1351
|
+
return !key_less_(b, a);
|
|
1352
|
+
}
|
|
1353
|
+
|
|
1354
|
+
//! True if a > b ? constructed from key_less()
|
|
1355
|
+
bool key_greater(const key_type& a, const key_type& b) const
|
|
1356
|
+
{
|
|
1357
|
+
return key_less_(b, a);
|
|
1358
|
+
}
|
|
1359
|
+
|
|
1360
|
+
//! True if a >= b ? constructed from key_less()
|
|
1361
|
+
bool key_greaterequal(const key_type& a, const key_type& b) const
|
|
1362
|
+
{
|
|
1363
|
+
return !key_less_(a, b);
|
|
1364
|
+
}
|
|
1365
|
+
|
|
1366
|
+
//! True if a == b ? constructed from key_less(). This requires the <
|
|
1367
|
+
//! relation to be a total order, otherwise the B+ tree cannot be sorted.
|
|
1368
|
+
bool key_equal(const key_type& a, const key_type& b) const
|
|
1369
|
+
{
|
|
1370
|
+
return !key_less_(a, b) && !key_less_(b, a);
|
|
1371
|
+
}
|
|
1372
|
+
|
|
1373
|
+
//! \}
|
|
1374
|
+
|
|
1375
|
+
public:
|
|
1376
|
+
//! \name Allocators
|
|
1377
|
+
//! \{
|
|
1378
|
+
|
|
1379
|
+
//! Return the base node allocator provided during construction.
|
|
1380
|
+
allocator_type get_allocator() const
|
|
1381
|
+
{
|
|
1382
|
+
return allocator_;
|
|
1383
|
+
}
|
|
1384
|
+
|
|
1385
|
+
//! \}
|
|
1386
|
+
|
|
1387
|
+
private:
|
|
1388
|
+
//! \name Node Object Allocation and Deallocation Functions
|
|
1389
|
+
//! \{
|
|
1390
|
+
|
|
1391
|
+
//! Return an allocator for LeafNode objects.
|
|
1392
|
+
typename LeafNode::alloc_type leaf_node_allocator()
|
|
1393
|
+
{
|
|
1394
|
+
return typename LeafNode::alloc_type(allocator_);
|
|
1395
|
+
}
|
|
1396
|
+
|
|
1397
|
+
//! Return an allocator for InnerNode objects.
|
|
1398
|
+
typename InnerNode::alloc_type inner_node_allocator()
|
|
1399
|
+
{
|
|
1400
|
+
return typename InnerNode::alloc_type(allocator_);
|
|
1401
|
+
}
|
|
1402
|
+
|
|
1403
|
+
//! Allocate and initialize a leaf node
|
|
1404
|
+
LeafNode* allocate_leaf()
|
|
1405
|
+
{
|
|
1406
|
+
LeafNode* n = new (leaf_node_allocator().allocate(1)) LeafNode();
|
|
1407
|
+
n->initialize();
|
|
1408
|
+
stats_.leaves++;
|
|
1409
|
+
return n;
|
|
1410
|
+
}
|
|
1411
|
+
|
|
1412
|
+
//! Allocate and initialize an inner node
|
|
1413
|
+
InnerNode* allocate_inner(unsigned short level)
|
|
1414
|
+
{
|
|
1415
|
+
InnerNode* n = new (inner_node_allocator().allocate(1)) InnerNode();
|
|
1416
|
+
n->initialize(level);
|
|
1417
|
+
stats_.inner_nodes++;
|
|
1418
|
+
return n;
|
|
1419
|
+
}
|
|
1420
|
+
|
|
1421
|
+
//! Correctly free either inner or leaf node, destructs all contained key
|
|
1422
|
+
//! and value objects.
|
|
1423
|
+
void free_node(node* n)
|
|
1424
|
+
{
|
|
1425
|
+
if (n->is_leafnode())
|
|
1426
|
+
{
|
|
1427
|
+
LeafNode* ln = static_cast<LeafNode*>(n);
|
|
1428
|
+
typename LeafNode::alloc_type a(leaf_node_allocator());
|
|
1429
|
+
std::allocator_traits<typename LeafNode::alloc_type>::destroy(a,
|
|
1430
|
+
ln);
|
|
1431
|
+
std::allocator_traits<typename LeafNode::alloc_type>::deallocate(
|
|
1432
|
+
a, ln, 1);
|
|
1433
|
+
stats_.leaves--;
|
|
1434
|
+
}
|
|
1435
|
+
else
|
|
1436
|
+
{
|
|
1437
|
+
InnerNode* in = static_cast<InnerNode*>(n);
|
|
1438
|
+
typename InnerNode::alloc_type a(inner_node_allocator());
|
|
1439
|
+
std::allocator_traits<typename InnerNode::alloc_type>::destroy(a,
|
|
1440
|
+
in);
|
|
1441
|
+
std::allocator_traits<typename InnerNode::alloc_type>::deallocate(
|
|
1442
|
+
a, in, 1);
|
|
1443
|
+
stats_.inner_nodes--;
|
|
1444
|
+
}
|
|
1445
|
+
}
|
|
1446
|
+
|
|
1447
|
+
//! \}
|
|
1448
|
+
|
|
1449
|
+
public:
|
|
1450
|
+
//! \name Fast Destruction of the B+ Tree
|
|
1451
|
+
//! \{
|
|
1452
|
+
|
|
1453
|
+
//! Frees all key/data pairs and all nodes of the tree.
|
|
1454
|
+
void clear()
|
|
1455
|
+
{
|
|
1456
|
+
if (root_)
|
|
1457
|
+
{
|
|
1458
|
+
clear_recursive(root_);
|
|
1459
|
+
free_node(root_);
|
|
1460
|
+
|
|
1461
|
+
root_ = nullptr;
|
|
1462
|
+
head_leaf_ = tail_leaf_ = nullptr;
|
|
1463
|
+
|
|
1464
|
+
stats_ = tree_stats();
|
|
1465
|
+
}
|
|
1466
|
+
|
|
1467
|
+
TLX_BTREE_ASSERT(stats_.size == 0);
|
|
1468
|
+
}
|
|
1469
|
+
|
|
1470
|
+
private:
|
|
1471
|
+
//! Recursively free up nodes.
|
|
1472
|
+
void clear_recursive(node* n)
|
|
1473
|
+
{
|
|
1474
|
+
if (n->is_leafnode())
|
|
1475
|
+
{
|
|
1476
|
+
LeafNode* leafnode = static_cast<LeafNode*>(n);
|
|
1477
|
+
|
|
1478
|
+
for (unsigned short slot = 0; slot < leafnode->slotuse; ++slot)
|
|
1479
|
+
{
|
|
1480
|
+
// data objects are deleted by LeafNode's destructor
|
|
1481
|
+
}
|
|
1482
|
+
}
|
|
1483
|
+
else
|
|
1484
|
+
{
|
|
1485
|
+
InnerNode* innernode = static_cast<InnerNode*>(n);
|
|
1486
|
+
|
|
1487
|
+
for (unsigned short slot = 0; slot < innernode->slotuse + 1; ++slot)
|
|
1488
|
+
{
|
|
1489
|
+
clear_recursive(innernode->childid[slot]);
|
|
1490
|
+
free_node(innernode->childid[slot]);
|
|
1491
|
+
}
|
|
1492
|
+
}
|
|
1493
|
+
}
|
|
1494
|
+
|
|
1495
|
+
//! \}
|
|
1496
|
+
|
|
1497
|
+
public:
|
|
1498
|
+
//! \name STL Iterator Construction Functions
|
|
1499
|
+
//! \{
|
|
1500
|
+
|
|
1501
|
+
//! Constructs a read/data-write iterator that points to the first slot in
|
|
1502
|
+
//! the first leaf of the B+ tree.
|
|
1503
|
+
iterator begin()
|
|
1504
|
+
{
|
|
1505
|
+
return iterator(head_leaf_, 0);
|
|
1506
|
+
}
|
|
1507
|
+
|
|
1508
|
+
//! Constructs a read/data-write iterator that points to the first invalid
|
|
1509
|
+
//! slot in the last leaf of the B+ tree.
|
|
1510
|
+
iterator end()
|
|
1511
|
+
{
|
|
1512
|
+
return iterator(tail_leaf_, tail_leaf_ ? tail_leaf_->slotuse : 0);
|
|
1513
|
+
}
|
|
1514
|
+
|
|
1515
|
+
//! Constructs a read-only constant iterator that points to the first slot
|
|
1516
|
+
//! in the first leaf of the B+ tree.
|
|
1517
|
+
const_iterator begin() const
|
|
1518
|
+
{
|
|
1519
|
+
return const_iterator(head_leaf_, 0);
|
|
1520
|
+
}
|
|
1521
|
+
|
|
1522
|
+
//! Constructs a read-only constant iterator that points to the first
|
|
1523
|
+
//! invalid slot in the last leaf of the B+ tree.
|
|
1524
|
+
const_iterator end() const
|
|
1525
|
+
{
|
|
1526
|
+
return const_iterator(tail_leaf_, tail_leaf_ ? tail_leaf_->slotuse : 0);
|
|
1527
|
+
}
|
|
1528
|
+
|
|
1529
|
+
//! Constructs a read/data-write reverse iterator that points to the first
|
|
1530
|
+
//! invalid slot in the last leaf of the B+ tree. Uses STL magic.
|
|
1531
|
+
reverse_iterator rbegin()
|
|
1532
|
+
{
|
|
1533
|
+
return reverse_iterator(end());
|
|
1534
|
+
}
|
|
1535
|
+
|
|
1536
|
+
//! Constructs a read/data-write reverse iterator that points to the first
|
|
1537
|
+
//! slot in the first leaf of the B+ tree. Uses STL magic.
|
|
1538
|
+
reverse_iterator rend()
|
|
1539
|
+
{
|
|
1540
|
+
return reverse_iterator(begin());
|
|
1541
|
+
}
|
|
1542
|
+
|
|
1543
|
+
//! Constructs a read-only reverse iterator that points to the first
|
|
1544
|
+
//! invalid slot in the last leaf of the B+ tree. Uses STL magic.
|
|
1545
|
+
const_reverse_iterator rbegin() const
|
|
1546
|
+
{
|
|
1547
|
+
return const_reverse_iterator(end());
|
|
1548
|
+
}
|
|
1549
|
+
|
|
1550
|
+
//! Constructs a read-only reverse iterator that points to the first slot
|
|
1551
|
+
//! in the first leaf of the B+ tree. Uses STL magic.
|
|
1552
|
+
const_reverse_iterator rend() const
|
|
1553
|
+
{
|
|
1554
|
+
return const_reverse_iterator(begin());
|
|
1555
|
+
}
|
|
1556
|
+
|
|
1557
|
+
//! \}
|
|
1558
|
+
|
|
1559
|
+
private:
|
|
1560
|
+
//! \name B+ Tree Node Binary Search Functions
|
|
1561
|
+
//! \{
|
|
1562
|
+
|
|
1563
|
+
//! Searches for the first key in the node n greater or equal to key. Uses
|
|
1564
|
+
//! binary search with an optional linear self-verification. This is a
|
|
1565
|
+
//! template function, because the slotkey array is located at different
|
|
1566
|
+
//! places in LeafNode and InnerNode.
|
|
1567
|
+
template <typename node_type>
|
|
1568
|
+
unsigned short find_lower(const node_type* n, const key_type& key) const
|
|
1569
|
+
{
|
|
1570
|
+
if (sizeof(*n) > traits::binsearch_threshold)
|
|
1571
|
+
{
|
|
1572
|
+
if (n->slotuse == 0)
|
|
1573
|
+
return 0;
|
|
1574
|
+
|
|
1575
|
+
unsigned short lo = 0, hi = n->slotuse;
|
|
1576
|
+
|
|
1577
|
+
while (lo < hi)
|
|
1578
|
+
{
|
|
1579
|
+
unsigned short mid = (lo + hi) >> 1;
|
|
1580
|
+
|
|
1581
|
+
if (key_lessequal(key, n->key(mid)))
|
|
1582
|
+
{
|
|
1583
|
+
hi = mid; // key <= mid
|
|
1584
|
+
}
|
|
1585
|
+
else
|
|
1586
|
+
{
|
|
1587
|
+
lo = mid + 1; // key > mid
|
|
1588
|
+
}
|
|
1589
|
+
}
|
|
1590
|
+
|
|
1591
|
+
TLX_BTREE_PRINT("BTree::find_lower: on " << n << " key " << key
|
|
1592
|
+
<< " -> " << lo << " / "
|
|
1593
|
+
<< hi);
|
|
1594
|
+
|
|
1595
|
+
// verify result using simple linear search
|
|
1596
|
+
if (self_verify)
|
|
1597
|
+
{
|
|
1598
|
+
unsigned short i = 0;
|
|
1599
|
+
while (i < n->slotuse && key_less(n->key(i), key))
|
|
1600
|
+
++i;
|
|
1601
|
+
|
|
1602
|
+
TLX_BTREE_PRINT("BTree::find_lower: testfind: " << i);
|
|
1603
|
+
TLX_BTREE_ASSERT(i == lo);
|
|
1604
|
+
}
|
|
1605
|
+
|
|
1606
|
+
return lo;
|
|
1607
|
+
}
|
|
1608
|
+
|
|
1609
|
+
// for nodes <= binsearch_threshold do linear search.
|
|
1610
|
+
unsigned short lo = 0;
|
|
1611
|
+
while (lo < n->slotuse && key_less(n->key(lo), key))
|
|
1612
|
+
++lo;
|
|
1613
|
+
return lo;
|
|
1614
|
+
}
|
|
1615
|
+
|
|
1616
|
+
//! Searches for the first key in the node n greater than key. Uses binary
|
|
1617
|
+
//! search with an optional linear self-verification. This is a template
|
|
1618
|
+
//! function, because the slotkey array is located at different places in
|
|
1619
|
+
//! LeafNode and InnerNode.
|
|
1620
|
+
template <typename node_type>
|
|
1621
|
+
unsigned short find_upper(const node_type* n, const key_type& key) const
|
|
1622
|
+
{
|
|
1623
|
+
if (sizeof(*n) > traits::binsearch_threshold)
|
|
1624
|
+
{
|
|
1625
|
+
if (n->slotuse == 0)
|
|
1626
|
+
return 0;
|
|
1627
|
+
|
|
1628
|
+
unsigned short lo = 0, hi = n->slotuse;
|
|
1629
|
+
|
|
1630
|
+
while (lo < hi)
|
|
1631
|
+
{
|
|
1632
|
+
unsigned short mid = (lo + hi) >> 1;
|
|
1633
|
+
|
|
1634
|
+
if (key_less(key, n->key(mid)))
|
|
1635
|
+
{
|
|
1636
|
+
hi = mid; // key < mid
|
|
1637
|
+
}
|
|
1638
|
+
else
|
|
1639
|
+
{
|
|
1640
|
+
lo = mid + 1; // key >= mid
|
|
1641
|
+
}
|
|
1642
|
+
}
|
|
1643
|
+
|
|
1644
|
+
TLX_BTREE_PRINT("BTree::find_upper: on " << n << " key " << key
|
|
1645
|
+
<< " -> " << lo << " / "
|
|
1646
|
+
<< hi);
|
|
1647
|
+
|
|
1648
|
+
// verify result using simple linear search
|
|
1649
|
+
if (self_verify)
|
|
1650
|
+
{
|
|
1651
|
+
unsigned short i = 0;
|
|
1652
|
+
while (i < n->slotuse && key_lessequal(n->key(i), key))
|
|
1653
|
+
++i;
|
|
1654
|
+
|
|
1655
|
+
TLX_BTREE_PRINT("BTree::find_upper testfind: " << i);
|
|
1656
|
+
TLX_BTREE_ASSERT(i == hi);
|
|
1657
|
+
}
|
|
1658
|
+
|
|
1659
|
+
return lo;
|
|
1660
|
+
}
|
|
1661
|
+
|
|
1662
|
+
// for nodes <= binsearch_threshold do linear search.
|
|
1663
|
+
unsigned short lo = 0;
|
|
1664
|
+
while (lo < n->slotuse && key_lessequal(n->key(lo), key))
|
|
1665
|
+
++lo;
|
|
1666
|
+
return lo;
|
|
1667
|
+
}
|
|
1668
|
+
|
|
1669
|
+
//! \}
|
|
1670
|
+
|
|
1671
|
+
public:
|
|
1672
|
+
//! \name Access Functions to the Item Count
|
|
1673
|
+
//! \{
|
|
1674
|
+
|
|
1675
|
+
//! Return the number of key/data pairs in the B+ tree
|
|
1676
|
+
size_type size() const
|
|
1677
|
+
{
|
|
1678
|
+
return stats_.size;
|
|
1679
|
+
}
|
|
1680
|
+
|
|
1681
|
+
//! Returns true if there is at least one key/data pair in the B+ tree
|
|
1682
|
+
bool empty() const
|
|
1683
|
+
{
|
|
1684
|
+
return (size() == size_type(0));
|
|
1685
|
+
}
|
|
1686
|
+
|
|
1687
|
+
//! Returns the largest possible size of the B+ Tree. This is just a
|
|
1688
|
+
//! function required by the STL standard, the B+ Tree can hold more items.
|
|
1689
|
+
size_type max_size() const
|
|
1690
|
+
{
|
|
1691
|
+
return size_type(-1);
|
|
1692
|
+
}
|
|
1693
|
+
|
|
1694
|
+
//! Return a const reference to the current statistics.
|
|
1695
|
+
const struct tree_stats& get_stats() const
|
|
1696
|
+
{
|
|
1697
|
+
return stats_;
|
|
1698
|
+
}
|
|
1699
|
+
|
|
1700
|
+
//! \}
|
|
1701
|
+
|
|
1702
|
+
public:
|
|
1703
|
+
//! \name STL Access Functions Querying the Tree by Descending to a Leaf
|
|
1704
|
+
//! \{
|
|
1705
|
+
|
|
1706
|
+
//! Non-STL function checking whether a key is in the B+ tree. The same as
|
|
1707
|
+
//! (find(k) != end()) or (count() != 0).
|
|
1708
|
+
bool exists(const key_type& key) const
|
|
1709
|
+
{
|
|
1710
|
+
const node* n = root_;
|
|
1711
|
+
if (!n)
|
|
1712
|
+
return false;
|
|
1713
|
+
|
|
1714
|
+
while (!n->is_leafnode())
|
|
1715
|
+
{
|
|
1716
|
+
const InnerNode* inner = static_cast<const InnerNode*>(n);
|
|
1717
|
+
unsigned short slot = find_lower(inner, key);
|
|
1718
|
+
|
|
1719
|
+
n = inner->childid[slot];
|
|
1720
|
+
}
|
|
1721
|
+
|
|
1722
|
+
const LeafNode* leaf = static_cast<const LeafNode*>(n);
|
|
1723
|
+
|
|
1724
|
+
unsigned short slot = find_lower(leaf, key);
|
|
1725
|
+
return (slot < leaf->slotuse && key_equal(key, leaf->key(slot)));
|
|
1726
|
+
}
|
|
1727
|
+
|
|
1728
|
+
//! Tries to locate a key in the B+ tree and returns an iterator to the
|
|
1729
|
+
//! key/data slot if found. If unsuccessful it returns end().
|
|
1730
|
+
iterator find(const key_type& key)
|
|
1731
|
+
{
|
|
1732
|
+
node* n = root_;
|
|
1733
|
+
if (!n)
|
|
1734
|
+
return end();
|
|
1735
|
+
|
|
1736
|
+
while (!n->is_leafnode())
|
|
1737
|
+
{
|
|
1738
|
+
const InnerNode* inner = static_cast<const InnerNode*>(n);
|
|
1739
|
+
unsigned short slot = find_lower(inner, key);
|
|
1740
|
+
|
|
1741
|
+
n = inner->childid[slot];
|
|
1742
|
+
}
|
|
1743
|
+
|
|
1744
|
+
LeafNode* leaf = static_cast<LeafNode*>(n);
|
|
1745
|
+
|
|
1746
|
+
unsigned short slot = find_lower(leaf, key);
|
|
1747
|
+
return (slot < leaf->slotuse && key_equal(key, leaf->key(slot))) ?
|
|
1748
|
+
iterator(leaf, slot) :
|
|
1749
|
+
end();
|
|
1750
|
+
}
|
|
1751
|
+
|
|
1752
|
+
//! Tries to locate a key in the B+ tree and returns an constant iterator to
|
|
1753
|
+
//! the key/data slot if found. If unsuccessful it returns end().
|
|
1754
|
+
const_iterator find(const key_type& key) const
|
|
1755
|
+
{
|
|
1756
|
+
const node* n = root_;
|
|
1757
|
+
if (!n)
|
|
1758
|
+
return end();
|
|
1759
|
+
|
|
1760
|
+
while (!n->is_leafnode())
|
|
1761
|
+
{
|
|
1762
|
+
const InnerNode* inner = static_cast<const InnerNode*>(n);
|
|
1763
|
+
unsigned short slot = find_lower(inner, key);
|
|
1764
|
+
|
|
1765
|
+
n = inner->childid[slot];
|
|
1766
|
+
}
|
|
1767
|
+
|
|
1768
|
+
const LeafNode* leaf = static_cast<const LeafNode*>(n);
|
|
1769
|
+
|
|
1770
|
+
unsigned short slot = find_lower(leaf, key);
|
|
1771
|
+
return (slot < leaf->slotuse && key_equal(key, leaf->key(slot))) ?
|
|
1772
|
+
const_iterator(leaf, slot) :
|
|
1773
|
+
end();
|
|
1774
|
+
}
|
|
1775
|
+
|
|
1776
|
+
//! Tries to locate a key in the B+ tree and returns the number of identical
|
|
1777
|
+
//! key entries found.
|
|
1778
|
+
size_type count(const key_type& key) const
|
|
1779
|
+
{
|
|
1780
|
+
const node* n = root_;
|
|
1781
|
+
if (!n)
|
|
1782
|
+
return 0;
|
|
1783
|
+
|
|
1784
|
+
while (!n->is_leafnode())
|
|
1785
|
+
{
|
|
1786
|
+
const InnerNode* inner = static_cast<const InnerNode*>(n);
|
|
1787
|
+
unsigned short slot = find_lower(inner, key);
|
|
1788
|
+
|
|
1789
|
+
n = inner->childid[slot];
|
|
1790
|
+
}
|
|
1791
|
+
|
|
1792
|
+
const LeafNode* leaf = static_cast<const LeafNode*>(n);
|
|
1793
|
+
|
|
1794
|
+
unsigned short slot = find_lower(leaf, key);
|
|
1795
|
+
size_type num = 0;
|
|
1796
|
+
|
|
1797
|
+
while (leaf && slot < leaf->slotuse && key_equal(key, leaf->key(slot)))
|
|
1798
|
+
{
|
|
1799
|
+
++num;
|
|
1800
|
+
if (++slot >= leaf->slotuse)
|
|
1801
|
+
{
|
|
1802
|
+
leaf = leaf->next_leaf;
|
|
1803
|
+
slot = 0;
|
|
1804
|
+
}
|
|
1805
|
+
}
|
|
1806
|
+
|
|
1807
|
+
return num;
|
|
1808
|
+
}
|
|
1809
|
+
|
|
1810
|
+
//! Searches the B+ tree and returns an iterator to the first pair equal to
|
|
1811
|
+
//! or greater than key, or end() if all keys are smaller.
|
|
1812
|
+
iterator lower_bound(const key_type& key)
|
|
1813
|
+
{
|
|
1814
|
+
node* n = root_;
|
|
1815
|
+
if (!n)
|
|
1816
|
+
return end();
|
|
1817
|
+
|
|
1818
|
+
while (!n->is_leafnode())
|
|
1819
|
+
{
|
|
1820
|
+
const InnerNode* inner = static_cast<const InnerNode*>(n);
|
|
1821
|
+
unsigned short slot = find_lower(inner, key);
|
|
1822
|
+
|
|
1823
|
+
n = inner->childid[slot];
|
|
1824
|
+
}
|
|
1825
|
+
|
|
1826
|
+
LeafNode* leaf = static_cast<LeafNode*>(n);
|
|
1827
|
+
|
|
1828
|
+
unsigned short slot = find_lower(leaf, key);
|
|
1829
|
+
return iterator(leaf, slot);
|
|
1830
|
+
}
|
|
1831
|
+
|
|
1832
|
+
//! Searches the B+ tree and returns a constant iterator to the first pair
|
|
1833
|
+
//! equal to or greater than key, or end() if all keys are smaller.
|
|
1834
|
+
const_iterator lower_bound(const key_type& key) const
|
|
1835
|
+
{
|
|
1836
|
+
const node* n = root_;
|
|
1837
|
+
if (!n)
|
|
1838
|
+
return end();
|
|
1839
|
+
|
|
1840
|
+
while (!n->is_leafnode())
|
|
1841
|
+
{
|
|
1842
|
+
const InnerNode* inner = static_cast<const InnerNode*>(n);
|
|
1843
|
+
unsigned short slot = find_lower(inner, key);
|
|
1844
|
+
|
|
1845
|
+
n = inner->childid[slot];
|
|
1846
|
+
}
|
|
1847
|
+
|
|
1848
|
+
const LeafNode* leaf = static_cast<const LeafNode*>(n);
|
|
1849
|
+
|
|
1850
|
+
unsigned short slot = find_lower(leaf, key);
|
|
1851
|
+
return const_iterator(leaf, slot);
|
|
1852
|
+
}
|
|
1853
|
+
|
|
1854
|
+
//! Searches the B+ tree and returns an iterator to the first pair greater
|
|
1855
|
+
//! than key, or end() if all keys are smaller or equal.
|
|
1856
|
+
iterator upper_bound(const key_type& key)
|
|
1857
|
+
{
|
|
1858
|
+
node* n = root_;
|
|
1859
|
+
if (!n)
|
|
1860
|
+
return end();
|
|
1861
|
+
|
|
1862
|
+
while (!n->is_leafnode())
|
|
1863
|
+
{
|
|
1864
|
+
const InnerNode* inner = static_cast<const InnerNode*>(n);
|
|
1865
|
+
unsigned short slot = find_upper(inner, key);
|
|
1866
|
+
|
|
1867
|
+
n = inner->childid[slot];
|
|
1868
|
+
}
|
|
1869
|
+
|
|
1870
|
+
LeafNode* leaf = static_cast<LeafNode*>(n);
|
|
1871
|
+
|
|
1872
|
+
unsigned short slot = find_upper(leaf, key);
|
|
1873
|
+
return iterator(leaf, slot);
|
|
1874
|
+
}
|
|
1875
|
+
|
|
1876
|
+
//! Searches the B+ tree and returns a constant iterator to the first pair
|
|
1877
|
+
//! greater than key, or end() if all keys are smaller or equal.
|
|
1878
|
+
const_iterator upper_bound(const key_type& key) const
|
|
1879
|
+
{
|
|
1880
|
+
const node* n = root_;
|
|
1881
|
+
if (!n)
|
|
1882
|
+
return end();
|
|
1883
|
+
|
|
1884
|
+
while (!n->is_leafnode())
|
|
1885
|
+
{
|
|
1886
|
+
const InnerNode* inner = static_cast<const InnerNode*>(n);
|
|
1887
|
+
unsigned short slot = find_upper(inner, key);
|
|
1888
|
+
|
|
1889
|
+
n = inner->childid[slot];
|
|
1890
|
+
}
|
|
1891
|
+
|
|
1892
|
+
const LeafNode* leaf = static_cast<const LeafNode*>(n);
|
|
1893
|
+
|
|
1894
|
+
unsigned short slot = find_upper(leaf, key);
|
|
1895
|
+
return const_iterator(leaf, slot);
|
|
1896
|
+
}
|
|
1897
|
+
|
|
1898
|
+
//! Searches the B+ tree and returns both lower_bound() and upper_bound().
|
|
1899
|
+
std::pair<iterator, iterator> equal_range(const key_type& key)
|
|
1900
|
+
{
|
|
1901
|
+
return std::pair<iterator, iterator>(lower_bound(key),
|
|
1902
|
+
upper_bound(key));
|
|
1903
|
+
}
|
|
1904
|
+
|
|
1905
|
+
//! Searches the B+ tree and returns both lower_bound() and upper_bound().
|
|
1906
|
+
std::pair<const_iterator, const_iterator> equal_range(
|
|
1907
|
+
const key_type& key) const
|
|
1908
|
+
{
|
|
1909
|
+
return std::pair<const_iterator, const_iterator>(lower_bound(key),
|
|
1910
|
+
upper_bound(key));
|
|
1911
|
+
}
|
|
1912
|
+
|
|
1913
|
+
//! \}
|
|
1914
|
+
|
|
1915
|
+
public:
|
|
1916
|
+
//! \name B+ Tree Object Comparison Functions
|
|
1917
|
+
//! \{
|
|
1918
|
+
|
|
1919
|
+
//! Equality relation of B+ trees of the same type. B+ trees of the same
|
|
1920
|
+
//! size and equal elements (both key and data) are considered equal. Beware
|
|
1921
|
+
//! of the random ordering of duplicate keys.
|
|
1922
|
+
bool operator==(const BTree& other) const
|
|
1923
|
+
{
|
|
1924
|
+
return (size() == other.size()) &&
|
|
1925
|
+
std::equal(begin(), end(), other.begin());
|
|
1926
|
+
}
|
|
1927
|
+
|
|
1928
|
+
//! Inequality relation. Based on operator==.
|
|
1929
|
+
bool operator!=(const BTree& other) const
|
|
1930
|
+
{
|
|
1931
|
+
return !(*this == other);
|
|
1932
|
+
}
|
|
1933
|
+
|
|
1934
|
+
//! Total ordering relation of B+ trees of the same type. It uses
|
|
1935
|
+
//! std::lexicographical_compare() for the actual comparison of elements.
|
|
1936
|
+
bool operator<(const BTree& other) const
|
|
1937
|
+
{
|
|
1938
|
+
return std::lexicographical_compare(begin(), end(), other.begin(),
|
|
1939
|
+
other.end());
|
|
1940
|
+
}
|
|
1941
|
+
|
|
1942
|
+
//! Greater relation. Based on operator<.
|
|
1943
|
+
bool operator>(const BTree& other) const
|
|
1944
|
+
{
|
|
1945
|
+
return other < *this;
|
|
1946
|
+
}
|
|
1947
|
+
|
|
1948
|
+
//! Less-equal relation. Based on operator<.
|
|
1949
|
+
bool operator<=(const BTree& other) const
|
|
1950
|
+
{
|
|
1951
|
+
return !(other < *this);
|
|
1952
|
+
}
|
|
1953
|
+
|
|
1954
|
+
//! Greater-equal relation. Based on operator<.
|
|
1955
|
+
bool operator>=(const BTree& other) const
|
|
1956
|
+
{
|
|
1957
|
+
return !(*this < other);
|
|
1958
|
+
}
|
|
1959
|
+
|
|
1960
|
+
//! \}
|
|
1961
|
+
|
|
1962
|
+
public:
|
|
1963
|
+
//! \name Fast Copy: Assign Operator and Copy Constructors
|
|
1964
|
+
//! \{
|
|
1965
|
+
|
|
1966
|
+
//! Assignment operator. All the key/data pairs are copied.
|
|
1967
|
+
BTree& operator=(const BTree& other)
|
|
1968
|
+
{
|
|
1969
|
+
if (this != &other)
|
|
1970
|
+
{
|
|
1971
|
+
clear();
|
|
1972
|
+
|
|
1973
|
+
key_less_ = other.key_comp();
|
|
1974
|
+
allocator_ = other.get_allocator();
|
|
1975
|
+
|
|
1976
|
+
if (other.size() != 0)
|
|
1977
|
+
{
|
|
1978
|
+
stats_.leaves = stats_.inner_nodes = 0;
|
|
1979
|
+
if (other.root_)
|
|
1980
|
+
{
|
|
1981
|
+
root_ = copy_recursive(other.root_);
|
|
1982
|
+
}
|
|
1983
|
+
stats_ = other.stats_;
|
|
1984
|
+
}
|
|
1985
|
+
|
|
1986
|
+
if (self_verify)
|
|
1987
|
+
verify();
|
|
1988
|
+
}
|
|
1989
|
+
return *this;
|
|
1990
|
+
}
|
|
1991
|
+
|
|
1992
|
+
//! Copy constructor. The newly initialized B+ tree object will contain a
|
|
1993
|
+
//! copy of all key/data pairs.
|
|
1994
|
+
BTree(const BTree& other)
|
|
1995
|
+
: root_(nullptr),
|
|
1996
|
+
head_leaf_(nullptr),
|
|
1997
|
+
tail_leaf_(nullptr),
|
|
1998
|
+
stats_(other.stats_),
|
|
1999
|
+
key_less_(other.key_comp()),
|
|
2000
|
+
allocator_(other.get_allocator())
|
|
2001
|
+
{
|
|
2002
|
+
if (size() > 0)
|
|
2003
|
+
{
|
|
2004
|
+
stats_.leaves = stats_.inner_nodes = 0;
|
|
2005
|
+
if (other.root_)
|
|
2006
|
+
{
|
|
2007
|
+
root_ = copy_recursive(other.root_);
|
|
2008
|
+
}
|
|
2009
|
+
if (self_verify)
|
|
2010
|
+
verify();
|
|
2011
|
+
}
|
|
2012
|
+
}
|
|
2013
|
+
|
|
2014
|
+
private:
|
|
2015
|
+
//! Recursively copy nodes from another B+ tree object
|
|
2016
|
+
struct node* copy_recursive(const node* n)
|
|
2017
|
+
{
|
|
2018
|
+
if (n->is_leafnode())
|
|
2019
|
+
{
|
|
2020
|
+
const LeafNode* leaf = static_cast<const LeafNode*>(n);
|
|
2021
|
+
LeafNode* newleaf = allocate_leaf();
|
|
2022
|
+
|
|
2023
|
+
newleaf->slotuse = leaf->slotuse;
|
|
2024
|
+
std::copy(leaf->slotdata, leaf->slotdata + leaf->slotuse,
|
|
2025
|
+
newleaf->slotdata);
|
|
2026
|
+
|
|
2027
|
+
if (head_leaf_ == nullptr)
|
|
2028
|
+
{
|
|
2029
|
+
head_leaf_ = tail_leaf_ = newleaf;
|
|
2030
|
+
newleaf->prev_leaf = newleaf->next_leaf = nullptr;
|
|
2031
|
+
}
|
|
2032
|
+
else
|
|
2033
|
+
{
|
|
2034
|
+
newleaf->prev_leaf = tail_leaf_;
|
|
2035
|
+
tail_leaf_->next_leaf = newleaf;
|
|
2036
|
+
tail_leaf_ = newleaf;
|
|
2037
|
+
}
|
|
2038
|
+
|
|
2039
|
+
return newleaf;
|
|
2040
|
+
}
|
|
2041
|
+
|
|
2042
|
+
const InnerNode* inner = static_cast<const InnerNode*>(n);
|
|
2043
|
+
InnerNode* newinner = allocate_inner(inner->level);
|
|
2044
|
+
|
|
2045
|
+
newinner->slotuse = inner->slotuse;
|
|
2046
|
+
std::copy(inner->slotkey, inner->slotkey + inner->slotuse,
|
|
2047
|
+
newinner->slotkey);
|
|
2048
|
+
|
|
2049
|
+
for (unsigned short slot = 0; slot <= inner->slotuse; ++slot)
|
|
2050
|
+
newinner->childid[slot] = copy_recursive(inner->childid[slot]);
|
|
2051
|
+
|
|
2052
|
+
return newinner;
|
|
2053
|
+
}
|
|
2054
|
+
|
|
2055
|
+
//! \}
|
|
2056
|
+
|
|
2057
|
+
public:
|
|
2058
|
+
//! \name Public Insertion Functions
|
|
2059
|
+
//! \{
|
|
2060
|
+
|
|
2061
|
+
//! Attempt to insert a key/data pair into the B+ tree. If the tree does not
|
|
2062
|
+
//! allow duplicate keys, then the insert may fail if it is already present.
|
|
2063
|
+
std::pair<iterator, bool> insert(const value_type& x)
|
|
2064
|
+
{
|
|
2065
|
+
return insert_start(key_of_value::get(x), x);
|
|
2066
|
+
}
|
|
2067
|
+
|
|
2068
|
+
//! Attempt to insert a key/data pair into the B+ tree. The iterator hint is
|
|
2069
|
+
//! currently ignored by the B+ tree insertion routine.
|
|
2070
|
+
iterator insert(iterator /* hint */, const value_type& x)
|
|
2071
|
+
{
|
|
2072
|
+
return insert_start(key_of_value::get(x), x).first;
|
|
2073
|
+
}
|
|
2074
|
+
|
|
2075
|
+
//! Attempt to insert the range [first,last) of value_type pairs into the B+
|
|
2076
|
+
//! tree. Each key/data pair is inserted individually; to bulk load the
|
|
2077
|
+
//! tree, use a constructor with range.
|
|
2078
|
+
template <typename InputIterator>
|
|
2079
|
+
void insert(InputIterator first, InputIterator last)
|
|
2080
|
+
{
|
|
2081
|
+
InputIterator iter = first;
|
|
2082
|
+
while (iter != last)
|
|
2083
|
+
{
|
|
2084
|
+
insert(*iter);
|
|
2085
|
+
++iter;
|
|
2086
|
+
}
|
|
2087
|
+
}
|
|
2088
|
+
|
|
2089
|
+
//! \}
|
|
2090
|
+
|
|
2091
|
+
private:
|
|
2092
|
+
//! \name Private Insertion Functions
|
|
2093
|
+
//! \{
|
|
2094
|
+
|
|
2095
|
+
//! Start the insertion descent at the current root and handle root splits.
|
|
2096
|
+
//! Returns true if the item was inserted
|
|
2097
|
+
std::pair<iterator, bool> insert_start(const key_type& key,
|
|
2098
|
+
const value_type& value)
|
|
2099
|
+
{
|
|
2100
|
+
node* newchild = nullptr;
|
|
2101
|
+
key_type newkey = key_type();
|
|
2102
|
+
|
|
2103
|
+
if (root_ == nullptr)
|
|
2104
|
+
{
|
|
2105
|
+
root_ = head_leaf_ = tail_leaf_ = allocate_leaf();
|
|
2106
|
+
}
|
|
2107
|
+
|
|
2108
|
+
std::pair<iterator, bool> r =
|
|
2109
|
+
insert_descend(root_, key, value, &newkey, &newchild);
|
|
2110
|
+
|
|
2111
|
+
if (newchild)
|
|
2112
|
+
{
|
|
2113
|
+
// this only occurs if insert_descend() could not insert the key
|
|
2114
|
+
// into the root node, this mean the root is full and a new root
|
|
2115
|
+
// needs to be created.
|
|
2116
|
+
InnerNode* newroot = allocate_inner(root_->level + 1);
|
|
2117
|
+
newroot->slotkey[0] = newkey;
|
|
2118
|
+
|
|
2119
|
+
newroot->childid[0] = root_;
|
|
2120
|
+
newroot->childid[1] = newchild;
|
|
2121
|
+
|
|
2122
|
+
newroot->slotuse = 1;
|
|
2123
|
+
|
|
2124
|
+
root_ = newroot;
|
|
2125
|
+
}
|
|
2126
|
+
|
|
2127
|
+
// increment size if the item was inserted
|
|
2128
|
+
if (r.second)
|
|
2129
|
+
++stats_.size;
|
|
2130
|
+
|
|
2131
|
+
#ifdef TLX_BTREE_DEBUG
|
|
2132
|
+
if (debug)
|
|
2133
|
+
print(std::cout);
|
|
2134
|
+
#endif
|
|
2135
|
+
|
|
2136
|
+
if (self_verify)
|
|
2137
|
+
{
|
|
2138
|
+
verify();
|
|
2139
|
+
TLX_BTREE_ASSERT(exists(key));
|
|
2140
|
+
}
|
|
2141
|
+
|
|
2142
|
+
return r;
|
|
2143
|
+
}
|
|
2144
|
+
|
|
2145
|
+
/*!
|
|
2146
|
+
* Insert an item into the B+ tree.
|
|
2147
|
+
*
|
|
2148
|
+
* Descend down the nodes to a leaf, insert the key/data pair in a free
|
|
2149
|
+
* slot. If the node overflows, then it must be split and the new split node
|
|
2150
|
+
* inserted into the parent. Unroll / this splitting up to the root.
|
|
2151
|
+
*/
|
|
2152
|
+
std::pair<iterator, bool> insert_descend(node* n, const key_type& key,
|
|
2153
|
+
const value_type& value,
|
|
2154
|
+
key_type* splitkey,
|
|
2155
|
+
node** splitnode)
|
|
2156
|
+
{
|
|
2157
|
+
if (!n->is_leafnode())
|
|
2158
|
+
{
|
|
2159
|
+
InnerNode* inner = static_cast<InnerNode*>(n);
|
|
2160
|
+
|
|
2161
|
+
key_type newkey = key_type();
|
|
2162
|
+
node* newchild = nullptr;
|
|
2163
|
+
|
|
2164
|
+
unsigned short slot = find_lower(inner, key);
|
|
2165
|
+
|
|
2166
|
+
TLX_BTREE_PRINT("BTree::insert_descend into "
|
|
2167
|
+
<< inner->childid[slot]);
|
|
2168
|
+
|
|
2169
|
+
std::pair<iterator, bool> r = insert_descend(
|
|
2170
|
+
inner->childid[slot], key, value, &newkey, &newchild);
|
|
2171
|
+
|
|
2172
|
+
if (newchild)
|
|
2173
|
+
{
|
|
2174
|
+
TLX_BTREE_PRINT("BTree::insert_descend newchild"
|
|
2175
|
+
<< " with key " << newkey << " node "
|
|
2176
|
+
<< newchild << " at slot " << slot);
|
|
2177
|
+
|
|
2178
|
+
if (inner->is_full())
|
|
2179
|
+
{
|
|
2180
|
+
split_inner_node(inner, splitkey, splitnode, slot);
|
|
2181
|
+
|
|
2182
|
+
TLX_BTREE_PRINT("BTree::insert_descend done split_inner:"
|
|
2183
|
+
<< " putslot: " << slot << " putkey: "
|
|
2184
|
+
<< newkey << " upkey: " << *splitkey);
|
|
2185
|
+
|
|
2186
|
+
#ifdef TLX_BTREE_DEBUG
|
|
2187
|
+
if (debug)
|
|
2188
|
+
{
|
|
2189
|
+
print_node(std::cout, inner);
|
|
2190
|
+
print_node(std::cout, *splitnode);
|
|
2191
|
+
}
|
|
2192
|
+
#endif
|
|
2193
|
+
|
|
2194
|
+
// check if insert slot is in the split sibling node
|
|
2195
|
+
TLX_BTREE_PRINT("BTree::insert_descend switch: "
|
|
2196
|
+
<< slot << " > " << inner->slotuse + 1);
|
|
2197
|
+
|
|
2198
|
+
if (slot == inner->slotuse + 1 &&
|
|
2199
|
+
inner->slotuse < (*splitnode)->slotuse)
|
|
2200
|
+
{
|
|
2201
|
+
// special case when the insert slot matches the split
|
|
2202
|
+
// place between the two nodes, then the insert key
|
|
2203
|
+
// becomes the split key.
|
|
2204
|
+
|
|
2205
|
+
TLX_BTREE_ASSERT(inner->slotuse + 1 < inner_slotmax);
|
|
2206
|
+
|
|
2207
|
+
InnerNode* split = static_cast<InnerNode*>(*splitnode);
|
|
2208
|
+
|
|
2209
|
+
// move the split key and it's datum into the left node
|
|
2210
|
+
inner->slotkey[inner->slotuse] = *splitkey;
|
|
2211
|
+
inner->childid[inner->slotuse + 1] = split->childid[0];
|
|
2212
|
+
inner->slotuse++;
|
|
2213
|
+
|
|
2214
|
+
// set new split key and move corresponding datum into
|
|
2215
|
+
// right node
|
|
2216
|
+
split->childid[0] = newchild;
|
|
2217
|
+
*splitkey = newkey;
|
|
2218
|
+
|
|
2219
|
+
return r;
|
|
2220
|
+
}
|
|
2221
|
+
|
|
2222
|
+
if (slot >= inner->slotuse + 1)
|
|
2223
|
+
{
|
|
2224
|
+
// in case the insert slot is in the newly create split
|
|
2225
|
+
// node, we reuse the code below.
|
|
2226
|
+
|
|
2227
|
+
slot -= inner->slotuse + 1;
|
|
2228
|
+
inner = static_cast<InnerNode*>(*splitnode);
|
|
2229
|
+
TLX_BTREE_PRINT("BTree::insert_descend switching to "
|
|
2230
|
+
"splitted node "
|
|
2231
|
+
<< inner << " slot " << slot);
|
|
2232
|
+
}
|
|
2233
|
+
}
|
|
2234
|
+
|
|
2235
|
+
// move items and put pointer to child node into correct slot
|
|
2236
|
+
TLX_BTREE_ASSERT(slot >= 0 && slot <= inner->slotuse);
|
|
2237
|
+
|
|
2238
|
+
std::copy_backward(inner->slotkey + slot,
|
|
2239
|
+
inner->slotkey + inner->slotuse,
|
|
2240
|
+
inner->slotkey + inner->slotuse + 1);
|
|
2241
|
+
std::copy_backward(inner->childid + slot,
|
|
2242
|
+
inner->childid + inner->slotuse + 1,
|
|
2243
|
+
inner->childid + inner->slotuse + 2);
|
|
2244
|
+
|
|
2245
|
+
inner->slotkey[slot] = newkey;
|
|
2246
|
+
inner->childid[slot + 1] = newchild;
|
|
2247
|
+
inner->slotuse++;
|
|
2248
|
+
}
|
|
2249
|
+
|
|
2250
|
+
return r;
|
|
2251
|
+
}
|
|
2252
|
+
|
|
2253
|
+
// n->is_leafnode() == true
|
|
2254
|
+
LeafNode* leaf = static_cast<LeafNode*>(n);
|
|
2255
|
+
|
|
2256
|
+
unsigned short slot = find_lower(leaf, key);
|
|
2257
|
+
|
|
2258
|
+
if (!allow_duplicates && slot < leaf->slotuse &&
|
|
2259
|
+
key_equal(key, leaf->key(slot)))
|
|
2260
|
+
{
|
|
2261
|
+
return std::pair<iterator, bool>(iterator(leaf, slot), false);
|
|
2262
|
+
}
|
|
2263
|
+
|
|
2264
|
+
if (leaf->is_full())
|
|
2265
|
+
{
|
|
2266
|
+
split_leaf_node(leaf, splitkey, splitnode);
|
|
2267
|
+
|
|
2268
|
+
// check if insert slot is in the split sibling node
|
|
2269
|
+
if (slot >= leaf->slotuse)
|
|
2270
|
+
{
|
|
2271
|
+
slot -= leaf->slotuse;
|
|
2272
|
+
leaf = static_cast<LeafNode*>(*splitnode);
|
|
2273
|
+
}
|
|
2274
|
+
}
|
|
2275
|
+
|
|
2276
|
+
// move items and put data item into correct data slot
|
|
2277
|
+
TLX_BTREE_ASSERT(slot >= 0 && slot <= leaf->slotuse);
|
|
2278
|
+
|
|
2279
|
+
std::copy_backward(leaf->slotdata + slot,
|
|
2280
|
+
leaf->slotdata + leaf->slotuse,
|
|
2281
|
+
leaf->slotdata + leaf->slotuse + 1);
|
|
2282
|
+
|
|
2283
|
+
leaf->slotdata[slot] = value;
|
|
2284
|
+
leaf->slotuse++;
|
|
2285
|
+
|
|
2286
|
+
if (splitnode && leaf != *splitnode && slot == leaf->slotuse - 1)
|
|
2287
|
+
{
|
|
2288
|
+
// special case: the node was split, and the insert is at the
|
|
2289
|
+
// last slot of the old node. then the splitkey must be updated.
|
|
2290
|
+
*splitkey = key;
|
|
2291
|
+
}
|
|
2292
|
+
|
|
2293
|
+
return std::pair<iterator, bool>(iterator(leaf, slot), true);
|
|
2294
|
+
}
|
|
2295
|
+
|
|
2296
|
+
//! Split up a leaf node into two equally-filled sibling leaves. Returns the
|
|
2297
|
+
//! new nodes and it's insertion key in the two parameters.
|
|
2298
|
+
void split_leaf_node(LeafNode* leaf, key_type* out_newkey,
|
|
2299
|
+
node** out_newleaf)
|
|
2300
|
+
{
|
|
2301
|
+
TLX_BTREE_ASSERT(leaf->is_full());
|
|
2302
|
+
|
|
2303
|
+
unsigned short mid = (leaf->slotuse >> 1);
|
|
2304
|
+
|
|
2305
|
+
TLX_BTREE_PRINT("BTree::split_leaf_node on " << leaf);
|
|
2306
|
+
|
|
2307
|
+
LeafNode* newleaf = allocate_leaf();
|
|
2308
|
+
|
|
2309
|
+
newleaf->slotuse = leaf->slotuse - mid;
|
|
2310
|
+
|
|
2311
|
+
newleaf->next_leaf = leaf->next_leaf;
|
|
2312
|
+
if (newleaf->next_leaf == nullptr)
|
|
2313
|
+
{
|
|
2314
|
+
TLX_BTREE_ASSERT(leaf == tail_leaf_);
|
|
2315
|
+
tail_leaf_ = newleaf;
|
|
2316
|
+
}
|
|
2317
|
+
else
|
|
2318
|
+
{
|
|
2319
|
+
newleaf->next_leaf->prev_leaf = newleaf;
|
|
2320
|
+
}
|
|
2321
|
+
|
|
2322
|
+
std::copy(leaf->slotdata + mid, leaf->slotdata + leaf->slotuse,
|
|
2323
|
+
newleaf->slotdata);
|
|
2324
|
+
|
|
2325
|
+
leaf->slotuse = mid;
|
|
2326
|
+
leaf->next_leaf = newleaf;
|
|
2327
|
+
newleaf->prev_leaf = leaf;
|
|
2328
|
+
|
|
2329
|
+
*out_newkey = leaf->key(leaf->slotuse - 1);
|
|
2330
|
+
*out_newleaf = newleaf;
|
|
2331
|
+
}
|
|
2332
|
+
|
|
2333
|
+
//! Split up an inner node into two equally-filled sibling nodes. Returns
|
|
2334
|
+
//! the new nodes and it's insertion key in the two parameters. Requires the
|
|
2335
|
+
//! slot of the item will be inserted, so the nodes will be the same size
|
|
2336
|
+
//! after the insert.
|
|
2337
|
+
void split_inner_node(InnerNode* inner, key_type* out_newkey,
|
|
2338
|
+
node** out_newinner, unsigned int addslot)
|
|
2339
|
+
{
|
|
2340
|
+
TLX_BTREE_ASSERT(inner->is_full());
|
|
2341
|
+
|
|
2342
|
+
unsigned short mid = (inner->slotuse >> 1);
|
|
2343
|
+
|
|
2344
|
+
TLX_BTREE_PRINT("BTree::split_inner: mid " << mid << " addslot "
|
|
2345
|
+
<< addslot);
|
|
2346
|
+
|
|
2347
|
+
// if the split is uneven and the overflowing item will be put into the
|
|
2348
|
+
// larger node, then the smaller split node may underflow
|
|
2349
|
+
if (addslot <= mid && mid > inner->slotuse - (mid + 1))
|
|
2350
|
+
mid--;
|
|
2351
|
+
|
|
2352
|
+
TLX_BTREE_PRINT("BTree::split_inner: mid " << mid << " addslot "
|
|
2353
|
+
<< addslot);
|
|
2354
|
+
|
|
2355
|
+
TLX_BTREE_PRINT("BTree::split_inner_node on "
|
|
2356
|
+
<< inner << " into two nodes " << mid << " and "
|
|
2357
|
+
<< inner->slotuse - (mid + 1) << " sized");
|
|
2358
|
+
|
|
2359
|
+
InnerNode* newinner = allocate_inner(inner->level);
|
|
2360
|
+
|
|
2361
|
+
newinner->slotuse = inner->slotuse - (mid + 1);
|
|
2362
|
+
|
|
2363
|
+
std::copy(inner->slotkey + mid + 1, inner->slotkey + inner->slotuse,
|
|
2364
|
+
newinner->slotkey);
|
|
2365
|
+
std::copy(inner->childid + mid + 1, inner->childid + inner->slotuse + 1,
|
|
2366
|
+
newinner->childid);
|
|
2367
|
+
|
|
2368
|
+
inner->slotuse = mid;
|
|
2369
|
+
|
|
2370
|
+
*out_newkey = inner->key(mid);
|
|
2371
|
+
*out_newinner = newinner;
|
|
2372
|
+
}
|
|
2373
|
+
|
|
2374
|
+
//! \}
|
|
2375
|
+
|
|
2376
|
+
public:
|
|
2377
|
+
//! \name Bulk Loader - Construct Tree from Sorted Sequence
|
|
2378
|
+
//! \{
|
|
2379
|
+
|
|
2380
|
+
//! Bulk load a sorted range. Loads items into leaves and constructs a
|
|
2381
|
+
//! B-tree above them. The tree must be empty when calling this function.
|
|
2382
|
+
template <typename Iterator>
|
|
2383
|
+
void bulk_load(Iterator ibegin, Iterator iend)
|
|
2384
|
+
{
|
|
2385
|
+
TLX_BTREE_ASSERT(empty());
|
|
2386
|
+
|
|
2387
|
+
stats_.size = iend - ibegin;
|
|
2388
|
+
|
|
2389
|
+
// calculate number of leaves needed, round up.
|
|
2390
|
+
size_t num_items = iend - ibegin;
|
|
2391
|
+
size_t num_leaves = (num_items + leaf_slotmax - 1) / leaf_slotmax;
|
|
2392
|
+
|
|
2393
|
+
TLX_BTREE_PRINT("BTree::bulk_load, level 0: "
|
|
2394
|
+
<< stats_.size << " items into " << num_leaves
|
|
2395
|
+
<< " leaves with up to "
|
|
2396
|
+
<< ((iend - ibegin + num_leaves - 1) / num_leaves)
|
|
2397
|
+
<< " items per leaf.");
|
|
2398
|
+
|
|
2399
|
+
Iterator it = ibegin;
|
|
2400
|
+
for (size_t i = 0; i < num_leaves; ++i)
|
|
2401
|
+
{
|
|
2402
|
+
// allocate new leaf node
|
|
2403
|
+
LeafNode* leaf = allocate_leaf();
|
|
2404
|
+
|
|
2405
|
+
// copy keys or (key,value) pairs into leaf nodes, uses template
|
|
2406
|
+
// switch leaf->set_slot().
|
|
2407
|
+
leaf->slotuse = static_cast<int>(num_items / (num_leaves - i));
|
|
2408
|
+
for (size_t s = 0; s < leaf->slotuse; ++s, ++it)
|
|
2409
|
+
leaf->set_slot(s, *it);
|
|
2410
|
+
|
|
2411
|
+
if (tail_leaf_ != nullptr)
|
|
2412
|
+
{
|
|
2413
|
+
tail_leaf_->next_leaf = leaf;
|
|
2414
|
+
leaf->prev_leaf = tail_leaf_;
|
|
2415
|
+
}
|
|
2416
|
+
else
|
|
2417
|
+
{
|
|
2418
|
+
head_leaf_ = leaf;
|
|
2419
|
+
}
|
|
2420
|
+
tail_leaf_ = leaf;
|
|
2421
|
+
|
|
2422
|
+
num_items -= leaf->slotuse;
|
|
2423
|
+
}
|
|
2424
|
+
|
|
2425
|
+
TLX_BTREE_ASSERT(it == iend && num_items == 0);
|
|
2426
|
+
|
|
2427
|
+
// if the btree is so small to fit into one leaf, then we're done.
|
|
2428
|
+
if (head_leaf_ == tail_leaf_)
|
|
2429
|
+
{
|
|
2430
|
+
root_ = head_leaf_;
|
|
2431
|
+
return;
|
|
2432
|
+
}
|
|
2433
|
+
|
|
2434
|
+
TLX_BTREE_ASSERT(stats_.leaves == num_leaves);
|
|
2435
|
+
|
|
2436
|
+
// create first level of inner nodes, pointing to the leaves.
|
|
2437
|
+
size_t num_parents =
|
|
2438
|
+
(num_leaves + (inner_slotmax + 1) - 1) / (inner_slotmax + 1);
|
|
2439
|
+
|
|
2440
|
+
TLX_BTREE_PRINT("BTree::bulk_load, level 1: "
|
|
2441
|
+
<< num_leaves << " leaves in " << num_parents
|
|
2442
|
+
<< " inner nodes with up to "
|
|
2443
|
+
<< ((num_leaves + num_parents - 1) / num_parents)
|
|
2444
|
+
<< " leaves per inner node.");
|
|
2445
|
+
|
|
2446
|
+
// save inner nodes and maxkey for next level.
|
|
2447
|
+
typedef std::pair<InnerNode*, const key_type*> nextlevel_type;
|
|
2448
|
+
nextlevel_type* nextlevel = new nextlevel_type[num_parents];
|
|
2449
|
+
|
|
2450
|
+
LeafNode* leaf = head_leaf_;
|
|
2451
|
+
for (size_t i = 0; i < num_parents; ++i)
|
|
2452
|
+
{
|
|
2453
|
+
// allocate new inner node at level 1
|
|
2454
|
+
InnerNode* n = allocate_inner(1);
|
|
2455
|
+
|
|
2456
|
+
n->slotuse = static_cast<int>(num_leaves / (num_parents - i));
|
|
2457
|
+
TLX_BTREE_ASSERT(n->slotuse > 0);
|
|
2458
|
+
// this counts keys, but an inner node has keys+1 children.
|
|
2459
|
+
--n->slotuse;
|
|
2460
|
+
|
|
2461
|
+
// copy last key from each leaf and set child
|
|
2462
|
+
for (unsigned short s = 0; s < n->slotuse; ++s)
|
|
2463
|
+
{
|
|
2464
|
+
n->slotkey[s] = leaf->key(leaf->slotuse - 1);
|
|
2465
|
+
n->childid[s] = leaf;
|
|
2466
|
+
leaf = leaf->next_leaf;
|
|
2467
|
+
}
|
|
2468
|
+
n->childid[n->slotuse] = leaf;
|
|
2469
|
+
|
|
2470
|
+
// track max key of any descendant.
|
|
2471
|
+
nextlevel[i].first = n;
|
|
2472
|
+
nextlevel[i].second = &leaf->key(leaf->slotuse - 1);
|
|
2473
|
+
|
|
2474
|
+
leaf = leaf->next_leaf;
|
|
2475
|
+
num_leaves -= n->slotuse + 1;
|
|
2476
|
+
}
|
|
2477
|
+
|
|
2478
|
+
TLX_BTREE_ASSERT(leaf == nullptr && num_leaves == 0);
|
|
2479
|
+
|
|
2480
|
+
// recursively build inner nodes pointing to inner nodes.
|
|
2481
|
+
for (int level = 2; num_parents != 1; ++level)
|
|
2482
|
+
{
|
|
2483
|
+
size_t num_children = num_parents;
|
|
2484
|
+
num_parents =
|
|
2485
|
+
(num_children + (inner_slotmax + 1) - 1) / (inner_slotmax + 1);
|
|
2486
|
+
|
|
2487
|
+
TLX_BTREE_PRINT("BTree::bulk_load, level "
|
|
2488
|
+
<< level << ": " << num_children << " children in "
|
|
2489
|
+
<< num_parents << " inner nodes with up to "
|
|
2490
|
+
<< ((num_children + num_parents - 1) / num_parents)
|
|
2491
|
+
<< " children per inner node.");
|
|
2492
|
+
|
|
2493
|
+
size_t inner_index = 0;
|
|
2494
|
+
for (size_t i = 0; i < num_parents; ++i)
|
|
2495
|
+
{
|
|
2496
|
+
// allocate new inner node at level
|
|
2497
|
+
InnerNode* n = allocate_inner(level);
|
|
2498
|
+
|
|
2499
|
+
n->slotuse = static_cast<int>(num_children / (num_parents - i));
|
|
2500
|
+
TLX_BTREE_ASSERT(n->slotuse > 0);
|
|
2501
|
+
// this counts keys, but an inner node has keys+1 children.
|
|
2502
|
+
--n->slotuse;
|
|
2503
|
+
|
|
2504
|
+
// copy children and maxkeys from nextlevel
|
|
2505
|
+
for (unsigned short s = 0; s < n->slotuse; ++s)
|
|
2506
|
+
{
|
|
2507
|
+
n->slotkey[s] = *nextlevel[inner_index].second;
|
|
2508
|
+
n->childid[s] = nextlevel[inner_index].first;
|
|
2509
|
+
++inner_index;
|
|
2510
|
+
}
|
|
2511
|
+
n->childid[n->slotuse] = nextlevel[inner_index].first;
|
|
2512
|
+
|
|
2513
|
+
// reuse nextlevel array for parents, because we can overwrite
|
|
2514
|
+
// slots we've already consumed.
|
|
2515
|
+
nextlevel[i].first = n;
|
|
2516
|
+
nextlevel[i].second = nextlevel[inner_index].second;
|
|
2517
|
+
|
|
2518
|
+
++inner_index;
|
|
2519
|
+
num_children -= n->slotuse + 1;
|
|
2520
|
+
}
|
|
2521
|
+
|
|
2522
|
+
TLX_BTREE_ASSERT(num_children == 0);
|
|
2523
|
+
}
|
|
2524
|
+
|
|
2525
|
+
root_ = nextlevel[0].first;
|
|
2526
|
+
delete[] nextlevel;
|
|
2527
|
+
|
|
2528
|
+
if (self_verify)
|
|
2529
|
+
verify();
|
|
2530
|
+
}
|
|
2531
|
+
|
|
2532
|
+
//! \}
|
|
2533
|
+
|
|
2534
|
+
private:
|
|
2535
|
+
//! \name Support Class Encapsulating Deletion Results
|
|
2536
|
+
//! \{
|
|
2537
|
+
|
|
2538
|
+
//! Result flags of recursive deletion.
|
|
2539
|
+
enum result_flags_t
|
|
2540
|
+
{
|
|
2541
|
+
//! Deletion successful and no fix-ups necessary.
|
|
2542
|
+
btree_ok = 0,
|
|
2543
|
+
|
|
2544
|
+
//! Deletion not successful because key was not found.
|
|
2545
|
+
btree_not_found = 1,
|
|
2546
|
+
|
|
2547
|
+
//! Deletion successful, the last key was updated so parent slotkeys
|
|
2548
|
+
//! need updates.
|
|
2549
|
+
btree_update_lastkey = 2,
|
|
2550
|
+
|
|
2551
|
+
//! Deletion successful, children nodes were merged and the parent needs
|
|
2552
|
+
//! to remove the empty node.
|
|
2553
|
+
btree_fixmerge = 4
|
|
2554
|
+
};
|
|
2555
|
+
|
|
2556
|
+
//! B+ tree recursive deletion has much information which is needs to be
|
|
2557
|
+
//! passed upward.
|
|
2558
|
+
struct result_t
|
|
2559
|
+
{
|
|
2560
|
+
//! Merged result flags
|
|
2561
|
+
result_flags_t flags;
|
|
2562
|
+
|
|
2563
|
+
//! The key to be updated at the parent's slot
|
|
2564
|
+
key_type lastkey;
|
|
2565
|
+
|
|
2566
|
+
//! Constructor of a result with a specific flag, this can also be used
|
|
2567
|
+
//! as for implicit conversion.
|
|
2568
|
+
result_t(result_flags_t f = btree_ok) : flags(f), lastkey()
|
|
2569
|
+
{
|
|
2570
|
+
}
|
|
2571
|
+
|
|
2572
|
+
//! Constructor with a lastkey value.
|
|
2573
|
+
result_t(result_flags_t f, const key_type& k) : flags(f), lastkey(k)
|
|
2574
|
+
{
|
|
2575
|
+
}
|
|
2576
|
+
|
|
2577
|
+
//! Test if this result object has a given flag set.
|
|
2578
|
+
bool has(result_flags_t f) const
|
|
2579
|
+
{
|
|
2580
|
+
return (flags & f) != 0;
|
|
2581
|
+
}
|
|
2582
|
+
|
|
2583
|
+
//! Merge two results OR-ing the result flags and overwriting lastkeys.
|
|
2584
|
+
result_t& operator|=(const result_t& other)
|
|
2585
|
+
{
|
|
2586
|
+
flags = result_flags_t(flags | other.flags);
|
|
2587
|
+
|
|
2588
|
+
// we overwrite existing lastkeys on purpose
|
|
2589
|
+
if (other.has(btree_update_lastkey))
|
|
2590
|
+
lastkey = other.lastkey;
|
|
2591
|
+
|
|
2592
|
+
return *this;
|
|
2593
|
+
}
|
|
2594
|
+
};
|
|
2595
|
+
|
|
2596
|
+
//! \}
|
|
2597
|
+
|
|
2598
|
+
public:
|
|
2599
|
+
//! \name Public Erase Functions
|
|
2600
|
+
//! \{
|
|
2601
|
+
|
|
2602
|
+
//! Erases one (the first) of the key/data pairs associated with the given
|
|
2603
|
+
//! key.
|
|
2604
|
+
bool erase_one(const key_type& key)
|
|
2605
|
+
{
|
|
2606
|
+
TLX_BTREE_PRINT("BTree::erase_one(" << key << ") on btree size "
|
|
2607
|
+
<< size());
|
|
2608
|
+
|
|
2609
|
+
if (self_verify)
|
|
2610
|
+
verify();
|
|
2611
|
+
|
|
2612
|
+
if (!root_)
|
|
2613
|
+
return false;
|
|
2614
|
+
|
|
2615
|
+
result_t result = erase_one_descend(key, root_, nullptr, nullptr,
|
|
2616
|
+
nullptr, nullptr, nullptr, 0);
|
|
2617
|
+
|
|
2618
|
+
if (!result.has(btree_not_found))
|
|
2619
|
+
--stats_.size;
|
|
2620
|
+
|
|
2621
|
+
#ifdef TLX_BTREE_DEBUG
|
|
2622
|
+
if (debug)
|
|
2623
|
+
print(std::cout);
|
|
2624
|
+
#endif
|
|
2625
|
+
if (self_verify)
|
|
2626
|
+
verify();
|
|
2627
|
+
|
|
2628
|
+
return !result.has(btree_not_found);
|
|
2629
|
+
}
|
|
2630
|
+
|
|
2631
|
+
//! Erases all the key/data pairs associated with the given key. This is
|
|
2632
|
+
//! implemented using erase_one().
|
|
2633
|
+
size_type erase(const key_type& key)
|
|
2634
|
+
{
|
|
2635
|
+
size_type c = 0;
|
|
2636
|
+
|
|
2637
|
+
while (erase_one(key))
|
|
2638
|
+
{
|
|
2639
|
+
++c;
|
|
2640
|
+
if (!allow_duplicates)
|
|
2641
|
+
break;
|
|
2642
|
+
}
|
|
2643
|
+
|
|
2644
|
+
return c;
|
|
2645
|
+
}
|
|
2646
|
+
|
|
2647
|
+
//! Erase the key/data pair referenced by the iterator.
|
|
2648
|
+
void erase(iterator iter)
|
|
2649
|
+
{
|
|
2650
|
+
TLX_BTREE_PRINT("BTree::erase_iter(" << iter.curr_leaf << ","
|
|
2651
|
+
<< iter.curr_slot
|
|
2652
|
+
<< ") on btree size " << size());
|
|
2653
|
+
|
|
2654
|
+
if (self_verify)
|
|
2655
|
+
verify();
|
|
2656
|
+
|
|
2657
|
+
if (!root_)
|
|
2658
|
+
return;
|
|
2659
|
+
|
|
2660
|
+
result_t result = erase_iter_descend(iter, root_, nullptr, nullptr,
|
|
2661
|
+
nullptr, nullptr, nullptr, 0);
|
|
2662
|
+
|
|
2663
|
+
if (!result.has(btree_not_found))
|
|
2664
|
+
--stats_.size;
|
|
2665
|
+
|
|
2666
|
+
#ifdef TLX_BTREE_DEBUG
|
|
2667
|
+
if (debug)
|
|
2668
|
+
print(std::cout);
|
|
2669
|
+
#endif
|
|
2670
|
+
if (self_verify)
|
|
2671
|
+
verify();
|
|
2672
|
+
}
|
|
2673
|
+
|
|
2674
|
+
#ifdef BTREE_TODO
|
|
2675
|
+
//! Erase all key/data pairs in the range [first,last). This function is
|
|
2676
|
+
//! currently not implemented by the B+ Tree.
|
|
2677
|
+
void erase(iterator /* first */, iterator /* last */)
|
|
2678
|
+
{
|
|
2679
|
+
abort();
|
|
2680
|
+
}
|
|
2681
|
+
#endif
|
|
2682
|
+
|
|
2683
|
+
//! \}
|
|
2684
|
+
|
|
2685
|
+
private:
|
|
2686
|
+
//! \name Private Erase Functions
|
|
2687
|
+
//! \{
|
|
2688
|
+
|
|
2689
|
+
/*!
|
|
2690
|
+
* Erase one (the first) key/data pair in the B+ tree matching key.
|
|
2691
|
+
*
|
|
2692
|
+
* Descends down the tree in search of key. During the descent the parent,
|
|
2693
|
+
* left and right siblings and their parents are computed and passed
|
|
2694
|
+
* down. Once the key/data pair is found, it is removed from the leaf. If
|
|
2695
|
+
* the leaf underflows 6 different cases are handled. These cases resolve
|
|
2696
|
+
* the underflow by shifting key/data pairs from adjacent sibling nodes,
|
|
2697
|
+
* merging two sibling nodes or trimming the tree.
|
|
2698
|
+
*/
|
|
2699
|
+
result_t erase_one_descend(const key_type& key, node* curr, node* left,
|
|
2700
|
+
node* right, InnerNode* left_parent,
|
|
2701
|
+
InnerNode* right_parent, InnerNode* parent,
|
|
2702
|
+
unsigned int parentslot)
|
|
2703
|
+
{
|
|
2704
|
+
if (curr->is_leafnode())
|
|
2705
|
+
{
|
|
2706
|
+
LeafNode* leaf = static_cast<LeafNode*>(curr);
|
|
2707
|
+
LeafNode* left_leaf = static_cast<LeafNode*>(left);
|
|
2708
|
+
LeafNode* right_leaf = static_cast<LeafNode*>(right);
|
|
2709
|
+
|
|
2710
|
+
unsigned short slot = find_lower(leaf, key);
|
|
2711
|
+
|
|
2712
|
+
if (slot >= leaf->slotuse || !key_equal(key, leaf->key(slot)))
|
|
2713
|
+
{
|
|
2714
|
+
TLX_BTREE_PRINT("Could not find key " << key << " to erase.");
|
|
2715
|
+
|
|
2716
|
+
return btree_not_found;
|
|
2717
|
+
}
|
|
2718
|
+
|
|
2719
|
+
TLX_BTREE_PRINT("Found key in leaf " << curr << " at slot "
|
|
2720
|
+
<< slot);
|
|
2721
|
+
|
|
2722
|
+
std::copy(leaf->slotdata + slot + 1, leaf->slotdata + leaf->slotuse,
|
|
2723
|
+
leaf->slotdata + slot);
|
|
2724
|
+
|
|
2725
|
+
leaf->slotuse--;
|
|
2726
|
+
|
|
2727
|
+
result_t myres = btree_ok;
|
|
2728
|
+
|
|
2729
|
+
// if the last key of the leaf was changed, the parent is notified
|
|
2730
|
+
// and updates the key of this leaf
|
|
2731
|
+
if (slot == leaf->slotuse)
|
|
2732
|
+
{
|
|
2733
|
+
if (parent && parentslot < parent->slotuse)
|
|
2734
|
+
{
|
|
2735
|
+
TLX_BTREE_ASSERT(parent->childid[parentslot] == curr);
|
|
2736
|
+
parent->slotkey[parentslot] = leaf->key(leaf->slotuse - 1);
|
|
2737
|
+
}
|
|
2738
|
+
else
|
|
2739
|
+
{
|
|
2740
|
+
if (leaf->slotuse >= 1)
|
|
2741
|
+
{
|
|
2742
|
+
TLX_BTREE_PRINT("Scheduling lastkeyupdate: key "
|
|
2743
|
+
<< leaf->key(leaf->slotuse - 1));
|
|
2744
|
+
myres |= result_t(btree_update_lastkey,
|
|
2745
|
+
leaf->key(leaf->slotuse - 1));
|
|
2746
|
+
}
|
|
2747
|
+
else
|
|
2748
|
+
{
|
|
2749
|
+
TLX_BTREE_ASSERT(leaf == root_);
|
|
2750
|
+
}
|
|
2751
|
+
}
|
|
2752
|
+
}
|
|
2753
|
+
|
|
2754
|
+
if (leaf->is_underflow() && !(leaf == root_ && leaf->slotuse >= 1))
|
|
2755
|
+
{
|
|
2756
|
+
// determine what to do about the underflow
|
|
2757
|
+
|
|
2758
|
+
// case : if this empty leaf is the root, then delete all nodes
|
|
2759
|
+
// and set root to nullptr.
|
|
2760
|
+
if (left_leaf == nullptr && right_leaf == nullptr)
|
|
2761
|
+
{
|
|
2762
|
+
TLX_BTREE_ASSERT(leaf == root_);
|
|
2763
|
+
TLX_BTREE_ASSERT(leaf->slotuse == 0);
|
|
2764
|
+
|
|
2765
|
+
free_node(root_);
|
|
2766
|
+
|
|
2767
|
+
root_ = leaf = nullptr;
|
|
2768
|
+
head_leaf_ = tail_leaf_ = nullptr;
|
|
2769
|
+
|
|
2770
|
+
// will be decremented soon by insert_start()
|
|
2771
|
+
TLX_BTREE_ASSERT(stats_.size == 1);
|
|
2772
|
+
TLX_BTREE_ASSERT(stats_.leaves == 0);
|
|
2773
|
+
TLX_BTREE_ASSERT(stats_.inner_nodes == 0);
|
|
2774
|
+
|
|
2775
|
+
return btree_ok;
|
|
2776
|
+
}
|
|
2777
|
+
// case : if both left and right leaves would underflow in case
|
|
2778
|
+
// of a shift, then merging is necessary. choose the more local
|
|
2779
|
+
// merger with our parent
|
|
2780
|
+
if ((left_leaf == nullptr || left_leaf->is_few()) &&
|
|
2781
|
+
(right_leaf == nullptr || right_leaf->is_few()))
|
|
2782
|
+
{
|
|
2783
|
+
if (left_parent == parent)
|
|
2784
|
+
myres |= merge_leaves(left_leaf, leaf, left_parent);
|
|
2785
|
+
else
|
|
2786
|
+
myres |= merge_leaves(leaf, right_leaf, right_parent);
|
|
2787
|
+
}
|
|
2788
|
+
// case : the right leaf has extra data, so balance right with
|
|
2789
|
+
// current
|
|
2790
|
+
else if ((left_leaf != nullptr && left_leaf->is_few()) &&
|
|
2791
|
+
(right_leaf != nullptr && !right_leaf->is_few()))
|
|
2792
|
+
{
|
|
2793
|
+
if (right_parent == parent)
|
|
2794
|
+
myres |= shift_left_leaf(leaf, right_leaf, right_parent,
|
|
2795
|
+
parentslot);
|
|
2796
|
+
else
|
|
2797
|
+
myres |= merge_leaves(left_leaf, leaf, left_parent);
|
|
2798
|
+
}
|
|
2799
|
+
// case : the left leaf has extra data, so balance left with
|
|
2800
|
+
// current
|
|
2801
|
+
else if ((left_leaf != nullptr && !left_leaf->is_few()) &&
|
|
2802
|
+
(right_leaf != nullptr && right_leaf->is_few()))
|
|
2803
|
+
{
|
|
2804
|
+
if (left_parent == parent)
|
|
2805
|
+
shift_right_leaf(left_leaf, leaf, left_parent,
|
|
2806
|
+
parentslot - 1);
|
|
2807
|
+
else
|
|
2808
|
+
myres |= merge_leaves(leaf, right_leaf, right_parent);
|
|
2809
|
+
}
|
|
2810
|
+
// case : both the leaf and right leaves have extra data and our
|
|
2811
|
+
// parent, choose the leaf with more data
|
|
2812
|
+
else if (left_parent == right_parent)
|
|
2813
|
+
{
|
|
2814
|
+
if (left_leaf->slotuse <= right_leaf->slotuse)
|
|
2815
|
+
myres |= shift_left_leaf(leaf, right_leaf, right_parent,
|
|
2816
|
+
parentslot);
|
|
2817
|
+
else
|
|
2818
|
+
shift_right_leaf(left_leaf, leaf, left_parent,
|
|
2819
|
+
parentslot - 1);
|
|
2820
|
+
}
|
|
2821
|
+
else
|
|
2822
|
+
{
|
|
2823
|
+
if (left_parent == parent)
|
|
2824
|
+
shift_right_leaf(left_leaf, leaf, left_parent,
|
|
2825
|
+
parentslot - 1);
|
|
2826
|
+
else
|
|
2827
|
+
myres |= shift_left_leaf(leaf, right_leaf, right_parent,
|
|
2828
|
+
parentslot);
|
|
2829
|
+
}
|
|
2830
|
+
}
|
|
2831
|
+
|
|
2832
|
+
return myres;
|
|
2833
|
+
}
|
|
2834
|
+
|
|
2835
|
+
// !curr->is_leafnode()
|
|
2836
|
+
InnerNode* inner = static_cast<InnerNode*>(curr);
|
|
2837
|
+
InnerNode* left_inner = static_cast<InnerNode*>(left);
|
|
2838
|
+
InnerNode* right_inner = static_cast<InnerNode*>(right);
|
|
2839
|
+
|
|
2840
|
+
node *myleft, *myright;
|
|
2841
|
+
InnerNode *myleft_parent, *myright_parent;
|
|
2842
|
+
|
|
2843
|
+
unsigned short slot = find_lower(inner, key);
|
|
2844
|
+
|
|
2845
|
+
if (slot == 0)
|
|
2846
|
+
{
|
|
2847
|
+
myleft =
|
|
2848
|
+
(left == nullptr) ?
|
|
2849
|
+
nullptr :
|
|
2850
|
+
static_cast<InnerNode*>(left)->childid[left->slotuse - 1];
|
|
2851
|
+
myleft_parent = left_parent;
|
|
2852
|
+
}
|
|
2853
|
+
else
|
|
2854
|
+
{
|
|
2855
|
+
myleft = inner->childid[slot - 1];
|
|
2856
|
+
myleft_parent = inner;
|
|
2857
|
+
}
|
|
2858
|
+
|
|
2859
|
+
if (slot == inner->slotuse)
|
|
2860
|
+
{
|
|
2861
|
+
myright = (right == nullptr) ?
|
|
2862
|
+
nullptr :
|
|
2863
|
+
static_cast<InnerNode*>(right)->childid[0];
|
|
2864
|
+
myright_parent = right_parent;
|
|
2865
|
+
}
|
|
2866
|
+
else
|
|
2867
|
+
{
|
|
2868
|
+
myright = inner->childid[slot + 1];
|
|
2869
|
+
myright_parent = inner;
|
|
2870
|
+
}
|
|
2871
|
+
|
|
2872
|
+
TLX_BTREE_PRINT("erase_one_descend into " << inner->childid[slot]);
|
|
2873
|
+
|
|
2874
|
+
result_t result =
|
|
2875
|
+
erase_one_descend(key, inner->childid[slot], myleft, myright,
|
|
2876
|
+
myleft_parent, myright_parent, inner, slot);
|
|
2877
|
+
|
|
2878
|
+
result_t myres = btree_ok;
|
|
2879
|
+
|
|
2880
|
+
if (result.has(btree_not_found))
|
|
2881
|
+
{
|
|
2882
|
+
return result;
|
|
2883
|
+
}
|
|
2884
|
+
|
|
2885
|
+
if (result.has(btree_update_lastkey))
|
|
2886
|
+
{
|
|
2887
|
+
if (parent && parentslot < parent->slotuse)
|
|
2888
|
+
{
|
|
2889
|
+
TLX_BTREE_PRINT("Fixing lastkeyupdate: key "
|
|
2890
|
+
<< result.lastkey << " into parent " << parent
|
|
2891
|
+
<< " at parentslot " << parentslot);
|
|
2892
|
+
|
|
2893
|
+
TLX_BTREE_ASSERT(parent->childid[parentslot] == curr);
|
|
2894
|
+
parent->slotkey[parentslot] = result.lastkey;
|
|
2895
|
+
}
|
|
2896
|
+
else
|
|
2897
|
+
{
|
|
2898
|
+
TLX_BTREE_PRINT("Forwarding lastkeyupdate: key "
|
|
2899
|
+
<< result.lastkey);
|
|
2900
|
+
myres |= result_t(btree_update_lastkey, result.lastkey);
|
|
2901
|
+
}
|
|
2902
|
+
}
|
|
2903
|
+
|
|
2904
|
+
if (result.has(btree_fixmerge))
|
|
2905
|
+
{
|
|
2906
|
+
// either the current node or the next is empty and should be
|
|
2907
|
+
// removed
|
|
2908
|
+
if (inner->childid[slot]->slotuse != 0)
|
|
2909
|
+
slot++;
|
|
2910
|
+
|
|
2911
|
+
// this is the child slot invalidated by the merge
|
|
2912
|
+
TLX_BTREE_ASSERT(inner->childid[slot]->slotuse == 0);
|
|
2913
|
+
|
|
2914
|
+
free_node(inner->childid[slot]);
|
|
2915
|
+
|
|
2916
|
+
std::copy(inner->slotkey + slot, inner->slotkey + inner->slotuse,
|
|
2917
|
+
inner->slotkey + slot - 1);
|
|
2918
|
+
std::copy(inner->childid + slot + 1,
|
|
2919
|
+
inner->childid + inner->slotuse + 1,
|
|
2920
|
+
inner->childid + slot);
|
|
2921
|
+
|
|
2922
|
+
inner->slotuse--;
|
|
2923
|
+
|
|
2924
|
+
if (inner->level == 1)
|
|
2925
|
+
{
|
|
2926
|
+
// fix split key for children leaves
|
|
2927
|
+
slot--;
|
|
2928
|
+
LeafNode* child = static_cast<LeafNode*>(inner->childid[slot]);
|
|
2929
|
+
inner->slotkey[slot] = child->key(child->slotuse - 1);
|
|
2930
|
+
}
|
|
2931
|
+
}
|
|
2932
|
+
|
|
2933
|
+
if (inner->is_underflow() && !(inner == root_ && inner->slotuse >= 1))
|
|
2934
|
+
{
|
|
2935
|
+
// case: the inner node is the root and has just one child. that
|
|
2936
|
+
// child becomes the new root
|
|
2937
|
+
if (left_inner == nullptr && right_inner == nullptr)
|
|
2938
|
+
{
|
|
2939
|
+
TLX_BTREE_ASSERT(inner == root_);
|
|
2940
|
+
TLX_BTREE_ASSERT(inner->slotuse == 0);
|
|
2941
|
+
|
|
2942
|
+
root_ = inner->childid[0];
|
|
2943
|
+
|
|
2944
|
+
inner->slotuse = 0;
|
|
2945
|
+
free_node(inner);
|
|
2946
|
+
|
|
2947
|
+
return btree_ok;
|
|
2948
|
+
}
|
|
2949
|
+
// case : if both left and right leaves would underflow in case
|
|
2950
|
+
// of a shift, then merging is necessary. choose the more local
|
|
2951
|
+
// merger with our parent
|
|
2952
|
+
if ((left_inner == nullptr || left_inner->is_few()) &&
|
|
2953
|
+
(right_inner == nullptr || right_inner->is_few()))
|
|
2954
|
+
{
|
|
2955
|
+
if (left_parent == parent)
|
|
2956
|
+
myres |= merge_inner(left_inner, inner, left_parent,
|
|
2957
|
+
parentslot - 1);
|
|
2958
|
+
else
|
|
2959
|
+
myres |= merge_inner(inner, right_inner, right_parent,
|
|
2960
|
+
parentslot);
|
|
2961
|
+
}
|
|
2962
|
+
// case : the right leaf has extra data, so balance right with
|
|
2963
|
+
// current
|
|
2964
|
+
else if ((left_inner != nullptr && left_inner->is_few()) &&
|
|
2965
|
+
(right_inner != nullptr && !right_inner->is_few()))
|
|
2966
|
+
{
|
|
2967
|
+
if (right_parent == parent)
|
|
2968
|
+
shift_left_inner(inner, right_inner, right_parent,
|
|
2969
|
+
parentslot);
|
|
2970
|
+
else
|
|
2971
|
+
myres |= merge_inner(left_inner, inner, left_parent,
|
|
2972
|
+
parentslot - 1);
|
|
2973
|
+
}
|
|
2974
|
+
// case : the left leaf has extra data, so balance left with
|
|
2975
|
+
// current
|
|
2976
|
+
else if ((left_inner != nullptr && !left_inner->is_few()) &&
|
|
2977
|
+
(right_inner != nullptr && right_inner->is_few()))
|
|
2978
|
+
{
|
|
2979
|
+
if (left_parent == parent)
|
|
2980
|
+
shift_right_inner(left_inner, inner, left_parent,
|
|
2981
|
+
parentslot - 1);
|
|
2982
|
+
else
|
|
2983
|
+
myres |= merge_inner(inner, right_inner, right_parent,
|
|
2984
|
+
parentslot);
|
|
2985
|
+
}
|
|
2986
|
+
// case : both the leaf and right leaves have extra data and our
|
|
2987
|
+
// parent, choose the leaf with more data
|
|
2988
|
+
else if (left_parent == right_parent)
|
|
2989
|
+
{
|
|
2990
|
+
if (left_inner->slotuse <= right_inner->slotuse)
|
|
2991
|
+
shift_left_inner(inner, right_inner, right_parent,
|
|
2992
|
+
parentslot);
|
|
2993
|
+
else
|
|
2994
|
+
shift_right_inner(left_inner, inner, left_parent,
|
|
2995
|
+
parentslot - 1);
|
|
2996
|
+
}
|
|
2997
|
+
else
|
|
2998
|
+
{
|
|
2999
|
+
if (left_parent == parent)
|
|
3000
|
+
shift_right_inner(left_inner, inner, left_parent,
|
|
3001
|
+
parentslot - 1);
|
|
3002
|
+
else
|
|
3003
|
+
shift_left_inner(inner, right_inner, right_parent,
|
|
3004
|
+
parentslot);
|
|
3005
|
+
}
|
|
3006
|
+
}
|
|
3007
|
+
|
|
3008
|
+
return myres;
|
|
3009
|
+
}
|
|
3010
|
+
|
|
3011
|
+
/*!
|
|
3012
|
+
* Erase one key/data pair referenced by an iterator in the B+ tree.
|
|
3013
|
+
*
|
|
3014
|
+
* Descends down the tree in search of an iterator. During the descent the
|
|
3015
|
+
* parent, left and right siblings and their parents are computed and passed
|
|
3016
|
+
* down. The difficulty is that the iterator contains only a pointer to a
|
|
3017
|
+
* LeafNode, which means that this function must do a recursive depth first
|
|
3018
|
+
* search for that leaf node in the subtree containing all pairs of the same
|
|
3019
|
+
* key. This subtree can be very large, even the whole tree, though in
|
|
3020
|
+
* practice it would not make sense to have so many duplicate keys.
|
|
3021
|
+
*
|
|
3022
|
+
* Once the referenced key/data pair is found, it is removed from the leaf
|
|
3023
|
+
* and the same underflow cases are handled as in erase_one_descend.
|
|
3024
|
+
*/
|
|
3025
|
+
result_t erase_iter_descend(const iterator& iter, node* curr, node* left,
|
|
3026
|
+
node* right, InnerNode* left_parent,
|
|
3027
|
+
InnerNode* right_parent, InnerNode* parent,
|
|
3028
|
+
unsigned int parentslot)
|
|
3029
|
+
{
|
|
3030
|
+
if (curr->is_leafnode())
|
|
3031
|
+
{
|
|
3032
|
+
LeafNode* leaf = static_cast<LeafNode*>(curr);
|
|
3033
|
+
LeafNode* left_leaf = static_cast<LeafNode*>(left);
|
|
3034
|
+
LeafNode* right_leaf = static_cast<LeafNode*>(right);
|
|
3035
|
+
|
|
3036
|
+
// if this is not the correct leaf, get next step in recursive
|
|
3037
|
+
// search
|
|
3038
|
+
if (leaf != iter.curr_leaf)
|
|
3039
|
+
{
|
|
3040
|
+
return btree_not_found;
|
|
3041
|
+
}
|
|
3042
|
+
|
|
3043
|
+
if (iter.curr_slot >= leaf->slotuse)
|
|
3044
|
+
{
|
|
3045
|
+
TLX_BTREE_PRINT("Could not find iterator ("
|
|
3046
|
+
<< iter.curr_leaf << "," << iter.curr_slot
|
|
3047
|
+
<< ") to erase. Invalid leaf node?");
|
|
3048
|
+
|
|
3049
|
+
return btree_not_found;
|
|
3050
|
+
}
|
|
3051
|
+
|
|
3052
|
+
unsigned short slot = iter.curr_slot;
|
|
3053
|
+
|
|
3054
|
+
TLX_BTREE_PRINT("Found iterator in leaf " << curr << " at slot "
|
|
3055
|
+
<< slot);
|
|
3056
|
+
|
|
3057
|
+
std::copy(leaf->slotdata + slot + 1, leaf->slotdata + leaf->slotuse,
|
|
3058
|
+
leaf->slotdata + slot);
|
|
3059
|
+
|
|
3060
|
+
leaf->slotuse--;
|
|
3061
|
+
|
|
3062
|
+
result_t myres = btree_ok;
|
|
3063
|
+
|
|
3064
|
+
// if the last key of the leaf was changed, the parent is notified
|
|
3065
|
+
// and updates the key of this leaf
|
|
3066
|
+
if (slot == leaf->slotuse)
|
|
3067
|
+
{
|
|
3068
|
+
if (parent && parentslot < parent->slotuse)
|
|
3069
|
+
{
|
|
3070
|
+
TLX_BTREE_ASSERT(parent->childid[parentslot] == curr);
|
|
3071
|
+
parent->slotkey[parentslot] = leaf->key(leaf->slotuse - 1);
|
|
3072
|
+
}
|
|
3073
|
+
else
|
|
3074
|
+
{
|
|
3075
|
+
if (leaf->slotuse >= 1)
|
|
3076
|
+
{
|
|
3077
|
+
TLX_BTREE_PRINT("Scheduling lastkeyupdate: key "
|
|
3078
|
+
<< leaf->key(leaf->slotuse - 1));
|
|
3079
|
+
myres |= result_t(btree_update_lastkey,
|
|
3080
|
+
leaf->key(leaf->slotuse - 1));
|
|
3081
|
+
}
|
|
3082
|
+
else
|
|
3083
|
+
{
|
|
3084
|
+
TLX_BTREE_ASSERT(leaf == root_);
|
|
3085
|
+
}
|
|
3086
|
+
}
|
|
3087
|
+
}
|
|
3088
|
+
|
|
3089
|
+
if (leaf->is_underflow() && !(leaf == root_ && leaf->slotuse >= 1))
|
|
3090
|
+
{
|
|
3091
|
+
// determine what to do about the underflow
|
|
3092
|
+
|
|
3093
|
+
// case : if this empty leaf is the root, then delete all nodes
|
|
3094
|
+
// and set root to nullptr.
|
|
3095
|
+
if (left_leaf == nullptr && right_leaf == nullptr)
|
|
3096
|
+
{
|
|
3097
|
+
TLX_BTREE_ASSERT(leaf == root_);
|
|
3098
|
+
TLX_BTREE_ASSERT(leaf->slotuse == 0);
|
|
3099
|
+
|
|
3100
|
+
free_node(root_);
|
|
3101
|
+
|
|
3102
|
+
root_ = leaf = nullptr;
|
|
3103
|
+
head_leaf_ = tail_leaf_ = nullptr;
|
|
3104
|
+
|
|
3105
|
+
// will be decremented soon by insert_start()
|
|
3106
|
+
TLX_BTREE_ASSERT(stats_.size == 1);
|
|
3107
|
+
TLX_BTREE_ASSERT(stats_.leaves == 0);
|
|
3108
|
+
TLX_BTREE_ASSERT(stats_.inner_nodes == 0);
|
|
3109
|
+
|
|
3110
|
+
return btree_ok;
|
|
3111
|
+
}
|
|
3112
|
+
// case : if both left and right leaves would underflow in case
|
|
3113
|
+
// of a shift, then merging is necessary. choose the more local
|
|
3114
|
+
// merger with our parent
|
|
3115
|
+
if ((left_leaf == nullptr || left_leaf->is_few()) &&
|
|
3116
|
+
(right_leaf == nullptr || right_leaf->is_few()))
|
|
3117
|
+
{
|
|
3118
|
+
if (left_parent == parent)
|
|
3119
|
+
myres |= merge_leaves(left_leaf, leaf, left_parent);
|
|
3120
|
+
else
|
|
3121
|
+
myres |= merge_leaves(leaf, right_leaf, right_parent);
|
|
3122
|
+
}
|
|
3123
|
+
// case : the right leaf has extra data, so balance right with
|
|
3124
|
+
// current
|
|
3125
|
+
else if ((left_leaf != nullptr && left_leaf->is_few()) &&
|
|
3126
|
+
(right_leaf != nullptr && !right_leaf->is_few()))
|
|
3127
|
+
{
|
|
3128
|
+
if (right_parent == parent)
|
|
3129
|
+
{
|
|
3130
|
+
myres |= shift_left_leaf(leaf, right_leaf, right_parent,
|
|
3131
|
+
parentslot);
|
|
3132
|
+
}
|
|
3133
|
+
else
|
|
3134
|
+
{
|
|
3135
|
+
myres |= merge_leaves(left_leaf, leaf, left_parent);
|
|
3136
|
+
}
|
|
3137
|
+
}
|
|
3138
|
+
// case : the left leaf has extra data, so balance left with
|
|
3139
|
+
// current
|
|
3140
|
+
else if ((left_leaf != nullptr && !left_leaf->is_few()) &&
|
|
3141
|
+
(right_leaf != nullptr && right_leaf->is_few()))
|
|
3142
|
+
{
|
|
3143
|
+
if (left_parent == parent)
|
|
3144
|
+
{
|
|
3145
|
+
shift_right_leaf(left_leaf, leaf, left_parent,
|
|
3146
|
+
parentslot - 1);
|
|
3147
|
+
}
|
|
3148
|
+
else
|
|
3149
|
+
{
|
|
3150
|
+
myres |= merge_leaves(leaf, right_leaf, right_parent);
|
|
3151
|
+
}
|
|
3152
|
+
}
|
|
3153
|
+
// case : both the leaf and right leaves have extra data and our
|
|
3154
|
+
// parent, choose the leaf with more data
|
|
3155
|
+
else if (left_parent == right_parent)
|
|
3156
|
+
{
|
|
3157
|
+
if (left_leaf->slotuse <= right_leaf->slotuse)
|
|
3158
|
+
{
|
|
3159
|
+
myres |= shift_left_leaf(leaf, right_leaf, right_parent,
|
|
3160
|
+
parentslot);
|
|
3161
|
+
}
|
|
3162
|
+
else
|
|
3163
|
+
{
|
|
3164
|
+
shift_right_leaf(left_leaf, leaf, left_parent,
|
|
3165
|
+
parentslot - 1);
|
|
3166
|
+
}
|
|
3167
|
+
}
|
|
3168
|
+
else
|
|
3169
|
+
{
|
|
3170
|
+
if (left_parent == parent)
|
|
3171
|
+
{
|
|
3172
|
+
shift_right_leaf(left_leaf, leaf, left_parent,
|
|
3173
|
+
parentslot - 1);
|
|
3174
|
+
}
|
|
3175
|
+
else
|
|
3176
|
+
{
|
|
3177
|
+
myres |= shift_left_leaf(leaf, right_leaf, right_parent,
|
|
3178
|
+
parentslot);
|
|
3179
|
+
}
|
|
3180
|
+
}
|
|
3181
|
+
}
|
|
3182
|
+
|
|
3183
|
+
return myres;
|
|
3184
|
+
}
|
|
3185
|
+
|
|
3186
|
+
// !curr->is_leafnode()
|
|
3187
|
+
InnerNode* inner = static_cast<InnerNode*>(curr);
|
|
3188
|
+
InnerNode* left_inner = static_cast<InnerNode*>(left);
|
|
3189
|
+
InnerNode* right_inner = static_cast<InnerNode*>(right);
|
|
3190
|
+
|
|
3191
|
+
// find first slot below which the searched iterator might be
|
|
3192
|
+
// located.
|
|
3193
|
+
|
|
3194
|
+
result_t result;
|
|
3195
|
+
unsigned short slot = find_lower(inner, iter.key());
|
|
3196
|
+
|
|
3197
|
+
while (slot <= inner->slotuse)
|
|
3198
|
+
{
|
|
3199
|
+
node *myleft, *myright;
|
|
3200
|
+
InnerNode *myleft_parent, *myright_parent;
|
|
3201
|
+
|
|
3202
|
+
if (slot == 0)
|
|
3203
|
+
{
|
|
3204
|
+
myleft = (left == nullptr) ? nullptr :
|
|
3205
|
+
static_cast<InnerNode*>(left)
|
|
3206
|
+
->childid[left->slotuse - 1];
|
|
3207
|
+
myleft_parent = left_parent;
|
|
3208
|
+
}
|
|
3209
|
+
else
|
|
3210
|
+
{
|
|
3211
|
+
myleft = inner->childid[slot - 1];
|
|
3212
|
+
myleft_parent = inner;
|
|
3213
|
+
}
|
|
3214
|
+
|
|
3215
|
+
if (slot == inner->slotuse)
|
|
3216
|
+
{
|
|
3217
|
+
myright = (right == nullptr) ?
|
|
3218
|
+
nullptr :
|
|
3219
|
+
static_cast<InnerNode*>(right)->childid[0];
|
|
3220
|
+
myright_parent = right_parent;
|
|
3221
|
+
}
|
|
3222
|
+
else
|
|
3223
|
+
{
|
|
3224
|
+
myright = inner->childid[slot + 1];
|
|
3225
|
+
myright_parent = inner;
|
|
3226
|
+
}
|
|
3227
|
+
|
|
3228
|
+
TLX_BTREE_PRINT("erase_iter_descend into " << inner->childid[slot]);
|
|
3229
|
+
|
|
3230
|
+
result =
|
|
3231
|
+
erase_iter_descend(iter, inner->childid[slot], myleft, myright,
|
|
3232
|
+
myleft_parent, myright_parent, inner, slot);
|
|
3233
|
+
|
|
3234
|
+
if (!result.has(btree_not_found))
|
|
3235
|
+
break;
|
|
3236
|
+
|
|
3237
|
+
// continue recursive search for leaf on next slot
|
|
3238
|
+
|
|
3239
|
+
if (slot < inner->slotuse &&
|
|
3240
|
+
key_less(inner->slotkey[slot], iter.key()))
|
|
3241
|
+
return btree_not_found;
|
|
3242
|
+
|
|
3243
|
+
++slot;
|
|
3244
|
+
}
|
|
3245
|
+
|
|
3246
|
+
if (slot > inner->slotuse)
|
|
3247
|
+
return btree_not_found;
|
|
3248
|
+
|
|
3249
|
+
result_t myres = btree_ok;
|
|
3250
|
+
|
|
3251
|
+
if (result.has(btree_update_lastkey))
|
|
3252
|
+
{
|
|
3253
|
+
if (parent && parentslot < parent->slotuse)
|
|
3254
|
+
{
|
|
3255
|
+
TLX_BTREE_PRINT("Fixing lastkeyupdate: key "
|
|
3256
|
+
<< result.lastkey << " into parent "
|
|
3257
|
+
<< parent << " at parentslot "
|
|
3258
|
+
<< parentslot);
|
|
3259
|
+
|
|
3260
|
+
TLX_BTREE_ASSERT(parent->childid[parentslot] == curr);
|
|
3261
|
+
parent->slotkey[parentslot] = result.lastkey;
|
|
3262
|
+
}
|
|
3263
|
+
else
|
|
3264
|
+
{
|
|
3265
|
+
TLX_BTREE_PRINT("Forwarding lastkeyupdate: key "
|
|
3266
|
+
<< result.lastkey);
|
|
3267
|
+
myres |= result_t(btree_update_lastkey, result.lastkey);
|
|
3268
|
+
}
|
|
3269
|
+
}
|
|
3270
|
+
|
|
3271
|
+
if (result.has(btree_fixmerge))
|
|
3272
|
+
{
|
|
3273
|
+
// either the current node or the next is empty and should be
|
|
3274
|
+
// removed
|
|
3275
|
+
if (inner->childid[slot]->slotuse != 0)
|
|
3276
|
+
slot++;
|
|
3277
|
+
|
|
3278
|
+
// this is the child slot invalidated by the merge
|
|
3279
|
+
TLX_BTREE_ASSERT(inner->childid[slot]->slotuse == 0);
|
|
3280
|
+
|
|
3281
|
+
free_node(inner->childid[slot]);
|
|
3282
|
+
|
|
3283
|
+
std::copy(inner->slotkey + slot,
|
|
3284
|
+
inner->slotkey + inner->slotuse,
|
|
3285
|
+
inner->slotkey + slot - 1);
|
|
3286
|
+
std::copy(inner->childid + slot + 1,
|
|
3287
|
+
inner->childid + inner->slotuse + 1,
|
|
3288
|
+
inner->childid + slot);
|
|
3289
|
+
|
|
3290
|
+
inner->slotuse--;
|
|
3291
|
+
|
|
3292
|
+
if (inner->level == 1)
|
|
3293
|
+
{
|
|
3294
|
+
// fix split key for children leaves
|
|
3295
|
+
slot--;
|
|
3296
|
+
LeafNode* child =
|
|
3297
|
+
static_cast<LeafNode*>(inner->childid[slot]);
|
|
3298
|
+
inner->slotkey[slot] = child->key(child->slotuse - 1);
|
|
3299
|
+
}
|
|
3300
|
+
}
|
|
3301
|
+
|
|
3302
|
+
if (inner->is_underflow() &&
|
|
3303
|
+
!(inner == root_ && inner->slotuse >= 1))
|
|
3304
|
+
{
|
|
3305
|
+
// case: the inner node is the root and has just one
|
|
3306
|
+
// child. that child becomes the new root
|
|
3307
|
+
if (left_inner == nullptr && right_inner == nullptr)
|
|
3308
|
+
{
|
|
3309
|
+
TLX_BTREE_ASSERT(inner == root_);
|
|
3310
|
+
TLX_BTREE_ASSERT(inner->slotuse == 0);
|
|
3311
|
+
|
|
3312
|
+
root_ = inner->childid[0];
|
|
3313
|
+
|
|
3314
|
+
inner->slotuse = 0;
|
|
3315
|
+
free_node(inner);
|
|
3316
|
+
|
|
3317
|
+
return btree_ok;
|
|
3318
|
+
}
|
|
3319
|
+
// case : if both left and right leaves would underflow in case
|
|
3320
|
+
// of a shift, then merging is necessary. choose the more local
|
|
3321
|
+
// merger with our parent
|
|
3322
|
+
if ((left_inner == nullptr || left_inner->is_few()) &&
|
|
3323
|
+
(right_inner == nullptr || right_inner->is_few()))
|
|
3324
|
+
{
|
|
3325
|
+
if (left_parent == parent)
|
|
3326
|
+
{
|
|
3327
|
+
myres |= merge_inner(left_inner, inner, left_parent,
|
|
3328
|
+
parentslot - 1);
|
|
3329
|
+
}
|
|
3330
|
+
else
|
|
3331
|
+
{
|
|
3332
|
+
myres |= merge_inner(inner, right_inner, right_parent,
|
|
3333
|
+
parentslot);
|
|
3334
|
+
}
|
|
3335
|
+
}
|
|
3336
|
+
// case : the right leaf has extra data, so balance right with
|
|
3337
|
+
// current
|
|
3338
|
+
else if ((left_inner != nullptr && left_inner->is_few()) &&
|
|
3339
|
+
(right_inner != nullptr && !right_inner->is_few()))
|
|
3340
|
+
{
|
|
3341
|
+
if (right_parent == parent)
|
|
3342
|
+
{
|
|
3343
|
+
shift_left_inner(inner, right_inner, right_parent,
|
|
3344
|
+
parentslot);
|
|
3345
|
+
}
|
|
3346
|
+
else
|
|
3347
|
+
{
|
|
3348
|
+
myres |= merge_inner(left_inner, inner, left_parent,
|
|
3349
|
+
parentslot - 1);
|
|
3350
|
+
}
|
|
3351
|
+
}
|
|
3352
|
+
// case : the left leaf has extra data, so balance left with
|
|
3353
|
+
// current
|
|
3354
|
+
else if ((left_inner != nullptr && !left_inner->is_few()) &&
|
|
3355
|
+
(right_inner != nullptr && right_inner->is_few()))
|
|
3356
|
+
{
|
|
3357
|
+
if (left_parent == parent)
|
|
3358
|
+
{
|
|
3359
|
+
shift_right_inner(left_inner, inner, left_parent,
|
|
3360
|
+
parentslot - 1);
|
|
3361
|
+
}
|
|
3362
|
+
else
|
|
3363
|
+
{
|
|
3364
|
+
myres |= merge_inner(inner, right_inner, right_parent,
|
|
3365
|
+
parentslot);
|
|
3366
|
+
}
|
|
3367
|
+
}
|
|
3368
|
+
// case : both the leaf and right leaves have extra data and our
|
|
3369
|
+
// parent, choose the leaf with more data
|
|
3370
|
+
else if (left_parent == right_parent)
|
|
3371
|
+
{
|
|
3372
|
+
if (left_inner->slotuse <= right_inner->slotuse)
|
|
3373
|
+
{
|
|
3374
|
+
shift_left_inner(inner, right_inner, right_parent,
|
|
3375
|
+
parentslot);
|
|
3376
|
+
}
|
|
3377
|
+
else
|
|
3378
|
+
{
|
|
3379
|
+
shift_right_inner(left_inner, inner, left_parent,
|
|
3380
|
+
parentslot - 1);
|
|
3381
|
+
}
|
|
3382
|
+
}
|
|
3383
|
+
else
|
|
3384
|
+
{
|
|
3385
|
+
if (left_parent == parent)
|
|
3386
|
+
{
|
|
3387
|
+
shift_right_inner(left_inner, inner, left_parent,
|
|
3388
|
+
parentslot - 1);
|
|
3389
|
+
}
|
|
3390
|
+
else
|
|
3391
|
+
{
|
|
3392
|
+
shift_left_inner(inner, right_inner, right_parent,
|
|
3393
|
+
parentslot);
|
|
3394
|
+
}
|
|
3395
|
+
}
|
|
3396
|
+
}
|
|
3397
|
+
|
|
3398
|
+
return myres;
|
|
3399
|
+
}
|
|
3400
|
+
|
|
3401
|
+
//! Merge two leaf nodes. The function moves all key/data pairs from right
|
|
3402
|
+
//! to left and sets right's slotuse to zero. The right slot is then removed
|
|
3403
|
+
//! by the calling parent node.
|
|
3404
|
+
result_t merge_leaves(LeafNode* left, LeafNode* right, InnerNode* parent)
|
|
3405
|
+
{
|
|
3406
|
+
TLX_BTREE_PRINT("Merge leaf nodes " << left << " and " << right
|
|
3407
|
+
<< " with common parent " << parent
|
|
3408
|
+
<< ".");
|
|
3409
|
+
(void) parent;
|
|
3410
|
+
|
|
3411
|
+
TLX_BTREE_ASSERT(left->is_leafnode() && right->is_leafnode());
|
|
3412
|
+
TLX_BTREE_ASSERT(parent->level == 1);
|
|
3413
|
+
|
|
3414
|
+
TLX_BTREE_ASSERT(left->slotuse + right->slotuse < leaf_slotmax);
|
|
3415
|
+
|
|
3416
|
+
std::copy(right->slotdata, right->slotdata + right->slotuse,
|
|
3417
|
+
left->slotdata + left->slotuse);
|
|
3418
|
+
|
|
3419
|
+
left->slotuse += right->slotuse;
|
|
3420
|
+
|
|
3421
|
+
left->next_leaf = right->next_leaf;
|
|
3422
|
+
if (left->next_leaf)
|
|
3423
|
+
left->next_leaf->prev_leaf = left;
|
|
3424
|
+
else
|
|
3425
|
+
tail_leaf_ = left;
|
|
3426
|
+
|
|
3427
|
+
right->slotuse = 0;
|
|
3428
|
+
|
|
3429
|
+
return btree_fixmerge;
|
|
3430
|
+
}
|
|
3431
|
+
|
|
3432
|
+
//! Merge two inner nodes. The function moves all key/childid pairs from
|
|
3433
|
+
//! right to left and sets right's slotuse to zero. The right slot is then
|
|
3434
|
+
//! removed by the calling parent node.
|
|
3435
|
+
static result_t merge_inner(InnerNode* left, InnerNode* right,
|
|
3436
|
+
InnerNode* parent, unsigned int parentslot)
|
|
3437
|
+
{
|
|
3438
|
+
TLX_BTREE_PRINT("Merge inner nodes " << left << " and " << right
|
|
3439
|
+
<< " with common parent " << parent
|
|
3440
|
+
<< ".");
|
|
3441
|
+
|
|
3442
|
+
TLX_BTREE_ASSERT(left->level == right->level);
|
|
3443
|
+
TLX_BTREE_ASSERT(parent->level == left->level + 1);
|
|
3444
|
+
|
|
3445
|
+
TLX_BTREE_ASSERT(parent->childid[parentslot] == left);
|
|
3446
|
+
|
|
3447
|
+
TLX_BTREE_ASSERT(left->slotuse + right->slotuse < inner_slotmax);
|
|
3448
|
+
|
|
3449
|
+
if (self_verify)
|
|
3450
|
+
{
|
|
3451
|
+
// find the left node's slot in the parent's children
|
|
3452
|
+
unsigned int leftslot = 0;
|
|
3453
|
+
while (leftslot <= parent->slotuse &&
|
|
3454
|
+
parent->childid[leftslot] != left)
|
|
3455
|
+
++leftslot;
|
|
3456
|
+
|
|
3457
|
+
TLX_BTREE_ASSERT(leftslot < parent->slotuse);
|
|
3458
|
+
TLX_BTREE_ASSERT(parent->childid[leftslot] == left);
|
|
3459
|
+
TLX_BTREE_ASSERT(parent->childid[leftslot + 1] == right);
|
|
3460
|
+
|
|
3461
|
+
TLX_BTREE_ASSERT(parentslot == leftslot);
|
|
3462
|
+
}
|
|
3463
|
+
|
|
3464
|
+
// retrieve the decision key from parent
|
|
3465
|
+
left->slotkey[left->slotuse] = parent->slotkey[parentslot];
|
|
3466
|
+
left->slotuse++;
|
|
3467
|
+
|
|
3468
|
+
// copy over keys and children from right
|
|
3469
|
+
std::copy(right->slotkey, right->slotkey + right->slotuse,
|
|
3470
|
+
left->slotkey + left->slotuse);
|
|
3471
|
+
std::copy(right->childid, right->childid + right->slotuse + 1,
|
|
3472
|
+
left->childid + left->slotuse);
|
|
3473
|
+
|
|
3474
|
+
left->slotuse += right->slotuse;
|
|
3475
|
+
right->slotuse = 0;
|
|
3476
|
+
|
|
3477
|
+
return btree_fixmerge;
|
|
3478
|
+
}
|
|
3479
|
+
|
|
3480
|
+
//! Balance two leaf nodes. The function moves key/data pairs from right to
|
|
3481
|
+
//! left so that both nodes are equally filled. The parent node is updated
|
|
3482
|
+
//! if possible.
|
|
3483
|
+
static result_t shift_left_leaf(LeafNode* left, LeafNode* right,
|
|
3484
|
+
InnerNode* parent, unsigned int parentslot)
|
|
3485
|
+
{
|
|
3486
|
+
TLX_BTREE_ASSERT(left->is_leafnode() && right->is_leafnode());
|
|
3487
|
+
TLX_BTREE_ASSERT(parent->level == 1);
|
|
3488
|
+
|
|
3489
|
+
TLX_BTREE_ASSERT(left->next_leaf == right);
|
|
3490
|
+
TLX_BTREE_ASSERT(left == right->prev_leaf);
|
|
3491
|
+
|
|
3492
|
+
TLX_BTREE_ASSERT(left->slotuse < right->slotuse);
|
|
3493
|
+
TLX_BTREE_ASSERT(parent->childid[parentslot] == left);
|
|
3494
|
+
|
|
3495
|
+
unsigned int shiftnum = (right->slotuse - left->slotuse) >> 1;
|
|
3496
|
+
|
|
3497
|
+
TLX_BTREE_PRINT("Shifting (leaf) " << shiftnum << " entries to left "
|
|
3498
|
+
<< left << " from right " << right
|
|
3499
|
+
<< " with common parent " << parent
|
|
3500
|
+
<< ".");
|
|
3501
|
+
|
|
3502
|
+
TLX_BTREE_ASSERT(left->slotuse + shiftnum < leaf_slotmax);
|
|
3503
|
+
|
|
3504
|
+
// copy the first items from the right node to the last slot in the left
|
|
3505
|
+
// node.
|
|
3506
|
+
|
|
3507
|
+
std::copy(right->slotdata, right->slotdata + shiftnum,
|
|
3508
|
+
left->slotdata + left->slotuse);
|
|
3509
|
+
|
|
3510
|
+
left->slotuse += shiftnum;
|
|
3511
|
+
|
|
3512
|
+
// shift all slots in the right node to the left
|
|
3513
|
+
|
|
3514
|
+
std::copy(right->slotdata + shiftnum, right->slotdata + right->slotuse,
|
|
3515
|
+
right->slotdata);
|
|
3516
|
+
|
|
3517
|
+
right->slotuse -= shiftnum;
|
|
3518
|
+
|
|
3519
|
+
// fixup parent
|
|
3520
|
+
if (parentslot < parent->slotuse)
|
|
3521
|
+
{
|
|
3522
|
+
parent->slotkey[parentslot] = left->key(left->slotuse - 1);
|
|
3523
|
+
return btree_ok;
|
|
3524
|
+
}
|
|
3525
|
+
|
|
3526
|
+
// the update is further up the tree
|
|
3527
|
+
return result_t(btree_update_lastkey, left->key(left->slotuse - 1));
|
|
3528
|
+
}
|
|
3529
|
+
|
|
3530
|
+
//! Balance two inner nodes. The function moves key/data pairs from right to
|
|
3531
|
+
//! left so that both nodes are equally filled. The parent node is updated
|
|
3532
|
+
//! if possible.
|
|
3533
|
+
static void shift_left_inner(InnerNode* left, InnerNode* right,
|
|
3534
|
+
InnerNode* parent, unsigned int parentslot)
|
|
3535
|
+
{
|
|
3536
|
+
TLX_BTREE_ASSERT(left->level == right->level);
|
|
3537
|
+
TLX_BTREE_ASSERT(parent->level == left->level + 1);
|
|
3538
|
+
|
|
3539
|
+
TLX_BTREE_ASSERT(left->slotuse < right->slotuse);
|
|
3540
|
+
TLX_BTREE_ASSERT(parent->childid[parentslot] == left);
|
|
3541
|
+
|
|
3542
|
+
unsigned int shiftnum = (right->slotuse - left->slotuse) >> 1;
|
|
3543
|
+
|
|
3544
|
+
TLX_BTREE_PRINT("Shifting (inner) " << shiftnum << " entries to left "
|
|
3545
|
+
<< left << " from right " << right
|
|
3546
|
+
<< " with common parent " << parent
|
|
3547
|
+
<< ".");
|
|
3548
|
+
|
|
3549
|
+
TLX_BTREE_ASSERT(left->slotuse + shiftnum < inner_slotmax);
|
|
3550
|
+
|
|
3551
|
+
if (self_verify)
|
|
3552
|
+
{
|
|
3553
|
+
// find the left node's slot in the parent's children and compare to
|
|
3554
|
+
// parentslot
|
|
3555
|
+
|
|
3556
|
+
unsigned int leftslot = 0;
|
|
3557
|
+
while (leftslot <= parent->slotuse &&
|
|
3558
|
+
parent->childid[leftslot] != left)
|
|
3559
|
+
++leftslot;
|
|
3560
|
+
|
|
3561
|
+
TLX_BTREE_ASSERT(leftslot < parent->slotuse);
|
|
3562
|
+
TLX_BTREE_ASSERT(parent->childid[leftslot] == left);
|
|
3563
|
+
TLX_BTREE_ASSERT(parent->childid[leftslot + 1] == right);
|
|
3564
|
+
|
|
3565
|
+
TLX_BTREE_ASSERT(leftslot == parentslot);
|
|
3566
|
+
}
|
|
3567
|
+
|
|
3568
|
+
// copy the parent's decision slotkey and childid to the first new key
|
|
3569
|
+
// on the left
|
|
3570
|
+
left->slotkey[left->slotuse] = parent->slotkey[parentslot];
|
|
3571
|
+
left->slotuse++;
|
|
3572
|
+
|
|
3573
|
+
// copy the other items from the right node to the last slots in the
|
|
3574
|
+
// left node.
|
|
3575
|
+
std::copy(right->slotkey, right->slotkey + shiftnum - 1,
|
|
3576
|
+
left->slotkey + left->slotuse);
|
|
3577
|
+
std::copy(right->childid, right->childid + shiftnum,
|
|
3578
|
+
left->childid + left->slotuse);
|
|
3579
|
+
|
|
3580
|
+
left->slotuse += shiftnum - 1;
|
|
3581
|
+
|
|
3582
|
+
// fixup parent
|
|
3583
|
+
parent->slotkey[parentslot] = right->slotkey[shiftnum - 1];
|
|
3584
|
+
|
|
3585
|
+
// shift all slots in the right node
|
|
3586
|
+
std::copy(right->slotkey + shiftnum, right->slotkey + right->slotuse,
|
|
3587
|
+
right->slotkey);
|
|
3588
|
+
std::copy(right->childid + shiftnum,
|
|
3589
|
+
right->childid + right->slotuse + 1, right->childid);
|
|
3590
|
+
|
|
3591
|
+
right->slotuse -= shiftnum;
|
|
3592
|
+
}
|
|
3593
|
+
|
|
3594
|
+
//! Balance two leaf nodes. The function moves key/data pairs from left to
|
|
3595
|
+
//! right so that both nodes are equally filled. The parent node is updated
|
|
3596
|
+
//! if possible.
|
|
3597
|
+
static void shift_right_leaf(LeafNode* left, LeafNode* right,
|
|
3598
|
+
InnerNode* parent, unsigned int parentslot)
|
|
3599
|
+
{
|
|
3600
|
+
TLX_BTREE_ASSERT(left->is_leafnode() && right->is_leafnode());
|
|
3601
|
+
TLX_BTREE_ASSERT(parent->level == 1);
|
|
3602
|
+
|
|
3603
|
+
TLX_BTREE_ASSERT(left->next_leaf == right);
|
|
3604
|
+
TLX_BTREE_ASSERT(left == right->prev_leaf);
|
|
3605
|
+
TLX_BTREE_ASSERT(parent->childid[parentslot] == left);
|
|
3606
|
+
|
|
3607
|
+
TLX_BTREE_ASSERT(left->slotuse > right->slotuse);
|
|
3608
|
+
|
|
3609
|
+
unsigned int shiftnum = (left->slotuse - right->slotuse) >> 1;
|
|
3610
|
+
|
|
3611
|
+
TLX_BTREE_PRINT("Shifting (leaf) " << shiftnum << " entries to right "
|
|
3612
|
+
<< right << " from left " << left
|
|
3613
|
+
<< " with common parent " << parent
|
|
3614
|
+
<< ".");
|
|
3615
|
+
|
|
3616
|
+
if (self_verify)
|
|
3617
|
+
{
|
|
3618
|
+
// find the left node's slot in the parent's children
|
|
3619
|
+
unsigned int leftslot = 0;
|
|
3620
|
+
while (leftslot <= parent->slotuse &&
|
|
3621
|
+
parent->childid[leftslot] != left)
|
|
3622
|
+
++leftslot;
|
|
3623
|
+
|
|
3624
|
+
TLX_BTREE_ASSERT(leftslot < parent->slotuse);
|
|
3625
|
+
TLX_BTREE_ASSERT(parent->childid[leftslot] == left);
|
|
3626
|
+
TLX_BTREE_ASSERT(parent->childid[leftslot + 1] == right);
|
|
3627
|
+
|
|
3628
|
+
TLX_BTREE_ASSERT(leftslot == parentslot);
|
|
3629
|
+
}
|
|
3630
|
+
|
|
3631
|
+
// shift all slots in the right node
|
|
3632
|
+
|
|
3633
|
+
TLX_BTREE_ASSERT(right->slotuse + shiftnum < leaf_slotmax);
|
|
3634
|
+
|
|
3635
|
+
std::copy_backward(right->slotdata, right->slotdata + right->slotuse,
|
|
3636
|
+
right->slotdata + right->slotuse + shiftnum);
|
|
3637
|
+
|
|
3638
|
+
right->slotuse += shiftnum;
|
|
3639
|
+
|
|
3640
|
+
// copy the last items from the left node to the first slot in the right
|
|
3641
|
+
// node.
|
|
3642
|
+
std::copy(left->slotdata + left->slotuse - shiftnum,
|
|
3643
|
+
left->slotdata + left->slotuse, right->slotdata);
|
|
3644
|
+
|
|
3645
|
+
left->slotuse -= shiftnum;
|
|
3646
|
+
|
|
3647
|
+
parent->slotkey[parentslot] = left->key(left->slotuse - 1);
|
|
3648
|
+
}
|
|
3649
|
+
|
|
3650
|
+
//! Balance two inner nodes. The function moves key/data pairs from left to
|
|
3651
|
+
//! right so that both nodes are equally filled. The parent node is updated
|
|
3652
|
+
//! if possible.
|
|
3653
|
+
static void shift_right_inner(InnerNode* left, InnerNode* right,
|
|
3654
|
+
InnerNode* parent, unsigned int parentslot)
|
|
3655
|
+
{
|
|
3656
|
+
TLX_BTREE_ASSERT(left->level == right->level);
|
|
3657
|
+
TLX_BTREE_ASSERT(parent->level == left->level + 1);
|
|
3658
|
+
|
|
3659
|
+
TLX_BTREE_ASSERT(left->slotuse > right->slotuse);
|
|
3660
|
+
TLX_BTREE_ASSERT(parent->childid[parentslot] == left);
|
|
3661
|
+
|
|
3662
|
+
unsigned int shiftnum = (left->slotuse - right->slotuse) >> 1;
|
|
3663
|
+
|
|
3664
|
+
TLX_BTREE_PRINT("Shifting (leaf) " << shiftnum << " entries to right "
|
|
3665
|
+
<< right << " from left " << left
|
|
3666
|
+
<< " with common parent " << parent
|
|
3667
|
+
<< ".");
|
|
3668
|
+
|
|
3669
|
+
if (self_verify)
|
|
3670
|
+
{
|
|
3671
|
+
// find the left node's slot in the parent's children
|
|
3672
|
+
unsigned int leftslot = 0;
|
|
3673
|
+
while (leftslot <= parent->slotuse &&
|
|
3674
|
+
parent->childid[leftslot] != left)
|
|
3675
|
+
++leftslot;
|
|
3676
|
+
|
|
3677
|
+
TLX_BTREE_ASSERT(leftslot < parent->slotuse);
|
|
3678
|
+
TLX_BTREE_ASSERT(parent->childid[leftslot] == left);
|
|
3679
|
+
TLX_BTREE_ASSERT(parent->childid[leftslot + 1] == right);
|
|
3680
|
+
|
|
3681
|
+
TLX_BTREE_ASSERT(leftslot == parentslot);
|
|
3682
|
+
}
|
|
3683
|
+
|
|
3684
|
+
// shift all slots in the right node
|
|
3685
|
+
|
|
3686
|
+
TLX_BTREE_ASSERT(right->slotuse + shiftnum < inner_slotmax);
|
|
3687
|
+
|
|
3688
|
+
std::copy_backward(right->slotkey, right->slotkey + right->slotuse,
|
|
3689
|
+
right->slotkey + right->slotuse + shiftnum);
|
|
3690
|
+
std::copy_backward(right->childid, right->childid + right->slotuse + 1,
|
|
3691
|
+
right->childid + right->slotuse + 1 + shiftnum);
|
|
3692
|
+
|
|
3693
|
+
right->slotuse += shiftnum;
|
|
3694
|
+
|
|
3695
|
+
// copy the parent's decision slotkey and childid to the last new key on
|
|
3696
|
+
// the right
|
|
3697
|
+
right->slotkey[shiftnum - 1] = parent->slotkey[parentslot];
|
|
3698
|
+
|
|
3699
|
+
// copy the remaining last items from the left node to the first slot in
|
|
3700
|
+
// the right node.
|
|
3701
|
+
std::copy(left->slotkey + left->slotuse - shiftnum + 1,
|
|
3702
|
+
left->slotkey + left->slotuse, right->slotkey);
|
|
3703
|
+
std::copy(left->childid + left->slotuse - shiftnum + 1,
|
|
3704
|
+
left->childid + left->slotuse + 1, right->childid);
|
|
3705
|
+
|
|
3706
|
+
// copy the first to-be-removed key from the left node to the parent's
|
|
3707
|
+
// decision slot
|
|
3708
|
+
parent->slotkey[parentslot] = left->slotkey[left->slotuse - shiftnum];
|
|
3709
|
+
|
|
3710
|
+
left->slotuse -= shiftnum;
|
|
3711
|
+
}
|
|
3712
|
+
|
|
3713
|
+
//! \}
|
|
3714
|
+
|
|
3715
|
+
#ifdef TLX_BTREE_DEBUG
|
|
3716
|
+
|
|
3717
|
+
public:
|
|
3718
|
+
//! \name Debug Printing
|
|
3719
|
+
//! \{
|
|
3720
|
+
|
|
3721
|
+
//! Print out the B+ tree structure with keys onto the given ostream. This
|
|
3722
|
+
//! function requires that the header is compiled with TLX_BTREE_DEBUG and
|
|
3723
|
+
//! that key_type is printable via std::ostream.
|
|
3724
|
+
void print(std::ostream& os) const
|
|
3725
|
+
{
|
|
3726
|
+
if (root_)
|
|
3727
|
+
{
|
|
3728
|
+
print_node(os, root_, 0, true);
|
|
3729
|
+
}
|
|
3730
|
+
}
|
|
3731
|
+
|
|
3732
|
+
//! Print out only the leaves via the double linked list.
|
|
3733
|
+
void print_leaves(std::ostream& os) const
|
|
3734
|
+
{
|
|
3735
|
+
os << "leaves:" << std::endl;
|
|
3736
|
+
|
|
3737
|
+
const LeafNode* n = head_leaf_;
|
|
3738
|
+
|
|
3739
|
+
while (n)
|
|
3740
|
+
{
|
|
3741
|
+
os << " " << n << std::endl;
|
|
3742
|
+
|
|
3743
|
+
n = n->next_leaf;
|
|
3744
|
+
}
|
|
3745
|
+
}
|
|
3746
|
+
|
|
3747
|
+
private:
|
|
3748
|
+
//! Recursively descend down the tree and print out nodes.
|
|
3749
|
+
static void print_node(std::ostream& os, const node* node,
|
|
3750
|
+
unsigned int depth = 0, bool recursive = false)
|
|
3751
|
+
{
|
|
3752
|
+
for (unsigned int i = 0; i < depth; i++)
|
|
3753
|
+
os << " ";
|
|
3754
|
+
|
|
3755
|
+
os << "node " << node << " level " << node->level << " slotuse "
|
|
3756
|
+
<< node->slotuse << std::endl;
|
|
3757
|
+
|
|
3758
|
+
if (node->is_leafnode())
|
|
3759
|
+
{
|
|
3760
|
+
const LeafNode* leafnode = static_cast<const LeafNode*>(node);
|
|
3761
|
+
|
|
3762
|
+
for (unsigned int i = 0; i < depth; i++)
|
|
3763
|
+
os << " ";
|
|
3764
|
+
os << " leaf prev " << leafnode->prev_leaf << " next "
|
|
3765
|
+
<< leafnode->next_leaf << std::endl;
|
|
3766
|
+
|
|
3767
|
+
for (unsigned int i = 0; i < depth; i++)
|
|
3768
|
+
os << " ";
|
|
3769
|
+
|
|
3770
|
+
for (unsigned short slot = 0; slot < leafnode->slotuse; ++slot)
|
|
3771
|
+
{
|
|
3772
|
+
// os << leafnode->key(slot) << " "
|
|
3773
|
+
// << "(data: " << leafnode->slotdata[slot] << ") ";
|
|
3774
|
+
os << leafnode->key(slot) << " ";
|
|
3775
|
+
}
|
|
3776
|
+
os << std::endl;
|
|
3777
|
+
}
|
|
3778
|
+
else
|
|
3779
|
+
{
|
|
3780
|
+
const InnerNode* innernode = static_cast<const InnerNode*>(node);
|
|
3781
|
+
|
|
3782
|
+
for (unsigned int i = 0; i < depth; i++)
|
|
3783
|
+
os << " ";
|
|
3784
|
+
|
|
3785
|
+
for (unsigned short slot = 0; slot < innernode->slotuse; ++slot)
|
|
3786
|
+
{
|
|
3787
|
+
os << "(" << innernode->childid[slot] << ") "
|
|
3788
|
+
<< innernode->slotkey[slot] << " ";
|
|
3789
|
+
}
|
|
3790
|
+
os << "(" << innernode->childid[innernode->slotuse] << ")"
|
|
3791
|
+
<< std::endl;
|
|
3792
|
+
|
|
3793
|
+
if (recursive)
|
|
3794
|
+
{
|
|
3795
|
+
for (unsigned short slot = 0; slot < innernode->slotuse + 1;
|
|
3796
|
+
++slot)
|
|
3797
|
+
{
|
|
3798
|
+
print_node(os, innernode->childid[slot], depth + 1,
|
|
3799
|
+
recursive);
|
|
3800
|
+
}
|
|
3801
|
+
}
|
|
3802
|
+
}
|
|
3803
|
+
}
|
|
3804
|
+
|
|
3805
|
+
//! \}
|
|
3806
|
+
#endif
|
|
3807
|
+
|
|
3808
|
+
public:
|
|
3809
|
+
//! \name Verification of B+ Tree Invariants
|
|
3810
|
+
//! \{
|
|
3811
|
+
|
|
3812
|
+
//! Run a thorough verification of all B+ tree invariants. The program
|
|
3813
|
+
//! aborts via tlx_die_unless() if something is wrong.
|
|
3814
|
+
void verify() const
|
|
3815
|
+
{
|
|
3816
|
+
key_type minkey, maxkey;
|
|
3817
|
+
tree_stats vstats;
|
|
3818
|
+
|
|
3819
|
+
if (root_)
|
|
3820
|
+
{
|
|
3821
|
+
verify_node(root_, &minkey, &maxkey, vstats);
|
|
3822
|
+
|
|
3823
|
+
tlx_die_unless(vstats.size == stats_.size);
|
|
3824
|
+
tlx_die_unless(vstats.leaves == stats_.leaves);
|
|
3825
|
+
tlx_die_unless(vstats.inner_nodes == stats_.inner_nodes);
|
|
3826
|
+
|
|
3827
|
+
verify_leaflinks();
|
|
3828
|
+
}
|
|
3829
|
+
}
|
|
3830
|
+
|
|
3831
|
+
private:
|
|
3832
|
+
//! Recursively descend down the tree and verify each node
|
|
3833
|
+
void verify_node(const node* n, key_type* minkey, key_type* maxkey,
|
|
3834
|
+
tree_stats& vstats) const
|
|
3835
|
+
{
|
|
3836
|
+
TLX_BTREE_PRINT("verifynode " << n);
|
|
3837
|
+
|
|
3838
|
+
if (n->is_leafnode())
|
|
3839
|
+
{
|
|
3840
|
+
const LeafNode* leaf = static_cast<const LeafNode*>(n);
|
|
3841
|
+
|
|
3842
|
+
tlx_die_unless(leaf == root_ || !leaf->is_underflow());
|
|
3843
|
+
tlx_die_unless(leaf->slotuse > 0);
|
|
3844
|
+
|
|
3845
|
+
for (unsigned short slot = 0; slot < leaf->slotuse - 1; ++slot)
|
|
3846
|
+
{
|
|
3847
|
+
tlx_die_unless(
|
|
3848
|
+
key_lessequal(leaf->key(slot), leaf->key(slot + 1)));
|
|
3849
|
+
}
|
|
3850
|
+
|
|
3851
|
+
*minkey = leaf->key(0);
|
|
3852
|
+
*maxkey = leaf->key(leaf->slotuse - 1);
|
|
3853
|
+
|
|
3854
|
+
vstats.leaves++;
|
|
3855
|
+
vstats.size += leaf->slotuse;
|
|
3856
|
+
}
|
|
3857
|
+
else // !n->is_leafnode()
|
|
3858
|
+
{
|
|
3859
|
+
const InnerNode* inner = static_cast<const InnerNode*>(n);
|
|
3860
|
+
vstats.inner_nodes++;
|
|
3861
|
+
|
|
3862
|
+
tlx_die_unless(inner == root_ || !inner->is_underflow());
|
|
3863
|
+
tlx_die_unless(inner->slotuse > 0);
|
|
3864
|
+
|
|
3865
|
+
for (unsigned short slot = 0; slot < inner->slotuse - 1; ++slot)
|
|
3866
|
+
{
|
|
3867
|
+
tlx_die_unless(
|
|
3868
|
+
key_lessequal(inner->key(slot), inner->key(slot + 1)));
|
|
3869
|
+
}
|
|
3870
|
+
|
|
3871
|
+
for (unsigned short slot = 0; slot <= inner->slotuse; ++slot)
|
|
3872
|
+
{
|
|
3873
|
+
const node* subnode = inner->childid[slot];
|
|
3874
|
+
key_type subminkey = key_type();
|
|
3875
|
+
key_type submaxkey = key_type();
|
|
3876
|
+
|
|
3877
|
+
tlx_die_unless(subnode->level + 1 == inner->level);
|
|
3878
|
+
verify_node(subnode, &subminkey, &submaxkey, vstats);
|
|
3879
|
+
|
|
3880
|
+
TLX_BTREE_PRINT("verify subnode " << subnode << ": "
|
|
3881
|
+
<< subminkey << " - "
|
|
3882
|
+
<< submaxkey);
|
|
3883
|
+
|
|
3884
|
+
if (slot == 0)
|
|
3885
|
+
*minkey = subminkey;
|
|
3886
|
+
else
|
|
3887
|
+
tlx_die_unless(
|
|
3888
|
+
key_greaterequal(subminkey, inner->key(slot - 1)));
|
|
3889
|
+
|
|
3890
|
+
if (slot == inner->slotuse)
|
|
3891
|
+
*maxkey = submaxkey;
|
|
3892
|
+
else
|
|
3893
|
+
tlx_die_unless(key_equal(inner->key(slot), submaxkey));
|
|
3894
|
+
|
|
3895
|
+
if (inner->level == 1 && slot < inner->slotuse)
|
|
3896
|
+
{
|
|
3897
|
+
// children are leaves and must be linked together in the
|
|
3898
|
+
// correct order
|
|
3899
|
+
const LeafNode* leafa =
|
|
3900
|
+
static_cast<const LeafNode*>(inner->childid[slot]);
|
|
3901
|
+
const LeafNode* leafb =
|
|
3902
|
+
static_cast<const LeafNode*>(inner->childid[slot + 1]);
|
|
3903
|
+
|
|
3904
|
+
tlx_die_unless(leafa->next_leaf == leafb);
|
|
3905
|
+
tlx_die_unless(leafa == leafb->prev_leaf);
|
|
3906
|
+
}
|
|
3907
|
+
if (inner->level == 2 && slot < inner->slotuse)
|
|
3908
|
+
{
|
|
3909
|
+
// verify leaf links between the adjacent inner nodes
|
|
3910
|
+
const InnerNode* parenta =
|
|
3911
|
+
static_cast<const InnerNode*>(inner->childid[slot]);
|
|
3912
|
+
const InnerNode* parentb =
|
|
3913
|
+
static_cast<const InnerNode*>(inner->childid[slot + 1]);
|
|
3914
|
+
|
|
3915
|
+
const LeafNode* leafa = static_cast<const LeafNode*>(
|
|
3916
|
+
parenta->childid[parenta->slotuse]);
|
|
3917
|
+
const LeafNode* leafb =
|
|
3918
|
+
static_cast<const LeafNode*>(parentb->childid[0]);
|
|
3919
|
+
|
|
3920
|
+
tlx_die_unless(leafa->next_leaf == leafb);
|
|
3921
|
+
tlx_die_unless(leafa == leafb->prev_leaf);
|
|
3922
|
+
}
|
|
3923
|
+
}
|
|
3924
|
+
}
|
|
3925
|
+
}
|
|
3926
|
+
|
|
3927
|
+
//! Verify the double linked list of leaves.
|
|
3928
|
+
void verify_leaflinks() const
|
|
3929
|
+
{
|
|
3930
|
+
const LeafNode* n = head_leaf_;
|
|
3931
|
+
|
|
3932
|
+
tlx_die_unless(n->level == 0);
|
|
3933
|
+
tlx_die_unless(!n || n->prev_leaf == nullptr);
|
|
3934
|
+
|
|
3935
|
+
unsigned int testcount = 0;
|
|
3936
|
+
|
|
3937
|
+
while (n)
|
|
3938
|
+
{
|
|
3939
|
+
tlx_die_unless(n->level == 0);
|
|
3940
|
+
tlx_die_unless(n->slotuse > 0);
|
|
3941
|
+
|
|
3942
|
+
for (unsigned short slot = 0; slot < n->slotuse - 1; ++slot)
|
|
3943
|
+
{
|
|
3944
|
+
tlx_die_unless(key_lessequal(n->key(slot), n->key(slot + 1)));
|
|
3945
|
+
}
|
|
3946
|
+
|
|
3947
|
+
testcount += n->slotuse;
|
|
3948
|
+
|
|
3949
|
+
if (n->next_leaf)
|
|
3950
|
+
{
|
|
3951
|
+
tlx_die_unless(key_lessequal(n->key(n->slotuse - 1),
|
|
3952
|
+
n->next_leaf->key(0)));
|
|
3953
|
+
|
|
3954
|
+
tlx_die_unless(n == n->next_leaf->prev_leaf);
|
|
3955
|
+
}
|
|
3956
|
+
else
|
|
3957
|
+
{
|
|
3958
|
+
tlx_die_unless(tail_leaf_ == n);
|
|
3959
|
+
}
|
|
3960
|
+
|
|
3961
|
+
n = n->next_leaf;
|
|
3962
|
+
}
|
|
3963
|
+
|
|
3964
|
+
tlx_die_unless(testcount == size());
|
|
3965
|
+
}
|
|
3966
|
+
|
|
3967
|
+
//! \}
|
|
3968
|
+
};
|
|
3969
|
+
|
|
3970
|
+
//! \}
|
|
3971
|
+
//! \}
|
|
3972
|
+
|
|
3973
|
+
} // namespace tlx
|
|
3974
|
+
|
|
3975
|
+
#endif // !TLX_CONTAINER_BTREE_HEADER
|
|
3976
|
+
|
|
3977
|
+
/******************************************************************************/
|