滴水逆向联盟

标题: VC++2012编程演练数据结构《19》散列文件 [打印本页]

作者: 大灰狼    时间: 2014-8-26 08:15
标题: VC++2012编程演练数据结构《19》散列文件
散列文件是利用散列存储方式组织的文件,亦称为直接存取文件。它类似于散列表[1],即根据文件中关键字的特点,设计一个散列函数和处理冲突的方法,将记录散列到存储设备上。
  与散列表不同的是,对于文件来说,磁盘上的文件记录通常是成组存放的,若干个记录组成一个存储单位,在散列文件中,这个存储单位叫做桶(Bucket)。假如一个桶能存放m个记录,则当桶中已有m个同义词的记录时,存放第m+1个同义词会发生"溢出"。处理溢 出虽可采用散列表中处理冲突的各种方法,但对散列文件而言,主要采用拉链法。
  在散列文件中进行查找时,首先根据给定值求出散列桶地址,将基桶的记录读入内存,进行顺序查找,若找到关键字等于给定值的记录,则检索成功;否则,读入溢出桶的记录继续进行查找。
  在散列文件中删去一个记录,仅需对被删除记录标记即可。

文件优缺点

散列文件的优点是:文件随机存放,记录不需进行排序;插入、删除方便;存取速度快;不需要索引区,节省存储空间。其缺点是:不能进行顺序存取,只能按关键字随机存取,且询问方式限于简单询问,并且在经过多次插入、删除后,也可能造成文件结构不合理,需要重新组织文件。

散列表(Hash table,也叫哈希表),是根据关键码值(Key value)而直接进行访问的数据结构。也就是说,它通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度。这个映射函数叫做散列函数,存放记录的数组叫做散列表。
 * 若结构中存在关键字和K相等的记录,则必定在f(K)的存储位置上。由此,不需比较便可直接取得所查记录。称这个对应关系f为散列函数(Hash function),按这个思想建立的表为散列表。
  * 对不同的关键字可能得到同一散列地址,即key1≠key2,而f(key1)=f(key2),这种现象称冲突。具有相同函数值的关键字对该散列函数来说称做同义词。综上所述,根据散列函数H(key)和处理冲突的方法将一组关键字映象到一个有限的连续的地址集(区间)上,并以关键字在地址集中的“象” 作为记录在表中的存储位置,这种表便称为散列表,这一映象过程称为散列造表或散列,所得的存储位置称散列地址。这个现象也叫散列桶,在散列桶,只能通过顺序的方式来查找,一般只需要查找三次就可以找到。科学家计算过,当重载因子不超过75%,查找效率最高。
  * 若对于关键字集合中的任一个关键字,经散列函数映象到地址集合中任何一个地址的概率是相等的,则称此类散列函数为均匀散列函数(Uniform Hash function),这就是使关键字经过散列函数得到一个“随机的地址”,从而减少冲突。

打开IDE

我们创建一个工程

类实现如下


[cpp] view plaincopy








类调用如下


[cpp] view plaincopy


  • //散列文件的类实现的测试  
  • void main()  
  • { cout<<"运行结果:\n";  
  •   //定义保存记录的数组a并初始化  
  •   ElemType a[15]={{13,"li"},{18,"liu"},{17,"wphp"},{37,"menrm"},  
  •   {8,"ytong"},{22,"zhua"},{24,"push"},{48,"qian"},{34,"tang"},  
  •   {57,"shdm"},{55,"kang"},{30,"liuli"},{25,"qiaoh"},  
  •   {31,"dukun"},{17,"haiang"}};  
  •   //定义保存记录的数组b并初始化  
  •   ElemType b[16]={{23,"tang"},{38,"suan"},{56,"kony"},  
  •   {55,"shao"},{80,"caik"},{70,"ganwu"},{65,"dukun"},{42,"sini"},  
  •   {29,"liuda"},{43,"xitu"},{71,"taoto"},{77,"shouw"},  
  •   {93,"shum"},{69,"liyz"},{45,"xuyang"},{19,"wxy"}};  
  •   //定义散列表文件和主文件的名字,并由字符指针p1和p2所指向  
  •   char *p1=".\\HFile.idx", *p2=".\\HFile.dat";  
  •   //初始化散列表文件和主文件      
  •   HFile<ElemType> myfile(p1,p2);  
  •   //向散列文件插入数组a和b中保存的记录   
  •   myfile.THFInsertB(p1,p2,a,15);  
  •   myfile.THFInsertB(p1,p2,b,16);  
  •   //设mark用于保存删除或查找函数返回的值  
  •   int mark;  
  •   //定义x保存一个待插入的元素值或保存待删除或查找元素的关键字  
  •   ElemType x;  
  •   //利用键盘输入操作散列文件  
  •   while(1) {  
  •     cout<<endl<<"功能号表:"<<endl;  
  •     cout<<"1---向散列文件插入一个元素"<<endl;  
  •     cout<<"2---从散列文件中删除一个元素"<<endl;  
  •     cout<<"3---从散列文件中查找一个元素"<<endl;  
  •     cout<<"4---输出散列主文件"<<endl;  
  •     cout<<"5---结束运行"<<endl;  
  •     char ch;  
  •     cout<<"请输入你的选择(1-5): ";cin>>ch;  
  •     switch (ch)  
  •      {case '1':  
  •     cout<<"输入待插入元素x的值(一个整数和一个字符串):";  
  •       cin>>x.key>>x.rest;  
  •         myfile.THFInsertA(p1,p2,x);break;  
  •       case '2':  
  •         cout<<"输入待删除元素x的关键字:";  
  •           cin>>x.key;  
  •     mark=myfile.THFDelete(p1,p2,x);  
  •         if(mark==1) cout<<"删除成功!"<<x.key<<' '<<x.rest<<endl;  
  •     else cout<<"删除失败!"<<endl;break;  
  •       case '3':cout<<"输入待查找元素x的关键字:";  
  •             cin>>x.key;  
  •     mark=myfile.THFSearch(p1,p2,x);  
  •         if(mark==1)  
  •       cout<<"查找成功!"<<x.key<<' '<<x.rest<<endl;  
  •         else cout<<"查找失败!"<<endl;break;  
  •       case '4':myfile.THFPrint(p1,p2);break;  
  •       case '5':return;  
  •       default:cout<<"输入选择错误,请重输!"<<endl;  
  • }}}  






效果如下












欢迎光临 滴水逆向联盟 (http://dtdebug.com/) Powered by Discuz! X3.2