ExcelHome技术论坛

 找回密码
 免费注册

QQ登录

只需一步,快速开始

快捷登录

搜索
EH技术汇-专业的职场技能充电站 妙哉!函数段子手趣味讲函数 Excel服务器-会Excel,做管理系统 效率神器,一键搞定繁琐工作
HR薪酬管理数字化实战 Excel 2021函数公式学习大典 Excel数据透视表实战秘技 打造核心竞争力的职场宝典
让更多数据处理,一键完成 数据工作者的案头书 免费直播课集锦 ExcelHome出品 - VBA代码宝免费下载
用ChatGPT与VBA一键搞定Excel WPS表格从入门到精通 Excel VBA经典代码实践指南
楼主: 三坛老窖

[分享] 基于哈希查找的老窖字典

  [复制链接]

TA的精华主题

TA的得分主题

发表于 2024-11-8 16:24 | 显示全部楼层
谢谢分享。。

TA的精华主题

TA的得分主题

发表于 2024-11-11 09:40 | 显示全部楼层
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册
天地一相 发表于 2024-11-8 09:49
请教,测试了老窖的,速度真的好快。测试你的,因为我的64位,就调整了声明部分,红字消失后测试,报错53 ...

VBHelper.dll是我用C++写的,里面主要是封装了一个计算hash的算法(还有排序算法以及一些回调功能函数等)。hash算法用的开源的,并与针对VB6的不同数据类型简单优化了下,可惜我用不到64位,目前DLL只支持32位,下面附上了hash的C++代码。其他用到VBHelper.dll的地方我都注释掉了,只把hash函数替换就可以不用VBHelper.dll了

