数据结构之散列

   删除,插入,查找是对数据的最基本且最常用的操作,这几种操作的效率往往极大的影响着我们的程序的效率,当然,有很多数据结构都对这些操作提供了基本的支持,不过效率却大不相同,如向量表的查找效率是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


当然,要做好散列远远不只如此,还有很多待发展的东西,如寻找更好的散列函数,还有寻找更好的办法来避免冲突,比如利用探测的手段,如线性,平方探测等等!不过我就不展开说下去了!

没有更多推荐了,返回首页