删除,插入,查找是对数据的最基本且最常用的操作,这几种操作的效率往往极大的影响着我们的程序的效率,当然,有很多数据结构都对这些操作提供了基本的支持,不过效率却大不相同,如向量表的查找效率是O(1),但插入与删除为O(n)的,链表相反,查找效率是O(n),但插入与删除为O(1)的,而二叉查找树对三种操作都为O(lgn)。
但却有一种数据结构很神奇,他对三种操作的效率都是O(1)的,这种结构就是散列,散列可以认为是对输入空间的一个压缩形成一个散列表!但遗憾的是要做好一个散列表我们往往要找到一个散列函数,而寻找好的散列函数往往只能称作一种艺术,很难有什么好的理论支撑。尽管如此,散列在我们的生活中的应用还是极其的广泛!
例如,我们知道,基于比较的排序最好的效率是O(nlogn)的,平常我们用的快排,堆排就是如此。但如果我们是对一定范围内的数据进行排序,例如1000以内,这是我们就用散列的思想就能达到O(n)的效率!
虽然寻找散列函数十分的困难,但直接取余是比较通用的办法,通常是对一个素数进行取余,不过还是无法避免冲突的情况,这时一般用分离链接法来解决,下面就是我写的一个利用分离链接法来实现的散列:
//hash.h
#ifndef HASH_H #define HASH_H #include<iostream> using namespace std; #include<vector> #include<list> class Hashtable { private: vector<list<int> > hs; int size; public: Hashtable(int thesize=101){ hs.resize(thesize) ;size=0;} void insert(int &x) { if(size==hs.size()) { return; } list<int> &L=hs[hash(x)]; list<int>::iterator it; for(it=L.begin();it!=L.end();it++) if(*it==x) break; if(it==L.end()) { if(L.empty()) size++; L.push_back(x); } } void remove(int &x) { list<int> &L=hs[hash(x)]; list<int>::iterator it; for(it=L.begin();it!=L.end();it++) if(*it==x) break; if(it!=L.end()) { L.erase(it); if(L.empty()) size--; } } bool contains(int &x) { list<int> &L=hs[hash(x)]; list<int>::iterator it; for(it=L.begin();it!=L.end();it++) if(*it==x) break; if(it!=L.end()) return true; return false; } int hash(int x) { int hashvalue=x%hs.size(); return hashvalue; } }; #endif
原文:http://blog.csdn.net/alop_daoyan/article/details/22506115