我把VBHelper.dll和最新的字典代码也传上来吧。原来的有个bug,数据量大了才能看出来,也增加了一些功能函数,最实用的应该是ItemArrayView,字典Item是数组时,可以直接修改这个数组的元素,而不用创建一新的数组替换。
其实这个封装的HASH函数提升也不是很大,我记得数据量小时系统自带的字典快些。可以尝试调用C#中的字典之类的,估计会好用些。

  1. //BKDRHash
  2. /// @brief BKDR Hash Function  
  3. /// @detail 本 算法由于在Brian Kernighan与Dennis Ritchie的《The C Programming Language》一书被展示而得 名,是一种简单快捷的hash算法,也是Java目前采用的字符串的Hash算法(累乘因子为31)。
  4. inline
  5. size_t  __stdcall _HashCaseSensitive(wchar_t* str, ULONG iLen) {
  6.         size_t hash = 0;
  7.         while (iLen--) {
  8.                 hash = hash * 131 + (*str++);   // 也可以乘以31、131、1313、13131、131313..  
  9.                 // 有人说将乘法分解为位运算及加减法可以提高效率,如将上式表达为:hash = hash << 7 + hash << 1 + hash + ch;  
  10.                 // 但其实在Intel平台上,CPU内部对二者的处理效率都是差不多的,  
  11.                 // 我分别进行了100亿次的上述两种运算,发现二者时间差距基本为0(如果是Debug版,分解成位运算后的耗时还要高1/3);  
  12.                 // 在ARM这类RISC系统上没有测试过,由于ARM内部使用Booth's Algorithm来模拟32位整数乘法运算,它的效率与乘数有关:  
  13.                 // 当乘数8-31位都为1或0时,需要1个时钟周期  
  14.                 // 当乘数16-31位都为1或0时,需要2个时钟周期  
  15.                 // 当乘数24-31位都为1或0时,需要3个时钟周期  
  16.                 // 否则,需要4个时钟周期  
  17.                 // 因此,虽然我没有实际测试,但是我依然认为二者效率上差别不大
  18.                 //str += 2;
  19.         }
  20.         return  hash;
  21. }

  22. size_t __stdcall HashCaseSensitive(void* p) {
  23.         VARTYPE vt = ((VARIANT*)(p))->vt;

  24.         //VT_BYREF
  25.         if ((vt & VT_BYREF) == VT_BYREF) {
  26.                 p = ((VARIANT*)(p))->byref;
  27.                 vt &= ~VT_BYREF;
  28.         }
  29.         else
  30.                 p = &((VARIANT*)(p))->byref;

  31.         //VARIANT
  32.         if ((vt & VT_VARIANT) == VT_VARIANT) {
  33.                 vt &= ~VT_VARIANT;
  34.         }

  35.         if (vt == VT_BSTR) {
  36.                 {
  37.                         return _HashCaseSensitive((wchar_t*)(*(long*)(p)), (*((long*)(*(long*)(p)) - 1)) >> 1);
  38.                 }
  39.         }

  40.         //2 个字节 Boolean  Integer
  41.         if (vt == VT_I2 || vt == VT_BOOL) return *reinterpret_cast<UINT16*>(p);

  42.         //4 个字节 Long Single
  43.         if (vt == VT_I4 || vt == VT_R4) return *reinterpret_cast<size_t*>(p);

  44.         //8 个字节 Double LongLong Date Currency
  45.         if (vt == VT_R8 || vt == VT_DATE || vt == VT_CY || vt == VT_I8) return _HashCaseSensitive((wchar_t*)p, 4);

  46.         //16 个字节 Decimal
  47.         if (vt == VT_DECIMAL) return _HashCaseSensitive((wchar_t*)p, 8);

  48.         //1 个字节 Byte
  49.         if (vt == VT_UI1) return *reinterpret_cast<unsigned char*>(p);

  50.         return 0;
  51. }
  52. inline
  53. size_t  __stdcall _HashCaseInsensitive(wchar_t* str, ULONG iLen) {
  54.         size_t hash = 0;
  55.         while (iLen--) {
  56.                 hash = hash * 131 + ((*str > L'Z' || *str < L'A') ? (*str++) : ((*str++) | 0x20));
  57.         }
  58.         return hash;
  59. }
  60. size_t __stdcall HashCaseInsensitive(void* p) {
  61.         VARTYPE vt = ((VARIANT*)(p))->vt;

  62.         //vbNullString/vbEmpty返回0
  63.         if (((VARIANT*)(p))->byref == nullptr) return 0;

  64.         //VT_BYREF
  65.         if ((vt & VT_BYREF) == VT_BYREF) {
  66.                 p = ((VARIANT*)(p))->byref;
  67.                 vt &= ~VT_BYREF;
  68.         }
  69.         else
  70.                 p = &((VARIANT*)(p))->byref;

  71.         //VARIANT
  72.         if ((vt & VT_VARIANT) == VT_VARIANT) vt &= ~VT_VARIANT;

  73.         if (vt == VT_BSTR) return _HashCaseInsensitive((wchar_t*)(*(long*)(p)), (*((long*)(*(long*)(p)) - 1)) >> 1);

  74.         //2 个字节 Boolean  Integer
  75.         if (vt == VT_I2 || vt == VT_BOOL) return *reinterpret_cast<UINT16*>(p);

  76.         //4 个字节 Long Single
  77.         if (vt == VT_I4 || vt == VT_R4) return *reinterpret_cast<size_t*>(p);

  78.         //8 个字节 Double LongLong Date Currency
  79.         if (vt == VT_R8 || vt == VT_DATE || vt == VT_CY || vt == VT_I8) return _HashCaseSensitive((wchar_t*)p, 4);

  80.         //16 个字节 Decimal
  81.         if (vt == VT_DECIMAL) return _HashCaseSensitive((wchar_t*)p, 8);

  82.         //1 个字节 Byte
  83.         if (vt == VT_UI1) return *reinterpret_cast<unsigned char*>(p);

  84.         return 0;
  85. }
复制代码



VBHelper.zip (92.63 KB, 下载次数: 1) clsDictionary.rar (13.52 KB, 下载次数: 1)



您需要登录后才可以回帖 登录 | 免费注册

本版积分规则

手机版|关于我们|联系我们|ExcelHome

GMT+8, 2024-11-21 19:35 , Processed in 0.031621 second(s), 9 queries , Gzip On, MemCache On.

Powered by Discuz! X3.4

© 1999-2023 Wooffice Inc.

沪公网安备 31011702000001号 沪ICP备11019229号-2

本论坛言论纯属发表者个人意见,任何违反国家相关法律的言论,本站将协助国家相关部门追究发言者责任!     本站特聘法律顾问:李志群律师

快速回复 返回顶部 返回列表