⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 btreealgorithms.h

📁 b tree code for index in the database design
💻 H
📖 第 1 页 / 共 2 页
字号:
		if ( less && !wasInCache ) releaseNode( less->addr_ );
	}

	for ( int i = 0; i < node->size_; i++ )
	{
		// Apply condition
		if ( !condition.satisfy( node->elems_[ i ].key_ ) )
		{
			// Stop key reached
			return false;
		}

		retList.push_back( TContainer::ElemType( node->elems_[ i ] ) );

		if ( node->elems_[ i ].link_ )
		{
			NodeType *kid = 0;
			bool wasInCache = nodeInCache( node->elems_[ i ].link_ );
			if ( !loadNode( &kid, node->elems_[ i ].link_ ) ) return false;
			if ( !allKeys( kid, retList ) )
			{
				// End of tree or condition had reached
				return false;
			}
			if ( kid && !wasInCache ) releaseNode( kid->addr_ );
		}
	}

	return true;
}

//	===================================================================
//	BTreeAlgorithms< NodeSize, KeyT, DataT, TController >::allKeys

template < int NodeSize, typename KeyT, typename DataT, 
template < int, typename, typename > class TController >
template < class TContainer >
bool BTreeAlgorithms< NodeSize, KeyT, DataT, TController >::allKeys( 
	NodeType *node, TContainer &retList )
{
	if ( !node ) return true;

	if ( node->less_ )
	{
		NodeType *less = 0;

		bool wasInCache = nodeInCache( node->less_ );
		if ( !loadNode( &less, node->less_ ) ) return false;
		if ( !allKeys( less, retList ) ) return false;
		if ( less && !wasInCache ) releaseNode( less->addr_ );
	}

	for ( int i = 0; i < node->count(); i++ )
	{
		retList.push_back( TContainer::ElemType( node->elems_[ i ] ) );

		if ( node->elems_[ i ].link_ )
		{
			NodeType *kid = 0;

			bool wasInCache = nodeInCache( node->elems_[ i ].link_ );
			if ( !loadNode( &kid, node->elems_[ i ].link_ ) ) return false;
			if ( !allKeys( kid, retList ) ) return false;
			if ( kid && !wasInCache ) releaseNode( kid->addr_ );
		}
	}

	return true;
}

//	===================================================================
//	BTreeAlgorithms< NodeSize, KeyT, DataT, TController >::close

template< int NodeSize, typename KeyT, typename DataT, 
template < int, typename, typename > class TController >
void BTreeAlgorithms< NodeSize, KeyT, DataT, TController >::close()
{
	setMaxCacheSize( 0 );
	releaseCache();
	delete root_;
	root_ = 0;

	closeController();
}

//	===================================================================
//	BTreeAlgorithms< NodeSize, KeyT, DataT, TController >::rebalance

