<C/C++数据结构>散列表(C++模板实现)
来源:互联网 发布:淘宝搜商品价格 编辑:程序博客网 时间:2024/06/16 00:18
参考资源:
http://student.zjzk.cn/course_ware/data_structure/web/CHAZHAO/chazhao9.4.1.htm
一,散列表的基本概念
散列方法不同于顺序查找、二分查找、二叉排序树及B-树上的查找。它不以关键字的比较为基本操作,采用直接寻址技术。在理想情况下,无须任何比较就可以找到待查关键字,查找的期望时间为O(1)。
1、散列表
设所有可能出现的关键字集合记为U(简称全集)。实际发生(即实际存储)的关键字集合记为K(|K|比|U|小得多)。
散列方法是使用函数h将U映射到表T[0..m-1]的下标上(m=O(|U|))。这样以U中关键字为自变量,以h为函数的运算结果就是相应结点的存储地址。从而达到在O(1)时间内就可完成查找。
其中:
① h:U→{0,1,2,…,m-1} ,通常称h为散列函数(Hash Function)。散列函数h的作用是压缩待处理的下标范围,使待处理的|U|个值减少到m个值,从而降低空间开销。
② T为散列表(Hash Table)。
③ h(Ki)(Ki∈U)是关键字为Ki结点存储地址(亦称散列值或散列地址)。
④ 将结点按其关键字的散列地址存储到散列表中的过程称为散列(Hashing)
2、散列表的冲突现象
(1)冲突
两个不同的关键字,由于散列函数值相同,因而被映射到同一表位置上。该现象称为冲突(Collision)或碰撞。发生冲突的两个关键字称为该散列函数的同义词(Synonym)。
【例】上图中的k2≠k5,但h(k2)=h(k5),故k2和K5所在的结点的存储地址相同。
(2)安全避免冲突的条件
最理想的解决冲突的方法是安全避免冲突。要做到这一点必须满足两个条件:
①其一是|U|≤m
②其二是选择合适的散列函数。
这只适用于|U|较小,且关键字均事先已知的情况,此时经过精心设计散列函数h有可能完全避免冲突。
(3)冲突不可能完全避免
通常情况下,h是一个压缩映像。虽然|K|≤m,但|U|>m,故无论怎样设计h,也不可能完全避免冲突。因此,只能在设计h时尽可能使冲突最少。同时还需要确定解决冲突的方法,使发生冲突的同义词能够存储到表中。
(4)影响冲突的因素
冲突的频繁程度除了与h相关外,还与表的填满程度相关。
设m和n分别表示表长和表中填人的结点数,则将α=n/m定义为散列表的装填因子(Load Factor)。α越大,表越满,冲突的机会也越大。通常取α≤1。
二,C++模板实现
(1)HashTable.h代码如下:
<span style="font-size:12px;">#include "stdafx.h" #include "iostream" using namespace std; template<class DataType> class HashTable { public: HashTable(int size) { maxSize=size; count=0; element =new DataType[size]; if (element == NULL) { exit(1); }else { for (int i=0;i<size;i++) { element[i]=NULL; } } } ~HashTable() { delete[] element; } DataType getData(int i) { if (i < 0 || i >= maxSize) { exit(1); }else { return element[i]; } } int getNum() { return count; } //哈希函数,返回ndata的(在数组中的)存储位置 int Hash(DataType nData); //插入操作,插入newData到哈希表中 int insertHash(DataType newData); //搜寻nData的当前存储位置 int getHash(DataType nData); private: int maxSize; int count; DataType *element; }; template<class DataType> int HashTable<DataType>::Hash(DataType newData) { return newData%maxSize;//留余数法 } //搜索nData的空白存储位置 template<class DataType> int HashTable<DataType>::insertHash(DataType newData) { if (getNum() == maxSize) { cerr<<"哈希表已经满"<<endl; } int pos=Hash(newData); if (element[pos] == NULL) { element[pos]=newData; count++; return 1; }else { int rpos=(pos+1)%maxSize; while (rpos != pos) { if (element[rpos] == NULL)//寻找没有存储数据的位置 { element[rpos]=newData; count++; return 1; } rpos=(rpos+1)%maxSize; } if (rpos == pos)//如果最终都没能找到空位,直接强行赋值 { element[rpos]=newData; count++; return 1; } } } //搜寻nData的当前存储位置 template<class DataType> int HashTable<DataType>::getHash(DataType newData) { int pos=Hash(newData); if (element[pos] == newData) { return pos; }else { int rpos=(pos+1)%maxSize; while (rpos != pos) { if (element[rpos] == newData) { return rpos; } rpos=(rpos+1)%maxSize; } if (rpos == pos) { cerr<<"无法查找指定元素的存储位置"<<endl; return -1; }else { return rpos; } } } </span><span style="font-size: 14px;"> </span>
(2)主测试代码如下:
<span style="font-size:12px;">// ConsoleAppHashTable.cpp : 定义控制台应用程序的入口点。 // #include "stdafx.h" #include "HashTable.h" #include "iostream" using namespace std; int _tmain(int argc, _TCHAR* argv[]) { int len=10; HashTable<int> hashTest(len); //一次插入元素 hashTest.insertHash(10); hashTest.insertHash(1); hashTest.insertHash(9); hashTest.insertHash(5); hashTest.insertHash(5); hashTest.insertHash(2); hashTest.insertHash(18); hashTest.insertHash(65); hashTest.insertHash(21); //输出哈希表中的元素 cout<<"表中的元素为: "; for (int i=0;i<len;i++) { cout<<hashTest.getData(i)<<" "; } cout<<endl; //查找元素位置 cout<<"元素9的位置:"; int pos=hashTest.getHash(9); if (pos == -1) { cout<<"无此元素"<<endl; }else { cout<<pos<<endl; } system("pause"); return 0; } </span>(3)测试结果:
0 0
- <C/C++数据结构>散列表(C++模板实现)
- 大二数据结构实验之散列表实现通讯录(C++)
- <数据结构>顺序列表的C语言实现
- [C++]数据结构:散列表HashTable的实现与简单应用
- <C/C++数据结构>队列(C++模板实现)
- 数据结构(C++)最小优先权队列实现<模板类>
- [数据结构] 顺序表的实现(c++/类模板)
- [数据结构]链表的实现(c++/类模板)
- [数据结构]栈的实现(c++/类模板)
- 数据结构(栈)c/c++/java实现
- 数据结构之---C语言实现散列表(哈希Hash表)
- 数据结构之单链表C++(模板)
- 数据结构之双链表C++(模板)
- 数据结构(C++)----单链表模板类
- 数据结构(c++)最小堆模板类
- C 基础数据结构---散列表(Hash) ADT
- 深入浅出数据结构C语言版(14)——散列表
- 深入浅出数据结构C语言版(14)——散列表
- TKPROF 命令语法
- 记录我的学习历程
- Squid服务日志分析
- Android 众多的布局属性详解
- POJ 3026 Brog Maze BFS+最小生成树
- <C/C++数据结构>散列表(C++模板实现)
- 多线程
- bzoj1014 [JSOI2008]火星人prefix
- 归档文件保存路径设置
- 为什么要用BitSet
- 反射获取构造器对象
- ASP.NET MVC模型部分验证
- [Stanford Cryptography I] Week1
- 【scrapy】学习Scrapy入门