哈希表的简单实现——线性探测

  1 #include <iostream>
  2 #include <vector>
  3 #include <algorithm>
  4 #include <string>
  5 
  6 using namespace std;
  7 
  8 bool isprime(int n) {
  9     int lim = sqrt(n) + 1;
 10     for (int i = 2;i <= lim;i++)if (n%i == 0)return 0;
 11     return 1;
 12 }
 13 
 14 int nextprime(int n) {
 15     for (int i = n + 1;;i++)if (isprime(i))return i;
 16 }
 17 
 18 enum State
 19 {
 20     EMPTY,
 21     EXIST,
 22     DELETE,
 23 };
 24 
 25 struct Node {
 26     string key;
 27     State s;
 28     Node(const string& key = "", State s = EMPTY) :key(key), s(s) {}
 29     Node& operator=(const Node&rhs) {
 30         key = rhs.key;
 31         s = rhs.s;
 32         return *this;
 33     }
 34 };
 35 
 36 int myhash(const string& key) {
 37     int hashVal = 0;
 38     for (size_t i = 0;i < key.length();i++)hashVal += 37 * hashVal + key[i];
 39 
 40     return hashVal;
 41 }
 42 
 43 class hashTable {
 44     typedef Node obj;
 45     friend void print(const hashTable& h) {
 46         for (int i = 0;i < h.size();i++)
 47             if (h._table[i].s == EXIST)cout << h._table[i].s << endl;
 48     }
 49 private:
 50     vector<obj> _table;
 51     int num;
 52     int findEle(const string&);
 53     size_t size()const { return _table.size(); }//不加const限定符常引用对象无法调用此函数
 54     void chk_memory();
 55 public:
 56     hashTable():num(0) {};
 57     bool find(const obj&);
 58     bool insert(const obj&);
 59     bool remove(const obj&);
 60 };
 61 
 62 inline
 63 int hashTable::findEle(const string& key) {//查找是否存在
 64     if (num == 0 || size() == 0)return -1;
 65     int hv = myhash(key) % size();
 66 
 67     while (hv >= 0 && _table[hv].s != EMPTY) {//必须保证表不为空,不然可能死循环
 68         State cur = _table[hv].s;
 69         if (cur == DELETE || _table[hv].key != key) {
 70             hv++;//线性探测法
 71             if (hv == size())hv = 0;
 72             continue;
 73         }
 74         //已找到
 75         return hv;
 76     }
 77     return -1;//表示未找到
 78 }
 79 
 80 bool hashTable::find(const obj& o) {
 81     return findEle(o.key) != -1;
 82 }
 83 
 84 bool hashTable::remove(const obj&o) {
 85     int hv = findEle(o.key);
 86     if (hv == -1)return false;
 87 
 88     _table[hv].s = DELETE;
 89     num--;
 90 
 91     return true;
 92 }
 93 
 94 void hashTable::chk_memory() {
 95     if (num + 2 >= size()) {
 96         int newsize = (num == 0 ? 3 : 2 * num);
 97         newsize = nextprime(newsize);
 98 
 99         vector<obj> oldtable = _table;
100         _table.resize(newsize);
101         for (int i = 0;i < _table.size();i++)_table[i].s = EMPTY;
102         for (int i = 0;i < oldtable.size();i++)
103             if (oldtable[i].s == EXIST)_table[i] = oldtable[i];
104     }
105 }
106 
107 bool hashTable::insert(const obj&o) {
108     if (find(o)) {
109         cout << "已存在该键值,插入失败!" << endl;
110         return false;
111     }
112 
113     chk_memory();//保证有内存可插入
114     
115     int hv = myhash(o.key) % size();
116     while (_table[hv].s == EXIST) {
117         hv++;
118         if (hv == size())hv = 0;
119     }
120 
121     num++;
122     _table[hv].key = o.key;
123     _table[hv].s = EXIST;
124     return true;
125 }
126 
127 int main(void) {
128     hashTable h;
129     Node n(string("xixi"));
130     h.insert(n);
131     h.insert(n);
132     if (h.find(n))cout << "hhh" << endl;
133     h.remove(n);
134     if (h.find(n))cout << "hhh" << endl;
135     return 0;
136 }

没有经过严格测试,代码如上

转载于:https://www.cnblogs.com/schsb/p/8601365.html

