散列表的思想就是把关键值送给一个散列函数,产生出一个散列值,这个值平均分布在一个整数区域中
=>散列表的实现的细节
1 当数组足够大时可以直接寻址不需要散列函数,常数操作时间O(1)
但数据规模远大于散列表大小时,考虑到空间的局限性,需要散列函数使关键值均匀的分开
2 散列表的装载因子,也就是实际决定散列表运算时间的参数, 数据规模n 除与 散列表数组大小m 即 α = n/m
3 散列函数核心是采取一些措施尽可能地使关键字均地分开,
确保关键字的独立性 => 构造一个良好的散列函数
4 当关键值均匀地存储在散列链表里,花费常数操作时间+链表长度(数据规模n 除与 散列表数组大小m )= O(1)+n/m
如果散列函数弱爆了,几乎所有值都在一个链表里,那么花费线性时间(根据数据规模n)O(n)
5 散列表的大小为1001(选取素数,有助于更加均匀的分开关键值)
6 散列函数通过一系列相乘相加(基数为31),获取散列值(获取方式请看代码),最终值根据数组大小求模返回
7 通过链表解决碰撞(散列值相同情况),即散列表相当于一个数组,每个元素有一个链表
8 通过键 获取值的 一种散列表(键值对,使用动态分配内存)
1 #include <iostream> 2 #include <crtdbg.h> 3 using namespace std; 4 5 typedef int DataType; 6 7 struct Node 8 { 9 DataType data; 10 char *str; 11 Node * next; 12 }; 13 //可以直接使用一个结构体Node实现 14 //之所以分开是为了增加灵活性 15 struct hashNode 16 { 17 Node *node; 18 //hashNode *next; 19 }; 20 21 class Hash 22 { 23 private: 24 enum 25 { 26 MULTIPLIER = 31, //乘法散列基数(根据书里的经验 37 也可) 27 SIZE = 1001 //使用素数确定散列表大小,尽可能把关键吗均匀地分开 28 }; 29 hashNode *hashTable[SIZE];//散列表 30 int hashFn(const char* key);//散列函数 31 public: 32 Hash() 33 { 34 Init(); 35 } 36 ~Hash() 37 { 38 Delete(); 39 } 40 void Init(); 41 void Delete(); 42 bool Insert(const char* key, const DataType &data); 43 bool ExtractData(const char* key);//通过键删除该值 44 bool Find(const char* key, DataType &outData); 45 void Print()const; 46 47 }; 48 int Hash::hashFn(const char* key) 49 { 50 int hashVal = 0; 51 for (const char *p = key; *p != '