template< int NodeSize, typename KeyT, typename DataT, 
template < int, typename, typename > class TController >
bool BTreeAlgorithms< NodeSize, KeyT, DataT, TController >::rebalance( NodeType *node, int parentIndex )
{
	int minimal = node->maxKeys >> 1;

	if ( node->count() >= minimal )
	{
		// Node is balanced
		return true;
	}

	NodeType *parent = 0;
	if ( !loadNode( &parent, node->parent_ ) )
	{
		return false;
	}

	NodeType *leftNode = 0, *rightNode = 0;
	NodeType *combinedNode = 0;

	if ( 0 == parentIndex - 1 )
	{
		if ( !loadNode( &leftNode, parent->less_ ) ) return false;
	}
	else if ( parentIndex >= 2 )
	{
		if ( !loadNode( &leftNode, parent->elems_[ parentIndex - 2 ].link_ ) ) return false;
	}

	if ( parent && parentIndex < parent->count() )
	{
		if ( !loadNode( &rightNode, parent->elems_[ parentIndex ].link_ ) ) return false;
	}

	if ( leftNode && leftNode->count() > minimal )
	{
		// Check left
		BTreeElement< KeyT, DataT > parentElem = parent->elems_[ parentIndex - 1 ];
		parentElem.link_ = node->less_;
		node->less_ = leftNode->elems_[ leftNode->count() - 1 ].link_;
		node->add( parentElem );
		node->flags_ = NodeType::NodeChanged;

		if ( node->less_ )
		{
			NodeType *less = 0;
			if ( !loadNode( &less, node->less_ ) ) return false;
			less->parent_ = node->addr_;
			less->flags_ = NodeType::NodeChanged;
		}

		BTreeElement< KeyT, DataT > largest;
		leftNode->removeAt( leftNode->count() - 1, largest );
		parent->elems_[ parentIndex - 1 ].key_ = largest.key_;
		parent->elems_[ parentIndex - 1 ].data_ = largest.data_;
		parent->flags_ = NodeType::NodeChanged;
	}
	else if ( rightNode && rightNode->count() > minimal )
	{
		// Check right
		BTreeElement< KeyT, DataT > parentElem = parent->elems_[ parentIndex ];
		parentElem.link_ = rightNode->less_;
		node->add( parentElem );

		if ( rightNode->less_ )
		{
			NodeType *less = 0;
			if ( !loadNode( &less, rightNode->less_ ) ) return false;
			less->parent_ = node->addr_;
			less->flags_ = NodeType::NodeChanged;
		}

		BTreeElement< KeyT, DataT > smallest;
		rightNode->removeAt( 0, smallest );
		rightNode->less_ = smallest.link_;
		parent->elems_[ parentIndex ].key_ = smallest.key_;
		parent->elems_[ parentIndex ].data_ = smallest.data_;
		parent->flags_ = NodeType::NodeChanged;
	}
	else
	{
		// Combine nodes
		if ( leftNode )
		{
			int index = leftNode->add( parent->elems_[ parentIndex - 1 ].key_,
				parent->elems_[ parentIndex - 1 ].data_ );
			leftNode->elems_[ index ].link_ = node->less_;
			if ( node->less_ )
			{
				NodeType *less = 0;
				if ( !loadNode( &less, node->less_ ) ) return false;
				less->parent_ = leftNode->addr_;
				less->flags_ = NodeType::NodeChanged;
			}

			if ( !combine( leftNode, node ) ) return false;
			combinedNode = leftNode;
			parent->removeAt( parentIndex - 1 );
		}
		else if ( rightNode )
		{
			int index = node->add( parent->elems_[ parentIndex ].key_,
				parent->elems_[ parentIndex ].data_ );
			node->elems_[ index ].link_ = rightNode->less_;

			if ( rightNode->less_ )
			{
				NodeType *less = 0;
				if ( !loadNode( &less, rightNode->less_ ) ) return false;
				less->parent_ = node->addr_;
				less->flags_ = NodeType::NodeChanged;
			}

			if ( !combine( node, rightNode ) ) return false;
			combinedNode = node;
			parent->removeAt( parentIndex );
		}

		parentIndex = -1;

		if ( parent && parent->parent_ )
		{
			// Find parent index
			NodeType *pp = 0;
			if ( !loadNode( &pp, parent->parent_ ) ) return false;

			if ( pp->less_ == parent->addr_ )
			{
				parentIndex = 0;
			}
			else
			{
				// Check parents parent
				for ( int i = 0; i < pp->count(); i++ )
				{
					if ( pp->elems_[ i ].link_ == parent->addr_ )
					{
						parentIndex = i + 1;
						break;
					}
				}
			}

			if ( parentIndex >= 0 )
			{
				if ( !rebalance( parent, parentIndex ) ) return false;
			}
		}
		else
		{
			// It is root
			if ( parent && parent->isEmpty() )
			{
				deleteNode( root_ );
				root_ = combinedNode;
				rootAddr( root_->addr_ );
				combinedNode->parent_ = 0;
				combinedNode->flags_ = NodeType::NodeChanged;
			}
		}
	}

	return true;
}

//	===================================================================
//	BTreeAlgorithms< NodeSize, KeyT, DataT, TController >::combine

template< int NodeSize, typename KeyT, typename DataT, 
template < int, typename, typename > class TController >
bool BTreeAlgorithms< NodeSize, KeyT, DataT, TController >::combine( NodeType *leftNode, 
													NodeType *rightNode )
{
	if ( leftNode->count() + rightNode->count() > leftNode->maxKeys )
	{
		// No space for combining
		return true;
	}

	for ( int i = 0; i < rightNode->count(); i++ )
	{
		leftNode->elems_[ leftNode->count() ] = rightNode->elems_[ i ];

		if ( rightNode->elems_[ i ].link_ )
		{
			NodeType *link = 0;
			if ( !loadNode( &link, rightNode->elems_[ i ].link_ ) ) return false;
			link->parent_ = leftNode->addr_;
			link->flags_ = NodeType::NodeChanged;
		}

		leftNode->size_++;
		leftNode->flags_ = NodeType::NodeChanged;
	}

	deleteNode( rightNode );
	return true;
}

//	===================================================================
//	BTreeAlgorithms< NodeSize, KeyT, DataT, TController >::pullOut

