哈希表简单实现

来源:互联网 发布:win10禁用软件联网 编辑:程序博客网 时间:2024/06/12 09:13

哈希表的简单实现,使用分离连接法处理散列“冲突”(即多个key映射到相同表地址)

#include<stdio.h>#include<stdlib.h>#define HASH_LEN 10 //表长struct hash_node{hash_node * next;int key;int value;};//取留数法static int hash(int key){return key % HASH_LEN;}//链表法处理冲突static void collision(hash_node * vec[], int hash_addr, hash_node * h){if (vec[hash_addr] == NULL)vec[hash_addr] = h;else{h->next = vec[hash_addr];vec[hash_addr] = h;}}static void ord_num_print(int i){if (i == 1)printf("the 1st element: ");else if (i == 2)printf("the 2nd element: ");else if (i == 3)printf("the 3rd element: ");elseprintf("the %dth element: ", i);}static void print_table(hash_node * vec[]){hash_node * tmp;for (int i = 0; i < HASH_LEN; i++){if (vec[i] == NULL){ord_num_print(i + 1);printf("NULL\n");}else{ord_num_print(i + 1);tmp = vec[i];while (tmp != NULL){printf("%d  ", tmp->key);tmp = tmp->next;}printf("\n");}}}static void create_table(hash_node * vec[], int keys[], int num){hash_node * tmp;int hash_addr;for (int i = 0; i < num; i++){tmp = (hash_node *)malloc(sizeof(hash_node));tmp->key = keys[i];tmp->next = NULL;hash_addr = hash(keys[i]);collision(vec, hash_addr, tmp);}}void insert_element(hash_node * vec[], int key){hash_node * new_node;new_node = (hash_node*)malloc(sizeof(hash_node));new_node->next = NULL;new_node->key = key;int hash_addr;hash_addr = hash(key);collision(vec, hash_addr, new_node);}bool delete_element(hash_node * vec[], int key){int hash_addr = hash(key);if (vec[hash_addr] == NULL){printf("no such key!\n");return false;}else{hash_node * tmp = vec[hash_addr];hash_node * last = NULL;bool first = true;while (tmp->key != key){if (tmp->next == NULL){printf("no such key!\n");return false;}last = tmp;tmp = tmp->next;first = false;}if (first)vec[hash_addr] = tmp->next;elselast->next = tmp->next;free(tmp);}}int main(){hash_node * vec[HASH_LEN];for (int i = 0; i < HASH_LEN; i++){vec[i] = NULL;}int keys[HASH_LEN] = { 19, 14, 23, 68, 20, 84, 27, 55, 11, 10 };printf("first time\n");create_table(vec, keys, HASH_LEN);print_table(vec);printf("second time\n");insert_element(vec, 5);print_table(vec);printf("third time\n");delete_element(vec, 5);print_table(vec);getchar();return 0;}


如果不使用链表,另一个解决冲突的方法是当冲突发生时,就散列到表的另一单元。根据如下公式计算出下一个散列地址。

 i=0,1,2...依次寻找

根据f()不同可分为:

(1)线性探测

f(i)=i

(2)平方探测

f(i)=i^2


/*功能:哈希表,平方探测处理冲突描述:表有一半以上空时,才能保证元素插入;  若表中元素大于一半时,要再散列(rehash),  将表大小扩大一倍,遍历原表元素,使之  散列到新表中。*/#pragma once#include<vector>template<typename HashObj>class HashTable{public:HashTable(int size = 10);~HashTable();bool Contains(const HashObj & x);bool Insert(const HashObj & x);bool Delete(const HashObj & x);int TableSize() { return _Lists.size(); }private:enum EntryType{EMPTY, ACTIVE};struct HashEntry {HashObj elem;EntryType state;//表中元素状态HashEntry(const HashObj & e = HashObj(), EntryType s = EMPTY) : elem(e), state(s){}};std::vector<HashEntry> _Lists;int currSize;int myHash(const HashObj & x);bool isActive(int curPos) { return _Lists[curPos].state == ACTIVE; }int findPos(const HashObj & x);void rehash();};template<typename HashObj>HashTable<HashObj>::HashTable(int size){_Lists = std::vector<HashEntry>(size);currSize = 0;for (int i = 0; i < size; i++){_Lists[i].state = EMPTY;}}template<typename HashObj>HashTable<HashObj>::~HashTable(){}template<typename HashObj>int HashTable<HashObj>::myHash(const HashObj & x){int TableSize = _Lists.size();int pos;pos = x % TableSize;if (pos < 0)pos += TableSize;return pos;}template<typename HashObj>int HashTable<HashObj>::findPos(const HashObj & x){int TableSize = _Lists.size();int offset = 1;int curPos = myHash(x);while (_Lists[curPos].state != EMPTY && _Lists[curPos].elem != x){curPos += offset;offset += 2;//f(i)=i^2也可写成:f(i)=f(i-1)+2i-1if (curPos > TableSize)curPos -= TableSize;}return curPos;}template<typename HashObj>bool HashTable<HashObj>::Contains(const HashObj & x){return isActive(findPos(x));}template<typename HashObj>bool HashTable<HashObj>::Insert(const HashObj & x){int TableSize = _Lists.size();int curPos = findPos(x);if (isActive(curPos))return false;_Lists[curPos] = HashEntry(x, ACTIVE);if (++currSize > TableSize / 2)rehash();return true;}template<typename HashObj>bool HashTable<HashObj>::Delete(const HashObj & x){int curPos = findPos(x);if (!isActive(curPos))return false;_Lists[curPos].state = EMPTY;currSize--;return true;}template<typename HashObj>void HashTable<HashObj>::rehash(){std::vector<HashEntry> old_Lists = _Lists;_Lists.resize(old_Lists.size() * 2);for (int i = 0; i < old_Lists.size(); i++){EntryType state = old_Lists[i].state;HashObj elem = old_Lists[i].elem;if (state == ACTIVE){Insert(elem);}}}


原创粉丝点击