以下是一个简单的C语言实现哈希表的例子,其中包括了电话号码和用户名两个关键字的哈希表,并采用了线性探测再散列的方法解决冲突。 ```c #include <stdio.h> #include <string.h> #define MAX_SIZE 100 // 哈希表的最大大小 #define EMPTY -1 // 哈希表空位标志 typedef struct { char phone[12]; // 电话号码 char name[20]; // 用户名 char address[30]; // 地址 } Record; typedef struct { Record data; // 数据项 int key; // 哈希表关键字 } HashNode; void init(HashNode hash_table[], int size) { int i; for (i = 0; i < size; i++) { hash_table[i].key = EMPTY; } } int hash(char* key, int size) { int hash_val = 0; while (*key) { hash_val = (hash_val << 5) + *key++; } return hash_val % size; } int find(char* key, HashNode hash_table[], int size) { int hash_val = hash(key, size); while (hash_table[hash_val].key != EMPTY && strcmp(hash_table[hash_val].data.phone, key) != 0) { hash_val = (hash_val + 1) % size; } return hash_val; } void insert(Record data, HashNode hash_table[], int size) { int hash_val = find(data.phone, hash_table, size); hash_table[hash_val].data = data; hash_table[hash_val].key = hash(data.phone, size); } Record* search_by_phone(char* phone, HashNode hash_table[], int size) { int hash_val = find(phone, hash_table, size); if (hash_table[hash_val].key != EMPTY) { return &(hash_table[hash_val].data); } return NULL; } Record* search_by_name(char* name, HashNode hash_table[], int size) { int i; for (i = 0; i < size; i++) { if (hash_table[i].key != EMPTY && strcmp(hash_table[i].data.name, name) == 0) { return &(hash_table[i].data); } } return NULL; } int main() { HashNode phone_table[MAX_SIZE], name_table[MAX_SIZE]; Record record; int i, size; char phone[12], name[20]; printf("Enter the size of hash table: "); scanf("%d", &size); init(phone_table, size); init(name_table, size); printf("\nEnter the phone number, name and address of the person:\n"); for (i = 0; i < size; i++) { printf("Record %d:\n", i + 1); scanf("%s %s %s", record.phone, record.name, record.address); insert(record, phone_table, size); insert(record, name_table, size); } printf("\nEnter the phone number to search: "); scanf("%s", phone); Record* r = search_by_phone(phone, phone_table, size); if (r != NULL) { printf("Phone: %s\nName: %s\nAddress: %s\n", r->phone, r->name, r->address); } else { printf("Record not found.\n"); } printf("\nEnter the name to search: "); scanf("%s", name); r = search_by_name(name, name_table, size); if (r != NULL) { printf("Phone: %s\nName: %s\nAddress: %s\n", r->phone, r->name, r->address); } else { printf("Record not found.\n"); } return 0; } ``` 在这个例子中,我们首先定义了一个 `Record` 结构体来表示每个记录,其中包括了电话号码、用户名和地址三个数据项。然后我们定义了一个 `HashNode` 结构体来表示哈希表中的节点,其中包括了一个 `data` 成员来存储记录数据,以及一个 `key` 成员来存储哈希表关键字。 在 `init` 函数中,我们将哈希表中的每个节点的 `key` 成员初始化为 `EMPTY`,表示该节点为空。 在 `hash` 函数中,我们使用了一种简单的哈希函数,将字符串转换为整数并取模得到哈希值。 在 `find` 函数中,我们使用线性探测的方法解决哈希冲突,如果当前节点的 `key` 成员不为 `EMPTY` 且节点中的电话号码与要查找的电话号码不同,则继续搜索下一个节点,直到找到一个空节点或者关键字与要查找的电话号码相同的节点为止。 在 `insert` 函数中,我们通过调用 `find` 函数找到一个空节点或者与要插入的记录关键字相同的节点,并将该节点的 `data` 和 `key` 成员更新为要插入的记录数据和关键字。 在 `search_by_phone` 函数中,我们通过调用 `find` 函数找到与给定电话号码相同的节点,并返回该节点中的记录数据。 在 `search_by_name` 函数中,我们遍历哈希表中的所有节点,找到用户名与给定名字相同的节点,并返回该节点中的记录数据。 最后,在 `main` 函数中,我们首先从键盘输入每个记录的电话号码、用户名和地址,并将其插入到电话号码和用户名两个哈希表中。然后,我们分别通过调用 `search_by_phone` 和 `search_by_name` 函数来查找给定电话号码和用户名对应的记录,并输出该记录的电话号码、用户名和地址。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值