template< int NodeSize, typename KeyT, typename DataT, 
template < int, typename, typename > class TController >
bool BTreeAlgorithms< NodeSize, KeyT, DataT, TController >::pullOut( NodeType *node, 
																	int itemIndex )
{
	NodeType *leftSubtree = 0, *rightSubtree = 0;

	// Get subtrees
	if ( 0 == itemIndex )
	{
		if ( !loadNode( &leftSubtree, node->less_ ) ) return false;
	}
	else
	{
		if ( !loadNode( &leftSubtree, node->elems_[ itemIndex - 1 ].link_ ) ) return false;
	}

	if ( !loadNode( &rightSubtree, node->elems_[ itemIndex ].link_ ) ) return false;
	if ( !leftSubtree || !rightSubtree ) return false;

	if ( leftSubtree->count() > rightSubtree->count() )
	{
		// Left subtree is greater
		if ( leftSubtree->hasChilds() )
		{
			KeyT largestKey;
			DataT largestData;
			NodeType *largestNode = rightMost( leftSubtree, largestKey, largestData );
			node->elems_[ itemIndex ].key_ = largestKey;
			node->elems_[ itemIndex ].data_ = largestData;
			node->flags_ = NodeType::NodeChanged;
			largestNode->removeAt( largestNode->count() - 1 );

			NodeType *largestParent = 0;
			if ( !loadNode( &largestParent, largestNode->parent_ ) ) return false;
			if ( !rebalance( largestNode, largestParent->count() ) ) return false;
		}
		else
		{
			node->elems_[ itemIndex ].key_ = leftSubtree->elems_[ leftSubtree->count() - 1 ].key_;
			node->elems_[ itemIndex ].data_ = leftSubtree->elems_[ leftSubtree->count() - 1 ].data_;
			node->flags_ = NodeType::NodeChanged;
			leftSubtree->removeAt( leftSubtree->count() - 1 );
			if ( !rebalance( leftSubtree, itemIndex ) ) return false;
		}
	}
	else
	{
		// Right subtree is greater
		if ( rightSubtree->hasChilds() )
		{
			KeyT smallestKey;
			DataT smallestData;
			NodeType *smallestNode = leftMost( rightSubtree, smallestKey, smallestData );
			node->elems_[ itemIndex ].key_ = smallestKey;
			node->elems_[ itemIndex ].data_ = smallestData;
			node->flags_ = NodeType::NodeChanged;
			smallestNode->removeAt( 0 );
			if ( !rebalance( smallestNode, 0 ) ) return false;
		}
		else
		{
			node->elems_[ itemIndex ].key_ = rightSubtree->elems_[ 0 ].key_;
			node->elems_[ itemIndex ].data_ = rightSubtree->elems_[ 0 ].data_;
			node->flags_ = NodeType::NodeChanged;
			rightSubtree->removeAt( 0 );
			if ( !rebalance( rightSubtree, itemIndex + 1 ) ) return false;
		}
	}

	return true;
}

//	===================================================================
//	BTreeAlgorithms< NodeSize, KeyT, DataT, TController >::rightMost

template< int NodeSize, typename KeyT, typename DataT, 
template < int, typename, typename > class TController >
typename BTreeAlgorithms< NodeSize, KeyT, DataT, TController >::NodeType* 
		BTreeAlgorithms< NodeSize, KeyT, DataT, TController >::rightMost( NodeType *subtree, 
												KeyT &largestKey, DataT &largestData )
{
	if ( subtree->elems_[ subtree->count() - 1 ].link_ )
	{
		NodeType *rightMostLink = 0;
		if ( !loadNode( &rightMostLink, subtree->elems_[ subtree->count() - 1 ].link_ ) )
		{
			return 0;
		}

		return rightMost( rightMostLink, largestKey, largestData );
	}
	else
	{
		largestKey = subtree->elems_[ subtree->count() - 1 ].key_;
		largestData = subtree->elems_[ subtree->count() - 1 ].data_;
		return subtree;
	}
}

//	===================================================================
//	BTreeAlgorithms< NodeSize, KeyT, DataT, TController >::leftMost

template< int NodeSize, typename KeyT, typename DataT, 
template < int, typename, typename > class TController >
typename BTreeAlgorithms< NodeSize, KeyT, DataT, TController >::NodeType* 
			BTreeAlgorithms< NodeSize, KeyT, DataT, TController >::
			leftMost( NodeType *subtree, KeyT &smallestKey, DataT &smallestData )
{
	if ( subtree->less_ )
	{
		NodeType *leftMostLink = 0;
		if ( !loadNode( &leftMostLink, subtree->less_ ) )
		{
			return 0;
		}

		return leftMost( leftMostLink, smallestKey, smallestData );
	}
	else
	{
		smallestKey = subtree->elems_[ 0 ].key_;
		smallestData = subtree->elems_[ 0 ].data_;
		return subtree;
	}
}

