数据库实验4数据库操作的实现算法B树索引查找.docx
《数据库实验4数据库操作的实现算法B树索引查找.docx》由会员分享,可在线阅读,更多相关《数据库实验4数据库操作的实现算法B树索引查找.docx(29页珍藏版)》请在冰豆网上搜索。
数据库实验4数据库操作的实现算法B树索引查找
实验四数据库操作的实现算法
1、实验目的:
掌握B树索引查找算法,多路归并排序算法,并用高级语言实现
2、实验内容:
选择熟悉的高级语言设计和实现程序完成下列功能:
1)随机生成具有1,000,000条记录的文本文件,每条记录的长度为128字节,其中固定包含一个整型属性A,属性A的值随机生成。
其他属性可以自己定义。
2)针对属性A,用高级语言实现两趟多路归并排序算法。
要求在内存分配8M空间用于外部归并排序
3)以属性A为键值,实现B树索引。
完成索引的插入,删除和查找。
3、实验报告
Ø截屏给出实验结果
Ø给出算法流程图
由于共有1000000个元组,每个元组128B,因此总大小为128M,又内存限制为8M,则至少要分成128M/8M=16组。
为了尽可能的减少I/O次数,因此采用16路归并的方法;为了减少归并的时间,采用败者树,在O(lgn)的时间复杂度内选出最小的A属性元组,这种方法从划分到归并,读入两次,写出两次,最少的I/O次数是4*1000000.
Ø附上程序代码
1、生成1000000个128字节的元组代码:
#include
#include
#include
#include
usingnamespacestd;
constintN=1000000;
stringRandomChineseCharacters()
{
//srand((unsigned)time(NULL));
inthigh=0xd7-0xc1;//16-55区汉字
intlow=0xfe-0xa1;
inthigh_zn;
intlow_zn;
charname[3];
name[2]='\0';
strings;
for(inti=0;i<60;i++)
{
high_zn=rand()%high+0xc1;
low_zn=rand()%low+0xa1;
name[0]=high_zn;
name[1]=low_zn;
s.append(name);
}
returns;
}
intmain()
{
ofstreamofp("example2.txt");
if(!
ofp.is_open())
{
cout<<"can'topenfile!
"<return0;
}
srand((unsigned)time(NULL));
intt1=0,t2=0;//4+
stringname;
for(inti=1;i<=N;i++)
{
t1=rand();
t2=i;
name=RandomChineseCharacters();
//cout<ofp<}
return0;
}
2、16组快速排序和16路归并排序的代码
//Extenal_Merge_Sort.cpp:
定义控制台应用程序的入口点。
//
#include"stdafx.h"
#include
#include
#include
#include
#include
#include
usingnamespacestd;
typedefstructData
{
intdata;
intnum;
charname[121];
}Data;
//利用败者树
constintN=1000000;//数据总量
constintFILE_NUM=16;//文件个数
constintMAX_PART=62500;//每一个文件大小
FILE*fpreads[FILE_NUM];
constintMIN=-1;//最小值,必须比要排序数字的最小值要小,否则出错
constintMAX=9999999;//最大值,必须比要排序数字的最大值要大,否则出错
intresult=0;
intcmp(constvoid*a,constvoid*b)
{
if((*(Data*)a).data>(*(Data*)b).data)
return1;
elseif((*(Data*)a).data<(*(Data*)b).data)
return-1;
else
return0;
}
//从unsort_data.txt中读取数据
intread_data(FILE*fp,Data*array,intN)
{
intlength=0;
for(inti=0;i=
fscanf_s(fp,"%d%d%s\n",&array[i].data,&array[i].num,array[i].name,_countof(array[i].name)));i++)
{
length++;
}
returnlength;
}
//打开data0.txt-data9.txt这10个文件
FILE*open_file(intcount,char*mode)
{
FILE*fpwrite=NULL;
charfilename[20];
memset(filename,0,20);
sprintf_s(filename,20,"data%d.txt",count);
fopen_s(&fpwrite,filename,mode);
assert(fpwrite!
=NULL);
returnfpwrite;
}
//向data0.txt-data9.txt这10个文件写入排好序的数据
voidwrite_data(Data*array,intN,intcount)
{
FILE*fpwrite=open_file(count,"w");
inti=0;
for(i=0;i{
fprintf(fpwrite,"%d%d%s\n",array[i].data,array[i].num,array[i].name);
}
fprintf(fpwrite,"%d%d%s\n",MAX,array[i-1].num,array[i-1].name);//在每个文件最后写入一个最大值,表示文件结束
fclose(fpwrite);
}
//内部排序,调用16次快速排序,产生data0.txt-data16.txt这10个有序文件
voidinterior_sort(void)
{
clock_tbegin=clock();
FILE*fpread=NULL;
fopen_s(&fpread,"unsort_data.txt","r");
assert(fpread!
=NULL);
intcount=0;
Data*array=newData[MAX_PART];
assert(array!
=NULL);
while
(1)
{
memset(array,0,sizeof(Data)*MAX_PART);
intlength=read_data(fpread,array,MAX_PART);
if(length==0)
{
break;
}
qsort(array,length,sizeof(Data),cmp);
write_data(array,length,count);
count++;
}
delete[]array;
fclose(fpread);
clock_tend=clock();
cout<<"16timesQuickSortUseTime"<<(end-begin)/CLK_TCK<<"s"<}
//调整
voidadjust(intls[],Datadata[],ints)
{
intt=(s+FILE_NUM)/2;
while(t)
{
if(data[s].data>data[ls[t]].data)
{
inttemp=s;
s=ls[t];
ls[t]=temp;
}
t/=2;
}
ls[0]=s;
}
voidcreate_loser_tree(intls[],Datadata[])
{
data[FILE_NUM].data=MIN;
for(inti=0;i{
ls[i]=FILE_NUM;
}
for(inti=FILE_NUM-1;i>=0;i--)
{
adjust(ls,data,i);
}
}
voidmerge_sort_by_losertree()
{
clock_tbegin=clock();
FILE*fpreads[FILE_NUM];//10个文件的描述符
Datadata[FILE_NUM+1];//10个文件的10个当前最小数据
intls[FILE_NUM];//存放败者索引的节点
intindex;
FILE*fpwrite=NULL;
fopen_s(&fpwrite,"sort_data_by_losertree.txt","w");
assert(fpwrite!
=NULL);
for(inti=0;i{
fpreads[i]=open_file(i,"r");
}
for(inti=0;i{
fscanf_s(fpreads[i],"%d%d%s\n",&data[i].data,&data[i].num,data[i].name,_countof(data[i].name));
}
create_loser_tree(ls,data);//创建败者树
while(data[ls[0]].data!
=MAX)
{
index=ls[0];
fprintf(fpwrite,"%d%d%s\n",data[index].data,data[index].num,data[index].name);
result++;//测试数据是否全部读完。
fscanf_s(fpreads[index],"%d%d%s\n",&data[index].data,&data[index].num,data[index].name,_countof(data[index].name));
adjust(ls,data,index);
}
for(inti=0;i{
fclose(fpreads[i]);
}
fclose(fpwrite);
clock_tend=clock();
cout<<"16PathMergeSortUseTime:
"<<(end-begin)/CLK_TCK<<"s"<}
int_tmain(intargc,_TCHAR*argv[])
{
interior_sort();
merge_sort_by_losertree();
cout<<"MergedData:
"<getchar();
return0;
}
3、B树索引的建立、查找、删除的代码
#include"stdafx.h"
#include
#include
#include
#include
/**
*@briefthedegreeofbtree
*keypernode:
[M-1,2M-1]
*childpernode:
[M,2M]
*/
#defineM2
#defineMaxSize1000001
typedefstructbtree_node{
intk[2*M-1];
structbtree_node*p[2*M];
intnum;
boolis_leaf;
}btree_node;
/**
*@briefallocateanewbtreenode
*default:
is_leaf==true
*
*@returnpointerofnewnode
*/
btree_node*btree_node_new();
/**
*@briefcreateabtreeroot
*
*@returnpointerofbtreeroot
*/
btree_node*btree_create();
/**
*@briefsplitchildifnumofkeyinchildexceed2M-1
*
*@paramparent:
parentofchild
*@parampos:
p[pos]pointstochild
*@paramchild:
thenodetobesplited
*
*@return
*/
intbtree_split_child(btree_node*parent,intpos,btree_node*child);
/**
*@briefinsertavalueintobtree
*thenumofkeyinnodelessthan2M-1
*
*@paramnode:
treeroot
*@paramtarget:
targettoinsert
*/
voidbtree_insert_nonfull(btree_node*node,inttarget);
/**
*@briefinsertavalueintobtree
*
*@paramroot:
treeroot
*@paramtarget:
targettoinsert
*
*@return:
newrootoftree
*/
btree_node*btree_insert(btree_node*root,inttarget);
/**
*@briefmergey,zandroot->k[pos]toleft
*thisappenswhileyandzbothhaveM-1keys
*
*@paramroot:
parentnode
*@parampos:
postionofy
*@paramy:
leftnodetomerge
*@paramz:
rightnodetomerge
*/
voidbtree_merge_child(btree_node*root,intpos,btree_node*y,btree_node*z);
/**
*@briefdeleteavluefrombtree
*
*@paramroot:
btreeroot
*@paramtarget:
targettodelete
*
*@return:
newrootoftree
*/
btree_node*btree_delete(btree_node*root,inttarget);
/**
*@briefdeleteavluefrombtree
*roothasatleastMkeys
*
*@paramroot:
btreeroot
*@paramtarget:
targettodelete
*
*@return
*/
voidbtree_delete_nonone(btree_node*root,inttarget);
/**
*@brieffindtherightmostvalue
*
*@paramroot:
rootoftree
*
*@return:
therightmostvalue
*/
intbtree_search_predecessor(btree_node*root);
/**
*@brieffindtheleftmostvalue
*
*@paramroot:
rootoftree
*
*@return:
theleftmostvalue
*/
intbtree_search_successor(btree_node*root);
/**
*@briefshiftavaluefromztoy
*
*@paramroot:
btreeroot
*@parampos:
positionofy
*@paramy:
leftnode
*@paramz:
rightnode
*/
voidbtree_shift_to_left_child(btree_node*root,intpos,btree_node*y,btree_node*z);
/**
*@briefshiftavaluefromztoy
*
*@paramroot:
btreeroot
*@parampos:
positionofy
*@paramy:
leftnode
*@paramz:
rightnode
*/
voidbtree_shift_to_right_child(btree_node*root,intpos,btree_node*y,btree_node*z);
/**
*@briefinordertraversethebtree
*
*@paramroot:
rootoftreee
*/
voidbtree_inorder_print(btree_node*root);
/**
*@brieflevelprintthebtree
*
*@paramroot:
rootoftree
*/
voidbtree_level_display(btree_node*root);
btree_node*btree_node_new()
{
btree_node*node=(btree_node*)malloc(sizeof(btree_node));
if(NULL==node){
returnNULL;
}
for(inti=0;i<2*M-1;i++){
node->k[i]=0;
}
for(inti=0;i<2*M;i++){
node->p[i]=NULL;
}
node->num=0;
node->is_leaf=true;
}
btree_node*btree_create()
{
btree_node*node=btree_node_new();
if(NULL==node){
returnNULL;
}
returnnode;
}
intbtree_split_child(btree_node*parent,intpos,btree_node*child)
{
btree_node*new_child=btree_node_new();
if(NULL==new_child){
return-1;
}
new_child->is_leaf=child->is_leaf;
new_child->num=M-1;
for(inti=0;inew_child->k[i]=child->k[i+M];
}
if(false==new_child->is_leaf){
for(inti=0;inew_child->p[i]=child->p[i+M];
}
}
child->num=M-1;
for(inti=parent->num;i>pos;i--){
parent->p[i+1]=parent->p[i];
}
parent->p[pos+1]=new_child;
for(inti=parent->num-1;i>=pos;i--){
parent->k[i+1]=parent->k[i];
}
parent->k[pos]=child->k[M-1];
parent->num+=1;
}
voidbtree_insert_nonfull(btree_node*node,inttarget)
{
if(1==node->is_leaf){
intpos=node->num;
while(pos>=1&&targetk[pos-1]){
node->k[pos]=node->k[pos-1];
pos--;
}
node->k[pos]=target;
node->num+=1