`

哈希查找

 
阅读更多

大家可否知道,其实查找中有一种O(1)的查找,即所谓的秒杀。

第三:哈希查找:
     对的,他就是哈希查找,说到哈希,大家肯定要提到哈希函数,呵呵,这东西已经在我们脑子里面形成固有思维了。大家一定要知道“哈希“中的对应关系。

     比如说: ”5“是一个要保存的数,然后我丢给哈希函数,哈希函数给我返回一个”2",那么此时的”5“和“2”就建立一种对应关系,这种关系就是所谓的“哈希关系”,在实际应用中也就形成了”2“是key,”5“是value。

    那么有的朋友就会问如何做哈希,首先做哈希必须要遵守两点原则:
          ①:  key尽可能的分散,也就是我丢一个“6”和“5”给你,你都返回一个“2”,那么这样的哈希函数不尽完美。
          ②: 哈希函数尽可能的简单,也就是说丢一个“6”给你,你哈希函数要搞1小时才能给我,这样也是不好的。

其实常用的做哈希的手法有“五种”:

第一种:”直接定址法“。
很容易理解,key=Value+C; 这个“C"是常量。Value+C其实就是一个简单的哈希函数。

第二种:“除法取余法”。
很容易理解, key=value%C;解释同上。

第三种:“数字分析法”。
  这种蛮有意思,比如有一组value1=112233,value2=112633,value3=119033,
针对这样的数我们分析数中间两个数比较波动,其他数不变。那么我们取key的值就可以是
   key1=22,key2=26,key3=90。

第四种:“平方取中法”。此处忽略,见名识意。

第五种:“折叠法”。
   这种蛮有意思,比如value=135790,要求key是2位数的散列值。那么我们将value变为13+57+90=160,   然后去掉高位“1”,此时key=60,哈哈,这就是他们的哈希关系,这样做的目的就是key与每一位value都相关,来做到“散列地址”尽可能分散的 目地。

    正所谓常在河边走,哪有不湿鞋。哈希也一样,你哈希函数设计的再好,搞不好哪一次就撞楼了,那么抛给我们的问题就是如果来解决“散列地址“的冲突。

其实解决冲突常用的手法也就2种:

第一种: “开放地址法“。
所谓”开放地址“,其实就是数组中未使用的地址。也就是说,在发生冲突的地方,后到的那个元素(可采用两种方式
:①线性探测,②函数探测)向数组后寻找"开放地址“然后把自己插进入。

第二种:”链接法“。
  这个大家暂时不懂也没关系,我就先介绍一下原理,就是在每个元素上放一个”指针域“,在发生冲突的地方,后到的那个元素将自己的数据域抛给冲突中的元素,此时冲突的地方就形成了一个链表。

  上面啰嗦了那么多,也就是想让大家在”设计哈希“和”解决冲突“这两个方面提一点参考和手段。

那么下面就上代码了,
     设计函数采用:”除法取余法“。
     冲突方面采用:”开放地址线性探测法"。

Java代码  收藏代码
  1. import  java.util.List;  
  2. import  java.util.Arrays;  
  3. import  java.util.Scanner;  
  4. public   class  HashProgram    
  5.      {    
  6.          //“除法取余法”      
  7.          static   int  hashLength =  13 ;    
  8.      
  9.          //原数据    
  10.           static  Integer a[]={  13 29 27 28 26 30 38  };   
  11.           static  List<Integer> list=Arrays.asList(a);    
  12.    
  13.          //c#中可以这样啊!jdk1.7也不能啊   
  14.         // static List<int> list = new List<int>() { 13, 29, 27, 28, 26, 30, 38 };     
  15.        
  16.          //哈希表长度      
  17.          static   int [] hash =  new   int [hashLength];    
  18.      
  19.        public   static   void  main(String[] args)    
  20.          {    
  21.              Scanner sca=new  Scanner(System.in);  
  22.              //创建hash      
  23.              for  ( int  i =  0 ; i < list.size(); i++)    
  24.              {    
  25.                  InsertHash(hash, hashLength, list.get(i));    
  26.              }    
  27.      
  28.              System.out.println("Hash表中的数据:" );  
  29.              for ( int  i:hash)  
  30.                System.out.print(i+"," );    
  31.      
  32.              while  ( true )    
  33.              {    
  34.                  System.out.printf("\n请输入要查找数字:" );    
  35.                  int  result = sca.nextInt();    
  36.                  int   index = SearchHash(hash, hashLength, result);    
  37.      
  38.                  if  (index != - 1 )    
  39.                    System.out.println("数字"  + result +  "在索引的位置是:"  + index);    
  40.                  else     
  41.                    System.out.println("呜呜,"  + result +  " 在hash中没有找到!" );    
  42.      
  43.              }    
  44.          }    
  45.      
  46.      
  47.  // Hash表检索数据      
  48.   
  49.      static   int  SearchHash( int [] hash,  int  hashLength,  int  key)    
  50.          {    
  51.              //哈希函数      
  52.              int  hashAddress = key % hashLength;    
  53.      
  54.              //指定hashAdrress对应值存在但不是关键值,则用开放寻址法解决      
  55.              while  (hash[hashAddress] !=  0  && hash[hashAddress] != key)    
  56.              {    
  57.                  hashAddress = (++hashAddress) % hashLength;    
  58.              }    
  59.      
  60.              //查找到了开放单元,表示查找失败      
  61.              if  (hash[hashAddress] ==  0 )    
  62.                  return  - 1 ;    
  63.              return  hashAddress;    
  64.      
  65.          }    
  66.      
  67.             
  68.  //数据插入Hash表      
  69.    
  70.          static   void  InsertHash( int [] hash,  int  hashLength,  int  data)    
  71.          {    
  72.              //哈希函数      
  73.              int  hashAddress = data %  13 ;    
  74.               //如果key存在,则说明已经被别人占用,此时必须解决冲突      
  75.              while  (hash[hashAddress] !=  0 )    
  76.              {    
  77.                  //用开放寻址法找到      
  78.                  hashAddress = (++hashAddress) % hashLength;    
  79.              }    
  80.      
  81.              //将data存入字典中      
  82.              hash[hashAddress] = data;    
  83.          }    
  84.         
  85.  }    



运行:
D:\java>java   HashProgram
Hash表中的数据:
13,27,28,29,26,30,0,0,0,0,0,0,38
请输入要查找数字:38
数字38在索引的位置是:12

请输入要查找数字:33
呜呜,33 在hash中没有找到!

请输入要查找数字:27
数字27在索引的位置是:1

请输入要查找数字:

第四:索引查找
  简称分级查找.例如汉字查找.对象是计算机为索引查找而建立的主表和各级索引表,主表只有一个,索引表的级数和数量不受限制,根据具体的需要确定.索引存储结构是数据组织的一项很重要的存储技术,在数据库领域中有广泛的应用.

  基本思想:首先把一个集合或线性表(主表)按照一定的函数关系或条件划分成若干个逻辑上的子表,为每个子表分别建立一个索引项,由所有这些索引项构成主表的一个索引表,然后,可采用顺序或是链接的方式来存储索引表和每个子表.

索引表包含三个域:
(1)索引值域,用来存储对应子表的索引值,相当于记录的关键字,在索引表中由此索引值来唯一标识一个索引项.

(2)表的开始位置域,用来存储对应子表的第一个元素的存储位置,从此位置出发可以依次访问到子表中的所有元素.

(3)子表的长度域:用来存储对应子表的元素个数.

  索引查找算法:是在索引表和主表上进行的查找.过程是:首先根据给定的索引值K1,在索引表上查找出索引值等于K1的索引项,以确定对应子表 在主表的开始位置和长度.然后再根据给定的关键字K2,在对应的子表中查找出关键字等于K2的元素.对索引表或子表的查找时,若表是顺序存储的有序表,则 可进行顺序查找,也可以进行二分查找.否则只能进行顺序查找.

Java代码  收藏代码
  1. import  java.util.Arrays;  
  2. public   class  IndexSearch {    
  3.     
  4.     // 主表     
  5.     static   int [] students = {  101 102 103 104 105 0 0 0 0 0 201 202 ,    
  6.             203 204 0 0 0 0 0 0 301 302 303 0 0 0 0 0 0 0  };    
  7.     // 索引表     
  8.     static  IndexItem[] indexItem = {  new  IndexItem( 1 0 5 ),    
  9.             new  IndexItem( 2 10 4 ),  new  IndexItem( 3 20 3 ), };    
  10.     
  11.     // 查找数据     
  12.     public   static   int  indexSearch( int  key) {    
  13.         IndexItem item = null ;    
  14.     
  15.         // 建立索引规则     
  16.         int  index = key /  100 ;    
  17.     
  18.         // 首先去索引找     
  19.         for  ( int  i =  0 ; i < indexItem.length; i++) {    
  20.             if  (indexItem[i].index == index) {    
  21.                 item = indexItem[i];   
  22.                 break ;    
  23.             }    
  24.         }    
  25.     
  26.         // 如果item为null,则说明在索引中查找失败     
  27.         if  (item ==  null )    
  28.             return  - 1 ;    
  29.     
  30.         for  ( int  i = item.start; i < item.start + item.length; i++) {    
  31.             if  (students[i] == key) {    
  32.                 return  i;    
  33.             }    
  34.         }    
  35.         return  - 1 ;    
  36.     }    
  37.     
  38.     // / 插入数据     
  39.     public   static   int  insert( int  key) {    
  40.         IndexItem item = null ;    
  41.         // 建立索引规则     
  42.         int  index = key /  100 ;    
  43.         int  i =  0 ;    
  44.         for  (i =  0 ; i < indexItem.length; i++) {    
  45.             // 获取到了索引     
  46.             if  (indexItem[i].index == index) {    
  47.                 item = indexItem[i];  
  48.                 break ;    
  49.             }    
  50.         }    
  51.         if  (item ==  null )    
  52.             return  - 1 ;    
  53.         // 更新主表     
  54.         students[item.start + item.length] = key;    
  55.         // 更新索引表     
  56.         indexItem[i].length++;    
  57.         return   1 ;    
  58.     }    
  59.     
  60.     public   static   void  main(String[] args) {    
  61.         int  value =  205 ;    
  62.         // 将205插入集合中,过索引     
  63.         int  index = insert(value);    
  64.         insert(308 );    
  65.     
  66.         // 如果插入成功,获取205元素所在的位置     
  67.         if  (index ==  1 ) {    
  68.             System.out.println("\n插入后数据:"  + Arrays.toString(students));    
  69.             System.out.println("\n数据元素:205在数组中的位置为 "  + indexSearch( 205 ) +  "位" );    
  70.         }    
  71.     
  72.     }    
  73.     
  74. }    
  75.     
  76. // 索引项实体     
  77. class  IndexItem {    
  78.     // 对应主表的值     
  79.     public   int  index;    
  80.     // 主表记录区间段的开始位置     
  81.     public   int  start;    
  82.     // 主表记录区间段的长度     
  83.     public   int  length;    
  84.     
  85.     public  IndexItem() {    
  86.     }    
  87.     
  88.     public  IndexItem( int  index,  int  start,  int  length) {    
  89.         this .index = index;    
  90.         this .start = start;    
  91.         this .length = length;    
  92.     }    
  93. }    



运行:
D:\java>java   IndexSearch

插入后数据:[101, 102, 103, 104, 105, 0, 0, 0, 0, 0, 201, 202, 203, 204, 205, 0, 0, 0, 0, 0, 301, 302, 303, 308, 0, 0, 0, 0, 0, 0]

数据元素:205在数组中的位置为 14位

分享到:
评论

相关推荐

    哈希查找数据结构实验报告.pdf

    哈希查找数据结构实验报告 本实验报告的标题是 "哈希查找数据结构实验报告.pdf", 描述是 "哈希查找数据结构实验报告.pdf", 标签是 "考试"。该实验报告讲述了哈希表的造表和查找算法的实现。 第一部分:需求分析 ...

    哈希查找.cpp

    //哈希查找法 #include #include #include&lt;iomanip.h&gt; #define datawidth 5 //设置数据显示宽度 #define arraymaxnum 21 //约定数组大小,0号单元默认不用,故用户数据可以接受20个 #define defaultnum 10 //约定...

    数据结构 哈希查找

    哈希查找是数据结构中的一个重要组成部分,它提供了一种快速定位数据的方法。在这个主题中,我们将深入探讨哈希查找的概念、实现、优势以及在C语言中如何构建一个友好的用户界面来实现这一功能。 哈希查找的基本...

    利用哈希查找链地址法查找元素

    ### 哈希查找链地址法知识点解析 #### 一、引言 本文将详细介绍一个基于C语言实现的哈希表查找系统,该系统利用链地址法处理冲突,并支持基本的增删查操作。通过本篇文章,您将了解哈希表的基本原理、链地址法的...

    哈希表(散列表)和哈希查找

    总之,哈希表和哈希查找是计算机科学中重要的数据结构和算法,它们提供了一种快速访问数据的方式,广泛应用于数据库系统、编译器、缓存管理等多个领域。理解并熟练掌握哈希表的原理和实现,对于提升程序性能和解决...

    c/c++语言程序-哈希查找

    c/c++语言程序-哈希查找

    哈希查找算法的源代码c语言[文].pdf

    哈希查找算法的源代码c语言 哈希查找算法是软件网络技术中一种常用的查找算法,它通过将关键字转换为数组的索引来实现快速查找。该算法的实现需要解决两个主要问题:哈希函数的设计和冲突的处理。 哈希函数的设计 ...

    运用MFC来实现哈希查找算法

    哈希查找算法是一种高效的数据检索方法,它通过计算哈希函数将关键字映射到一个固定大小的哈希表中,以此实现快速查找。在本文中,我们将深入探讨如何利用Microsoft Foundation Classes (MFC) 来实现哈希查找算法。...

    数据结构课程设计之哈希查找设计

    在数据结构课程设计中,哈希查找是一种高效的数据组织和检索方法。哈希表是实现哈希查找的基础,它通过将关键字(key)映射到一个固定大小的数组索引来快速定位数据。在这个课程设计中,我们将使用C语言来实现这一...

    易语言万倍哈希查找

    易语言万倍哈希查找源码,万倍哈希查找,操作函数,加入,取回,删除,成员数,内部哈希,线程等待,取时间戳_易,创建进入许可证_,进入许可区_,退出许可区_,删除进入许可证_,启动线程_,销毁线程_,寻找字节集_,内存_申请,内存_...

    C语言 哈希查找算法

    C 言语 哈希查找算法 数据结构教才答案

    哈希查找C++源代码

    哈希查找 C++源代码 数据结构。 数据结构课作业。

    数据结构查找方法 哈希查找 折半查找 顺序查找

    本主题将深入探讨三种常见的查找方法:哈希查找、折半查找(又称二分查找)以及顺序查找。 首先,我们来理解哈希查找。哈希查找基于哈希表,这是一种能够快速访问数据的结构。哈希函数是哈希查找的核心,它能将输入...

    哈希查找算法

    哈希查找算法是一种在计算机科学中广泛使用的数据结构和算法技术,它主要依赖于哈希函数来实现快速的查找操作。哈希函数是将输入(通常是一个字符串或对象)映射到一个固定大小的数值(通常是一个数组的索引)的过程...

    哈希查找-表长101

    建立哈希表查找c++中32个关键字,其中哈希表长为M=101 32个关键字为auto break case char const continue default do double else enum extern float for goto if int long register return short signed sizeof ...

    易语言源码易语言万倍哈希查找源码.rar

    在这个“易语言源码易语言万倍哈希查找源码.rar”压缩包中,包含的是一个易语言编写的哈希查找算法的源代码。哈希查找是一种在数据结构中快速定位目标元素的技术,它的核心思想是通过哈希函数将键(key)转化为哈希...

    哈希表生成及哈希查找算法

    输入:待哈希数据序列 功能要求:输出哈希方法和解决冲突的方法(文字输出),输出哈希表

    数据结-构查找算法二分查找二叉顺序数哈希查找

    哈希查找利用哈希函数将关键字映射到一个固定大小的表中,以实现快速查找。理想情况下,哈希函数能够均匀分布关键字,避免冲突,这样查找只需要一次操作。当发生冲突时,可以采用开放地址法或链地址法等策略处理。...

    万倍哈希查找.rar

    《万倍哈希查找》是针对计算机编程领域中的一种高效数据查找技术的实践应用,尤其在处理大量数据时,能够显著提升查找效率。哈希查找是计算机科学中的一个重要概念,它利用哈希函数将数据映射到一个固定大小的表中,...

    C语言哈希查找-哈希查找

    C语言哈希查找_哈希查找

Global site tag (gtag.js) - Google Analytics