C++实现---哈希表,哈希函数以及线性探测,二次探测

tech2022-08-28  103

#include<iostream> #include<time.h> #include<string> #include<math.h> #include<stdio.h> #define m 15//哈希表的表长 #define NullKey 0 //单元为空的标记 using namespace std; int HT[m] = {}, HC[m] = {};//HT是哈希表,HC是统计每个元素的插入时候的查找次数。并且初始化。 int H(int key) {//哈希函数     return key % 13; } //线性探测,既可以找到空的地方,没空的地方也可以找到是哈希表之前是否有这个值,查找中,如果第一次没找到,则调用这个函数,继续往下查找。 int Linedetece(int HT[], int H0, int key, int& cnt) {//线性探测法  参数:哈希表,之前哈希函数计算出来的下标值,关键字,查找次数     int HI;     for (int i = 1; i < m; ++i) {         cnt++;         HI = (H0 + i) & m;//按照线性探测法计算下一个哈希地址HI         if (HT[HI] == NullKey) {             return HI;         }         else if(HT[HI]==key)//如果找到和这个关键字重复的值,返回该下标 ,,若单元HI中元素的关键字为Key                             //查找会用到,插入的话不会用到这一步,因为如果插入有重复的会插入失败;         {             return HI;         }     }       return -1; } //二次探测,既可以找到空的地方,没空的地方也可以找到是哈希表之前是否有这个值,查找中,如果第一次没找到,则调用这个函数,继续往下查找。 int Seconddetect(int HT[], int H0, int key, int& cnt) {//二次探测法。     int HI;     for (int i = 1; i <= m/2; ++i) {         int i1 = i * i;//右边         int i2 = -i1;//左边         cnt++;         HI = (H0 + i1) % m;//按照线性探测法计算下一个哈希地址         if (HT[HI] == NullKey) {//若单元HI为空,则所查元素不存在。             return HI;         }         else if (HT[HI] == key) {//若单元HI中元素的关键字为Key             return HI;         }         cnt++;//因为一个下标要查左右两次,所以需要两次++;         HI = (H0 + i2) % m;         if (HI < 0) HI += m;//如果超出左边界。右边界不可能超出,左边界可能变为负数         if (HT[HI] == NullKey) {             return HI;         }         if (HT[HI] == key) {             return HI;         }     }     return -1; } //查找,第一种情况:第一次的位置为空, 则插入  第二种情况,第一次位置不为空,被占据,按线性往后找空的插入。都没找到返回0; bool InsertHash(int HT[], int key) {     int H0 = H(key);     int HI = -1, cnt = 1;     if (HT[H0] == NullKey) {         HC[H0] = 1;//统计查找次数         HT[H0] = key;//若单元H0为空,放入         return true;     }     else {         HI = Linedetece(HT, H0, key, cnt);//找到后面空的下标,或者和自己数字相等的下标,相等的下标情况会在下面的if去掉。         //HI = Seconddetect(HT, H0, key, cnt);线性查找         if ((HI != -1) && (HT[HI] == NullKey)) {//哈希表里面有空值,如果没有空值,则失败,             //如果哈希表没满或者该元素没有插入  //因为上面的探测函数有可能找到key值,也会将其下标返回。哈希表不能有重复的值。                                                  HC[HI] = cnt;             HT[HI] = key;//若单元H0为空,放入             return true;         }     }     return 0; } void print(int HT[]) {     for (int i = 0; i < m; i++) {         cout << HT[i] << "\t";     }     cout << endl; } //查找,第一种情况,查是不是空,第二种情况,查第一次有没有找到,第三种情况,查哈希表其他位置有没有,第四种情况 返回失败。 int SerachHasn(int HT[], int key) {     //在哈希表HT中查找关键字为key的元素,若查找成功,则返回哈希表的单元序号。     int H0 = H(key);//根据哈希函数key计算哈希地址。     int HI, cnt = 1;     if (HT[H0] == NullKey) {//若单元H0为空,则所查元素不存在         return -1;     }     else if(HT[H0]==key){//若单元HO中元素的关键字为key,则查找成功。         cout << "查找成功,比较次数:" << cnt << endl;         return 0;     }     else {//第一次查找不为空,也没找到(是因为之前的元素占据了这个元素应该初始所在位置)         HI = Linedetece(HT, H0, key, cnt);         if (HT[HI] == key) {//若单元HO中元素的关键字为key,则查找成功。             cout << "查找成功,比较次数:" << cnt << endl;             return HI;         }         else         {             return -1;//若单元H0为空,则所查元素不存在         }     } } int main() {     int x;

    //memset(HT, 0, sizeof(HT));//将哈希表HT的sizeof(HT)个字节用0替换。     //memset(HT, 0, sizeof(HC));     print(HT);     cout << "输入12个关键字,存入哈希表中" << endl;     for (int i = 0; i < 12; i++) {         cin >> x;         if (!InsertHash(HT, x)) {             cout << "创建哈希表失败" << endl;             return 0;         }     }     cout << "输出哈希表" << endl;     print(HT);//输出哈希表     print(HC);//输出记录每个元素查找次数的数组。     cout << "输入要查找的关键字" << endl;     cin >> x;     int result = SerachHasn(HT, x);     if (result == -1) {         cout << "没找到";     }     else     {         cout << "在第" << result + 1 << "的位置找到" << endl;     }     return 0;

}

最新回复(0)