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

📄 mtnode.cpp

📁 M树源代码
💻 CPP
📖 第 1 页 / 共 3 页
字号:
/**********************************************************************                                                                    ** Copyright (c) 1997,1998, 1999                                      ** Multimedia DB Group and DEIS - CSITE-CNR,                          ** University of Bologna, Bologna, ITALY.                             **                                                                    ** All Rights Reserved.                                               **                                                                    ** Permission to use, copy, and distribute this software and its      ** documentation for NON-COMMERCIAL purposes and without fee is       ** hereby granted provided  that this copyright notice appears in     ** all copies.                                                        **                                                                    ** THE AUTHORS MAKE NO REPRESENTATIONS OR WARRANTIES ABOUT THE        ** SUITABILITY OF THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING  ** BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY,      ** FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT. THE AUTHOR  ** SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A      ** RESULT OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS    ** DERIVATIVES.                                                       **                                                                    **********************************************************************/#include <string.h>#include "MT.h"#include "MTpredicate.h"double MIN_UTIL;	// minimum node utilizationpp_function PROMOTE_PART_FUNCTION;	// promotion methodpv_function PROMOTE_VOTE_FUNCTION;	// confirmed promotion method (if needed)pp_function SECONDARY_PART_FUNCTION;	// root promotion method (can't use stored distances): used only for confirmed and MAX_UB_DIST methodsr_function RADIUS_FUNCTION;	// mM_RAD promotion method (if needed)int NUM_CANDIDATES;	// number of candidates for samplings_function SPLIT_FUNCTION;	// split methodextern int IOread;// used to quick-sort the entries in a node according to their distance from the parentintMTentrycmp(const void *x, const void *y){	double d=(*(MTentry **)x)->Key()->distance-(*(MTentry **)y)->Key()->distance;	int i=0;	if(d>0) i=1;	else if(d<0) i=-1;	return i;}// used in Split to find the next nearest entryintFindMin(double *vec, int veclen){	int i, min_i=-1;	double min=MAXDOUBLE;	for(i=0; i<veclen; i++)		if(vec[i]<min) {			min_i=i;			min=vec[i];		}	return min_i;}GiSTobject *MTnode::NCopy(){	MTnode *newnode=(MTnode *)Copy();	if((obj==NULL)&&(Path().Level()>1)) {		MTentry *e=Entry();		obj=newnode->obj=&(e->object());		delete e;	}	newnode->InvalidateEntries();	return newnode;}#ifdef PRINTING_OBJECTSvoidMTnode::Print(ostream& os) const{	if(obj!=NULL) os << *obj << " ";//	else cout << "obj NULL...\n";	os << ((MTnode *)this)->Path() << " #Entries: " << NumEntries() << ", Level " << Level();	if(IsLeaf()) os << "(Leaf)";	else os << "(Internal)";	os << ", Sibling: " << Sibling() << ", Size: " << Size() << "/" << Tree()->Store()->PageSize() << endl;	for(int i=0; i<NumEntries(); i++) (*this)[i]->Print(os);}#endifintMTnode::IsUnderFull(const GiSTstore &store) const{	return ((MIN_UTIL>0)&&(Size()<(int)(store.PageSize()*MIN_UTIL)));}voidMTnode::InvalidateEntries(){	for(int i=0; i<NumEntries(); i++)		((MTentry *)((*this)[i].Ptr()))->Key()->distance=-maxDist();}voidMTnode::InvalidateEntry(BOOL isNew){	GiSTpath path=Path();	if(path.Level()>1) {		MTnode *parent=((MT *)Tree())->ParentNode((MTnode *)this), *gparent=((MT *)Tree())->ParentNode(parent);		int i;		for(i=0; i<parent->NumEntries(); i++) {	// search the entry between the parent's children			MTentry *e=(MTentry *)((*parent)[i].Ptr());			if(e->Ptr()==path.Page()) {				if(isNew) e->Key()->distance=-maxDist();//				else e->Key()->distance=-e->Key()->distance;				e->Key()->splitted=TRUE;				break;			}		}		path.MakeParent();		for(i=0; i<gparent->NumEntries(); i++) {	// search the parent entry between the grandparent's children			MTentry *e=(MTentry *)((*gparent)[i].Ptr());			if(e->Ptr()==path.Page()) {				e->setmaxradius(-1);				break;			}		}		((MT *)Tree())->WriteNode(parent);	// write parent node (in inconsistent state)		((MT *)Tree())->WriteNode(gparent);	// write gparent node (to invalidate the parent's entry)		delete parent;		delete gparent;	}}MTentry *MTnode::Entry() const{	GiSTpath path=((MTnode *)this)->Path();	MTnode *parent=((MT *)Tree())->ParentNode((MTnode *)this);	MTentry *returnEntry=NULL;	for(int i=0; (i<parent->NumEntries())&&(returnEntry==NULL); i++)		if((*parent)[i].Ptr()->Ptr()==path.Page()) returnEntry=(MTentry *)(*parent)[i].Ptr()->Copy();	delete parent;	return returnEntry;}doubleMTnode::distance(int i) const{	MTentry *e=(MTentry *)((*this)[i].Ptr());//	if(e->Key()->distance>=0) cout << "Distance between " << obj << " & " << e->object() << " = " << e->Key()->distance << endl;//	else cout << "Computing distance between " << obj << " & " << e->object() << "..." << endl;	return (e->Key()->distance<0)? ((e->Key()->distance>-maxDist())? -e->Key()->distance: obj->distance(e->object())): e->Key()->distance;}// SearchMinPenalty returns where a new entry should be inserted.// Overriden to insert the distance from the parent in the new entry.GiSTpageMTnode::SearchMinPenalty(const GiSTentry& newEntry) const{	MTentry *minEntry=NULL;	MTpenalty *minPenalty=NULL;	for(int i=0; i<NumEntries(); i++) {		MTentry *e=(MTentry *)((*this)[i].Ptr());		assert((MTnode *)e->Node()==this);		MTpenalty *penalty=(MTpenalty *)e->Penalty(newEntry, minPenalty);	// use the alternate Penalty method in order to avoid some distance computations		if((minEntry==NULL)||(*penalty)<(*minPenalty)) {			minEntry=e;			if(minPenalty) delete minPenalty;			minPenalty=penalty;		}		else delete penalty;	}	((MTentry&)newEntry).Key()->distance=minPenalty->distance;	delete minPenalty;	return minEntry->Ptr();}voidMTnode::InsertBefore(const GiSTentry& entry, int index){	int n=NumEntries();	BOOL ordered=TRUE;	if(index>0) ordered=((*this)[index-1]->Compare(entry)<=0);	if(index<n) ordered=ordered&&((*this)[index]->Compare(entry)>=0);	if(ordered) {	// yes, the position is right for this entry		assert(index<=n);		GiSTentry *e=(GiSTentry *)entry.Copy();		e->SetLevel(Level());		e->SetPosition(index);		e->SetNode(this);		// Move everything else over		for(int i=n; i>index; i--) {			GiSTentry *e=(*this)[i-1];			e->SetPosition(i);			(*this)[i]=e;		}		// Stick the entry in		(*this)[index]=e;		// Bump up the count		SetNumEntries(n+1);	}	else Insert(entry);	// find the right place}// quick-sort the entries with respect to the distance from the parentvoidMTnode::Order(){	int i, obji=-1, n=NumEntries();	MTentry **array=new MTentry *[n], *objEntry=NULL;	for(i=0; i<n; i++) {		array[i]=(MTentry *)((MTentry *)(*this)[i].Ptr())->Copy();		if(obj==&((MTentry *)(*this)[i].Ptr())->object()) objEntry=array[i];	}	qsort(array, n, sizeof(MTentry *), MTentrycmp);	while(NumEntries()>0) DeleteEntry(0);	for(i=0; i<n; i++) {		InsertBefore(*(array[i]), i);		if(objEntry==array[i]) obji=i;		delete array[i];	}	delete []array;	if(obji>=0) obj=&((MTentry *)(*this)[obji].Ptr())->object();}GiSTnode *MTnode::PickSplit(){	MTnode *rightnode;	int leftdeletes, rightdeletes;	// number of entries to be deleted from each node	int *leftvec=new int[NumEntries()], *rightvec=new int[NumEntries()];	// array of entries to be deleted from each node	// promote the right node (possibly reassigning the left node);	// the right node's page is copied from left node; 	// we'll delete from the nodes as appropriate after the splitting phase//	cout << "In PickSplit with node " << this << "\n";	rightnode=PromotePart();	// now perform the split	Split(rightnode, leftvec, rightvec, &leftdeletes, &rightdeletes);	// complexity: O(n)	// given the deletion vectors, do bulk deletes	DeleteBulk(leftvec, leftdeletes);	rightnode->DeleteBulk(rightvec, rightdeletes);//	cout << "Nodes:\n" << this << rightnode;	// order the entries in both nodes	Order();	rightnode->Order();	delete []leftvec;	delete []rightvec;	// return the right node	return rightnode;}MTnode *MTnode::PromotePart(){	MTnode *newnode;	switch(PROMOTE_PART_FUNCTION) {		case RANDOM: {	// complexity: constant			int i, j;			// pick two *different* random entries//			cout << "Random promotion: ";			i=PickRandom(0, NumEntries());			do j=PickRandom(0, NumEntries());			while (j==i);			if(((MTentry *)(*this)[j].Ptr())->Key()->distance==0) {				int k=i; i=j; j=k;	// if we chose the parent entry, put it in the left node			}//			cout << "Entries " << (*this)[i].Ptr() << " & " << (*this)[j].Ptr() << " chosen.\n";			newnode=(MTnode *)NCopy();			// re-assign the nodes' object			newnode->obj=&((MTentry *)((*newnode)[j].Ptr()))->object();			obj=&((MTentry *)((*this)[i].Ptr()))->object();			if(((MTentry *)(*this)[i].Ptr())->Key()->distance>0) {	// if the parent object wasn't confirmed, invalidate also the parent				InvalidateEntry(TRUE);				InvalidateEntries();			}			else InvalidateEntry(FALSE);	// else, invalidate only the node's radii			break;		}		case CONFIRMED: {	// complexity: determined by the confirmed promotion algorithm			int i;			BOOL isRoot=TRUE;//			cout << "Confirmed promotion: ";//			for(i=0; (i<NumEntries())&&(isRoot); i++) isRoot=(((MTentry *)((*this)[i].Ptr()))->Key()->distance==-MAXDIST);			isRoot=(((MTentry *)((*this)[0].Ptr()))->Key()->distance==-maxDist());	// we have ordered entries			if(isRoot) {	// if we're splitting the root we have to use a policy that doesn't use stored distances				PROMOTE_PART_FUNCTION=SECONDARY_PART_FUNCTION;					newnode=PromotePart();				PROMOTE_PART_FUNCTION=CONFIRMED;			}			else {				int index=-1;				for(i=0; (i<NumEntries())&&(index<0); i++) if(((MTentry *)((*this)[i].Ptr()))->Key()->distance==0) index=i;				obj=&((MTentry *)((*this)[index].Ptr()))->object();				// now choose the right node parent				newnode=PromoteVote();			}			InvalidateEntry(FALSE);			break;

⌨️ 快捷键说明

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