散列查找(散列表创建及平方探测)

编译处理时,涉及变量及属性的管理 :插入(新变量的定义),查找(变量的引用)。

顺序查找  O(N)    二分查找 O(logN)    二叉树查找O(H)     平衡二叉树 O(logN)

如何快速查找?

查找的本质:已知对象找位置

有序的安排对象-》 全序:顺序查找  半序:二叉树

直接算出位置-》 散列查找

散列查找:1.计算位置。2.解决冲突。

一、计算位置 构造散列函数。  要求:计算简单;地址分布均匀。

数字关键词:1 直接定值。2 除留余数 h(key)= key mod p,p<tablesize且p为素数。3 数字分析法。 4 折叠法。 5平方取中法。

字符关键字:1 ASII码加和法    2 前3个字符移位法。3 移位法。

 

二、处理冲突

1. 开放地址法。(换个位置)

2.链地址法。(同一位置的冲突对象放在一起)

开放地址法

一旦发生冲突,就按照某种规则起找另一空地址。

若 发生了第i次冲突,试探性的将地址加di

线性探测:di=i    容易产生聚集现象

平方探测:di=+-i*i    有空间,但跳来跳去不一定能找到。  有定理显示,如果散列表长度是某个4k+3形式的素数时,平方探测就可以探查到整个散列空间。

双散列:di=i*h2(key)      对任意key,h2(key)!=0  h2(key )=p-(key mod p)

再散列:把散列表扩大,散列表扩大时,需要重新计算。

 

 

代码

散列表的创建:

 1 #define MAXTABLESIZE 100000 /* 允许开辟的最大散列表长度 */
 2 typedef int Index;
 3 typedef Index Position;
 4 typedef enum {    Legitimate, Empty, Deleted}EntryType;
 5 
 6 typedef struct HashEntry   cell;// 散列表单元定义
 7 struct HashEntry
 8 {
 9     ElementType Data;   //散列表单元中的数据
10     EntryType Info;  // 散列表单元的信息
11 };
12 typedef struct Tb1Node *HashTable;//散列表定义
13 struct Tb1Node       
14 {
15     int TableSize;  //散列表大小
16     cell *cells; //散列表数组,数组是散列表单元的集合
17 };
18 int NextPrime(int X)
19 {
20     int i,P;
21     P = (X%2==0) ?  X+1:X+2;  //PC从x下一个数奇数开始
22     while(P< MAXTABLESIZE)   //
23     {
24         for(i=(int) (sqrt(X));i<2;i--)//依次判断从根号x到2中是否有可以整除的
25             if(P%i==0) break; //说明不是素数,跳出for,
26             if(i==2)break;   //判断是不是全都除了一遍,如果全都除了一遍,都不整除,说明是素数,跳出while
27             else  P=P+2;    //说明不是素数,继续从下一个奇数p+2继续查找。
28     }
29     return P;
30 }
31 HashTable HashTableCreate(int TableSize)
32 {
33     int i;
34     HashTable h;
35     h =(HashTable)malloc(sizeof(  HashTable));  //申请散列表空间
36     h->TableSize=NextPrime(TableSize);//散列表的大小是比给定的tablesize大的素数
37     h->cells = (cell*)malloc(h->TableSize* sizeof( cell));//散列表中散列单元的 的数组申请空间
38     for(i=0;i<h->TableSize;i++)  //将散列表中的数组中的信息赋值
39         h->cells[i].Info=Empty;
40     return h;
41 }

错误分析:

1.一定要检查函数的返回值!!!!不要漏掉29行

 

平方探测法:

 1 Position Find(ElementType key,HashTable h)
 2 {
 3     Position NewPositon ,CurrentPosition;
 4     int Count=0;
 5     NewPositon=CurrentPosition=Hash(key,h->TableSize);
 6     while(h->cells[NewPositon].Info!=Empty&&h->cells[NewPositon].Data!=key)
 7     //当新位置的散列单元不是空而且散列单元数据不等于key 寻找下一位置                                                           
 8     {
 9         if(++Count%2)//判断计数器是奇数,di+i平方
10         {
11             NewPositon =CurrentPosition +(Count+1)*(Count+1)/4;
12             while(NewPositon>=h->TableSize)//新位置不能大于TableSize
13                 NewPositon=NewPositon%h->TableSize;
14         }
15         else//判断计数器是偶数,di-i平方
16         {
17                NewPositon =CurrentPosition -Count*Count/4;
18             while(NewPositon<0)//新位置不能小于于TableSize
19                 NewPositon=NewPositon+h->TableSize;
20         }
21 
22     }
23     return NewPositon;
24 }
25 bool Insert(HashTable h,ElementType key)
26 {
27     Position p;
28     p=Find(key,h);
29     if(h->cells[p].Info!=Legitimate)
30     {
31         h->cells[p].Info=Legitimate;
32         h->cells[p].Data=key;
33         return true;
34     }
35     else
36     {
37         printf("键值已经存在\n");
38         return false;
39     }
40 
41 }

 

posted @ 2016-09-14 17:28  张乐乐章  阅读(575)  评论(0编辑  收藏