数据结构--散列(分离链接法解决冲突)

Posted waitforyoull

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数据结构--散列(分离链接法解决冲突)相关的知识,希望对你有一定的参考价值。

     散列方法的主要思想是根据结点的关键码值来确定其存储地址:以关键码值K为自变量,通过一定的函数关系h(K)(称为散列函数),计算出对应的函数值来,把这个值解释为结点的存储地址,将结点存入到此存储单元中。检索时,用同样的方法计算地址,然后到相应的

单元里去取要找的结点。通过散列方法可以对结点进行快速检索。散列(hash,也称“哈希”)是一种重要的存储方式,也是一种常见的检索方法。

 

    因此,散列函数更像是一种映射,散列函数的选择有很多种,下面以散列函数为关键值对10取余为例,说明散列的插入关键字,删除关键字为例说明。

 

    代码如下:

#include<iostream>
using namespace std;

struct ListNode;
typedef struct ListNode *Position;
struct Hash_table;
typedef Hash_table *Hashtab;
typedef Position List;

#define Min_table_size 10

struct ListNode
{
   int Emelent;
   Position Next;
};

struct Hash_table
{
   int Table_size;
   List *Thelist;
};

//////////////相关函数声明//////////////////////
Hashtab Inittable (int Table_size);     //初始化一个散列
Position Find (int x,Hashtab H);      //查找元素x,返回对应的位置
int Hash (int x,int Table_size);  //散列函数
void Insert (int Key, Hashtab H);   //在散列中插入元素Key
void Delete (int Key, Hashtab H);   //在散列中删除元素Key



///////////////相关函数定义////////////////////
Hashtab Inittable (int table_size)
{
	Hashtab H;
	if(table_size < Min_table_size)
	{
	    cout << "Table size is too small" << endl;
		return NULL;
	}

	H = (Hashtab)malloc(sizeof(Hash_table));
	if(H == NULL)  cout << "out of space" << endl;
	H->Table_size = table_size;
	H->Thelist  = (List*)malloc(sizeof(Position) * H->Table_size);
	if(H->Thelist == NULL) cout << "out of space" << endl;
	for(int i = 0; i != H->Table_size; ++i)
	{
	   H->Thelist[i] = (Position)malloc(sizeof(ListNode));
	   if(H->Thelist[i] == NULL) cout << "out of space" << endl;
	   else
	   {
	      H->Thelist[i]->Next = NULL;
		  H->Thelist[i]->Emelent = i;
	   }
		   
	}
	return H;
}

int Hash (int x)   //对10取余数
{
   return x % 10;
}

Position Find (int x,Hashtab H)
{
  Position P;
  List L;

  L = H->Thelist[Hash(x)];  //指向含有那个元素的表头
  P = L->Next;
  while(P != NULL && P->Emelent != x)
	  P = P->Next;
  return P;
}

void Insert (int Key, Hashtab H)
{
   Position Pos, Newcell;
   List L;
   Pos = Find(Key, H);  //先找找看,有没有Key,有就算了
   if(Pos == NULL )
   {
      Newcell = (Position)malloc(sizeof(ListNode));
	  if(Newcell == NULL)  cout << "out of space" << endl;
	  else    //插入到槽后面的第一个位置
	  {
	     L = H->Thelist[Hash(Key)];
		 Newcell->Next = L->Next ;
		 Newcell->Emelent = Key;
		 L->Next = Newcell;
	  }
   }
}

void Delete (int Key, Hashtab H)
{
   Position p,Tmpcell;
   List L;
   p = Find(Key,H);
   if(p == NULL)
	   cout << "not find the " << Key << endl;
   else
   {
      L = H->Thelist[Hash(Key)];
	  p = L ;
	  while(p->Next != NULL && p->Next->Emelent != Key)   //寻找Key的前驱节点
	  {
	     p = p->Next;
	  }
	  //
	  Tmpcell = p->Next;
	  p->Next = Tmpcell->Next;
	  free(Tmpcell);
   }

}
int main ()
{
  Hashtab H = Inittable (11);
  Insert (1, H);
  Insert (4, H);
  Insert (9, H);
  Insert (16, H);
  Insert (25, H);
   Insert (19, H);
   Insert (29, H);
   Delete(19,H);
 
  cout << H->Thelist[9]->Next->Next->Emelent << endl;
   return 0;
}

  因为关键字和散列值不是一一对应的,这也正是散列函数的意义所在,所有就会产生冲突,上述代码解决冲突的办法为分离链接法。

 

      夜深了,,,

     

     她的背影犹如白色的影子。

     

     她一次都没有回头。

以上是关于数据结构--散列(分离链接法解决冲突)的主要内容,如果未能解决你的问题,请参考以下文章

解决hash冲突之分离链接法

数据结构—— 散列查找:冲突处理方法

散列——排解冲突 开放定址法(上)

数据结构--开放定址法解决散列冲突时几种探测法的比较

散列表的分离连接法

Java解决Hash(散列)冲突的四种方法--开放地址法(线性探测,二次探测,伪随机探测)链地址法再哈希建立公共溢出区