zoukankan      html  css  js  c++  java
  • 散列查找(散列表创建及平方探测)

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

    顺序查找  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("键值已经存在
    ");
    38         return false;
    39     }
    40 
    41 }
  • 相关阅读:
    深入理解 ProtoBuf 原理与工程实践(概述)
    高性能缓存 Caffeine 原理及实战
    Java 多线程上下文传递在复杂场景下的实践
    SpringBoot 2.0 中 HikariCP 数据库连接池原理解析
    MySQL 5.6.35 索引优化导致的死锁案例解析
    gitlab安装升级(大版本跨度9.4.5----13.2.1)
    mysql 查看表的索引
    python安装mysql库 ,MySQL-python
    Alpine包管理工具apk使用介绍
    docker容器添加hosts
  • 原文地址:https://www.cnblogs.com/zle1992/p/5872970.html
Copyright © 2011-2022 走看看