//	===================================================================
//	BTreeAlgorithms< NodeSize, KeyT, DataT, TController >::splitNode

template< int NodeSize, typename KeyT, typename DataT, 
template < int, typename, typename > class TController >
bool BTreeAlgorithms< NodeSize, KeyT, DataT, TController >::splitNode( NodeType *node, 
						BTreeElement< KeyT, DataT > &median, NodeType **nodeRight )
{
	BTreeElement< KeyT, DataT > insertElem( median );
	int medianIndex = getMedian( node, median );

	NodeType nodeLeftTmp;
	*nodeRight = newNode();

	// Replace element
	node->removeAt( medianIndex );
	node->add( insertElem );

	( *nodeRight )->less_ = median.link_;
	if ( median.link_ )
	{
		NodeType *link = 0;
		if ( !loadNode( &link, median.link_ ) ) return false;
		link->parent_ = ( *nodeRight )->addr_;
		link->flags_ = NodeType::NodeChanged;
	}
	nodeLeftTmp.less_ = node->less_;

	for ( int i = 0; i < node->size_; i++ )
	{
		if ( node->elems_[ i ].key_ < median.key_ )
		{
			nodeLeftTmp.elems_[ nodeLeftTmp.size_ ] = node->elems_[ i ];
			nodeLeftTmp.size_++;
		}
		else
		{
			( *nodeRight )->elems_[ ( *nodeRight )->size_ ] = node->elems_[ i ];

			if ( node->elems_[ i ].link_ )
			{
				NodeType *link = 0;
				
				bool wasInCache = nodeInCache( node->elems_[ i ].link_ );
				if ( !loadNode( &link, node->elems_[ i ].link_ ) ) return false;
				link->parent_ = ( *nodeRight )->addr_;
				link->flags_ = NodeType::NodeChanged;
				if ( link && !wasInCache ) releaseNode( link->addr_ );
			}

			( *nodeRight )->size_++;
		}
	}

	// Prepare result
	( *nodeRight )->parent_ = node->parent_;
	nodeLeftTmp.parent_ = node->parent_;
	nodeLeftTmp.addr_ = node->addr_;
	*node = nodeLeftTmp;

	( *nodeRight )->flags_ = NodeType::NodeChanged;
	node->flags_ = NodeType::NodeChanged;

	median.link_ = ( *nodeRight )->addr_;
	return true;
}

//	===================================================================
//	BTreeAlgorithms< NodeSize, KeyT, DataT, TController >::getMedian

template< int NodeSize, typename KeyT, typename DataT, 
template < int, typename, typename > class TController >
int BTreeAlgorithms< NodeSize, KeyT, DataT, TController >::getMedian( 
	BTreeNode< NodeSize, KeyT, DataT > *node, 
	BTreeElement< KeyT, DataT > &elem )
{
	int medianRange = node->size_ >> 1;
	elem = node->elems_[ medianRange ];
	return medianRange;
}

//	===================================================================
//	BTreeAlgorithms< NodeSize, KeyT, DataT, TController >::findNode

template< int NodeSize, typename KeyT, typename DataT, 
template < int, typename, typename > class TController >
typename BTreeAlgorithms< NodeSize, KeyT, DataT, TController >::NodeType* 
		BTreeAlgorithms< NodeSize, KeyT, DataT, TController >::
		findNode( NodeType *node, const KeyT &key, int &retIndex, int &parentIndex, bool &found )
{
	if ( !node ) return 0;

	found = false;
	retIndex = -1;

	if ( node->find( key, retIndex ) )
	{
		// Key found
		found = true;
		return node;
	}

	int link = 0;

	if ( retIndex > 0 )
	{
		link = node->elems_[ retIndex - 1 ].link_;
	}
	else
	{
		link = node->less_;
	}

	if ( !link )
	{
		// No more kids
		return node;
	}
	else if ( link == node->addr_ )
	{
		// Simple cyclic traversal skip (in case of corrapted index)
		return 0;
	}

	NodeType *nextLink = 0;
	if ( !loadNode( &nextLink, link ) ) return 0;

	parentIndex = retIndex;
	return findNode( nextLink, key, retIndex, parentIndex, found );
}

#endif // __BTreeAlgorithms_h__

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -