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

📄 hnsrtreefileobj.cc

📁 R 树
💻 CC
📖 第 1 页 / 共 5 页
字号:
/* * HnSRTreeFileObj.cc * Copyright (C) 1997 Norio Katayama * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA * * 03/20/96 katayama@rd.nacsis.ac.jp * $Id: HnSRTreeFileObj.cc,v 1.5 1997/12/04 03:32:30 katayama Exp $ */#include <math.h>#include <stdio.h>#include <unistd.h>#include <sys/types.h>#include "HnSRTreeFile.hh"#include "HnSRTreeFileObj.hh"#include "HnAbort.hh"/* * Constructor and Destructor */HnSRTreeFileObj::HnSRTreeFileObj(const char *path,				 int dimension, int dataSize, int blockSize,				 int splitFactor, int reinsertFactor){	HnSRTreeLeaf leaf;	if(splitFactor < 0 || splitFactor > 50)		HnAbort("split factor %d is out of range.", splitFactor);	if(reinsertFactor < 0 || reinsertFactor > 50)		HnAbort("reinsert factor %d is out of range.", reinsertFactor);	initialize();	if((fp = fopen(path, "w+")) == NULL) {		setSysError("fopen(%s, \"w+\")", path);		return;	}	this->dimension = dimension;	this->dataSize = dataSize;	this->blockSize = blockSize;	this->fileSize = blockSize;	this->splitFactor = splitFactor;	this->reinsertFactor = reinsertFactor;	freeOffset = -1;	rootOffset = 0;	height = 0;	leaf = allocateLeaf();	rootOffset = leaf.getOffset();	height ++;	writeLeaf(leaf);	writeSuperBlock();}HnSRTreeFileObj::HnSRTreeFileObj(const char *path,				 int dimension, int dataSize, int blockSize,				 int splitFactor, int reinsertFactor,				 HnPointArray &points, HnDataArray &values,				 HnBool debug){	HnSRTreeLeaf leaf;	int numLevels, numSplits, numRootSplits, numNodeSplits;	if(splitFactor < 0 || splitFactor > 50)		HnAbort("split factor %d is out of range.", splitFactor);	if(reinsertFactor < 0 || reinsertFactor > 50)		HnAbort("reinsert factor %d is out of range.", reinsertFactor);	initialize();	if((fp = fopen(path, "w+")) == NULL) {		setSysError("fopen(%s, \"w+\")", path);		return;	}	this->dimension = dimension;	this->dataSize = dataSize;	this->blockSize = blockSize;	this->fileSize = blockSize;	this->splitFactor = splitFactor;	this->reinsertFactor = reinsertFactor;	freeOffset = -1;	rootOffset = 0;	height = 0;	this->debug = debug;	getSplitFactors(points, values, &numLevels, 			&numSplits, &numRootSplits, &numNodeSplits);	if(numLevels == 1) {		HnSRTreeLeaf leaf = allocateLeaf();		int i;		for(i=0; i<points.length(); i++)			leaf.append(points[i], values[i]);		rootOffset = leaf.getOffset();		height = numLevels;		writeLeaf(leaf);		writeSuperBlock();	}	else {		HnSRTreeNode node = allocateNode();		constructTree(points, values, 0, points.length(),			      0, numLevels, 0, numSplits,			      numRootSplits, numNodeSplits,			      node);		rootOffset = node.getOffset();		height = numLevels;		writeNode(node);		writeSuperBlock();	}}HnSRTreeFileObj::HnSRTreeFileObj(const char *path, const char *mode){	initialize();	if(strcmp(mode, "rw") == 0) {		if((fp = fopen(path, "r+")) == NULL) {			setSysError("fopen(\"%s\", \"r+\")", path);			return;		}	}	else if(strcmp(mode, "r") == 0) {		if((fp = fopen(path, "r")) == NULL) {			setSysError("fopen(\"%s\", \"r\")", path);			return;		}	}	else		HnAbort("mode must be `r' or `rw'");	readSuperBlock();}HnSRTreeFileObj::~HnSRTreeFileObj(void){	if(fp != NULL)		fclose(fp);}voidHnSRTreeFileObj::close(void){	if(fp != NULL)		fclose(fp);	fp = NULL;}/* * Super Block */voidHnSRTreeFileObj::writeSuperBlock(void){	SuperBlock superBlock;	superBlock.dimension = dimension;	superBlock.dataSize = dataSize;	superBlock.blockSize = blockSize;	superBlock.fileSize = fileSize;	superBlock.freeOffset = freeOffset;	superBlock.rootOffset = rootOffset;	superBlock.height = height;	superBlock.splitFactor = splitFactor;	superBlock.reinsertFactor = reinsertFactor;	if(fseek(fp, 0, SEEK_SET) < 0)		HnSysError("fseek");	if(fwrite(&superBlock, sizeof(superBlock), 1, fp) != 1)		HnSysError("fwrite");}voidHnSRTreeFileObj::readSuperBlock(void){	SuperBlock superBlock;	if(fseek(fp, 0, SEEK_SET) < 0)		HnSysError("fseek");	if(fread(&superBlock, sizeof(superBlock), 1, fp) != 1)		HnSysError("fread");	dimension = superBlock.dimension;	dataSize = superBlock.dataSize;	blockSize = superBlock.blockSize;	fileSize = superBlock.fileSize;	freeOffset = superBlock.freeOffset;	rootOffset = superBlock.rootOffset;	height = superBlock.height;	splitFactor = superBlock.splitFactor;	reinsertFactor = superBlock.reinsertFactor;}/* * Block */voidHnSRTreeFileObj::writeBlock(const HnSRTreeBlock &block){	if(fseek(fp, block.getOffset(), SEEK_SET) < 0)		HnSysError("fseek");	if(fwrite(block.getBytes(), block.getSize(), 1, fp) != 1)		HnSysError("fwrite");}HnSRTreeBlockHnSRTreeFileObj::readBlock(off_t offset){	char *bytes = new char[blockSize];	HnSRTreeBlock block;	if(fseek(fp, offset, SEEK_SET) < 0)		HnSysError("fseek");	if(fread(bytes, blockSize, 1, fp) != 1)		HnSysError("fread");	block = new_HnSRTreeBlock(offset, bytes, blockSize);	delete bytes;	return block;}off_tHnSRTreeFileObj::allocateBlock(void){	off_t offset;	if(freeOffset < 0) {		offset = fileSize;		fileSize += blockSize;		writeSuperBlock();	}	else {		HnSRTreeBlock block;		const char *bp;		HnSRTreeBlock::Type type;		offset = freeOffset;		block = readBlock(freeOffset);		bp = block.getBytes();		memcpy(&type, bp, sizeof(type));		bp += sizeof(type);		if(type != HnSRTreeBlock::FREE)			HnAbort("busy block is included in the free block "				"chain.");                memcpy(&freeOffset, bp, sizeof(off_t));                writeSuperBlock();        }        return offset;}voidHnSRTreeFileObj::releaseBlock(off_t offset){	HnSRTreeBlock block;	char *buffer = new char[blockSize];	char *bp;	HnSRTreeBlock::Type type;        memset(buffer, 0, blockSize);	bp = buffer;	type = HnSRTreeBlock::FREE;	memcpy(bp, &type, sizeof(type));	bp += sizeof(type);	memcpy(bp, &freeOffset, sizeof(off_t));        block = new_HnSRTreeBlock(offset, buffer, blockSize);	delete buffer;        writeBlock(block);        freeOffset = offset;        writeSuperBlock();}/* * Leaf */voidHnSRTreeFileObj::writeLeaf(const HnSRTreeLeaf &leaf){	HnSRTreeBlock block;	if(debug) {		fprintf(stderr, "HnSRTreeFileObj::writeLeaf: %s\n",			(char *)leaf.toString());	}	block = leaf.toBlock();	writeBlock(block);}HnSRTreeLeafHnSRTreeFileObj::allocateLeaf(void){	off_t offset;	offset = allocateBlock();	return new_HnSRTreeLeaf(dimension, dataSize, blockSize, offset);}/* * Node */voidHnSRTreeFileObj::writeNode(const HnSRTreeNode &node){	HnSRTreeBlock block;	block = node.toBlock();	writeBlock(block);}HnSRTreeNodeHnSRTreeFileObj::allocateNode(void){	off_t offset;	offset = allocateBlock();	return new_HnSRTreeNode(dimension, blockSize, offset);}/* * Store */voidHnSRTreeFileObj::store(const HnPoint &point, const HnData &data){	if(point.getDimension() != getDimension())		HnAbort("mismatch in the dimensions (point: %d, file: %d)",			point.getDimension(), getDimension());	if(data.length() > dataSize)		HnAbort("The size of data (%d) exceeds the limit (%d).",			data.length(), dataSize);	reinsertList = new_HnSRTreeReinsertArray();	reinsertedBlocks = new_HnSRTreeOffsetArray();	reinsertList.append(new_HnSRTreeReinsert(point, data));	while(reinsertList.length() != 0) {		if(reinsertList[0].getType() == HnSRTreeReinsert::POINT) {			HnPoint point = reinsertList[0].getPoint();			HnData data = reinsertList[0].getData();			reinsertList.remove(0);			insertPoint(point, data);		}		else {			off_t offset = reinsertList[0].getOffset();			int level = reinsertList[0].getLevel();			reinsertList.remove(0);			insertBlock(offset, level);		}	}	if(debug)		check();}voidHnSRTreeFileObj::insertPoint(const HnPoint &point, const HnData &data){	HnSRTreeStack stack;	HnSRTreeLeaf leaf;	stack = chooseLeaf(point);	leaf = stack.getTopLeaf();	if(!leaf.isFull()) {		leaf.append(point, data);		writeLeaf(leaf);		updateCoreAndRect(stack);	}	else {		int index = -1;		if(stack.getDepth() != 1 &&		   (index = reinsertedBlocks.indexOf(leaf.getOffset())) < 0) {			reinsertedBlocks.append(leaf.getOffset());			reinsertLeaf(stack, point, data);		}		else {			if(index >= 0)				reinsertedBlocks.remove(index);			splitLeaf(stack, point, data);		}	}}voidHnSRTreeFileObj::insertBlock(off_t offset, int level){	HnSRTreeBlock block = readBlock(offset);	HnSRTreeCore core;	HnRect rect;	HnSRTreeStack stack;	HnSRTreeNode node;	if(block.isNode()) {		HnSRTreeNode node = new_HnSRTreeNode(dimension, block);		core = node.getCore();		rect = node.getBoundingRect();	}	else if(block.isLeaf()) {		HnSRTreeLeaf leaf =			new_HnSRTreeLeaf(dimension, dataSize, block);		core = leaf.getCore();		rect = leaf.getBoundingRect();	}	else		HnAbort("unexpected block type.");	stack = chooseNode(core, level);	node = stack.getTopNode();	if(!node.isFull()) {		node.append(core, rect, offset);		writeNode(node);		updateCoreAndRect(stack);	}	else {		int index = -1;		if(stack.getDepth() != 1 &&		   (index = reinsertedBlocks.indexOf(node.getOffset())) < 0) {			reinsertedBlocks.append(node.getOffset());			reinsertNode(stack, core, rect, offset);		}		else {			if(index >= 0)				reinsertedBlocks.remove(index);			splitNode(stack, core, rect, offset);		}	}}HnSRTreeStackHnSRTreeFileObj::chooseLeaf(const HnPoint &point){	HnSRTreeStack stack = new_HnSRTreeStack();	HnSRTreeBlock block;	HnSRTreeNode node;	HnSRTreeLeaf leaf;	int index;	/*	 * NOTE:	 *	The stack is used for keeping the trace of the access path.	 *	Cursors indicates which entry is used at each node.	 */	block = readBlock(rootOffset);	while(block.isNode()) {		node = new_HnSRTreeNode(dimension, block);		index = chooseSubtree(node, point);		stack.push(node, index);		block = readBlock(node.getOffsetAt(index));	}	leaf = new_HnSRTreeLeaf(dimension, dataSize, block);	stack.push(leaf, -1);	return stack;}intHnSRTreeFileObj::chooseSubtree(const HnSRTreeNode &node, const HnPoint &point){	struct {		int index;		double distance;	} min, cur;	min.index = -1;	min.distance = -1;	for(cur.index=0; cur.index<node.getCount(); cur.index++) {		HnSRTreeCore core = node.getCoreAt(cur.index);		cur.distance = point.getDistance(core.getCenter());		if(min.index == -1)			min = cur;		else {			if(cur.distance < min.distance)				min = cur;		}	}	return min.index;}HnSRTreeStackHnSRTreeFileObj::chooseNode(const HnSRTreeCore &core, int level){	HnSRTreeStack stack = new_HnSRTreeStack();	HnSRTreeBlock block;	HnSRTreeNode node;	int index;	/*	 * NOTE:	 *	The stack is used for keeping the trace of the access path.	 *	Cursors indicates which entry is used at each node.	 */	block = readBlock(rootOffset);	while(stack.getDepth() != height - level) {		node = new_HnSRTreeNode(dimension, block);		index = chooseSubtree(node, core.getCenter());		stack.push(node, index);		block = readBlock(node.getOffsetAt(index));	}	return stack;}voidHnSRTreeFileObj::updateCoreAndRect(HnSRTreeStack stack){	HnSRTreeCore core;	HnRect rect;	HnSRTreeLeaf leaf;	HnSRTreeNode node;	int cursor;	if(stack.isTopNode()) {		node = stack.getTopNode();		core = node.getCore();		rect = node.getBoundingRect();		stack.pop();	}	else {		leaf = stack.getTopLeaf();		core = leaf.getCore();		rect = leaf.getBoundingRect();		stack.pop();	}	while(stack.getDepth() != 0) {

⌨️ 快捷键说明

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