EPANET中的哈希文件——hash.c
/*-----------------------------------------------------------------------------
** hash.c
**
** Implementation of a simple Hash Table for string storage & retrieval
**
** Written by L. Rossman
** Last Updated on 6/19/03
**
** The hash table data structure (HTable) is defined in "hash.h".
** Interface Functions:
** HTcreate() - creates a hash table
** HTinsert() - inserts a string & its index value into a hash table
** HTfind() - retrieves the index value of a string from a table
** HTfree() - frees a hash table
**
*********************************************************************
** NOTE: This is a modified version of the original HASH.C module.
*********************************************************************
*/
/*-----------------------------------------------------------------------------
** 关于哈希表这一数据结构的介绍,可以参考博文:
** http://www.cnblogs.com/KingOfFreedom/archive/2012/12/11/2812505.html
**
** 这里采用的哈希函数是Fletcher's checksum to compute 2-byte hash of string
** 这里的哈希冲突解决方法是采用上述博文中的第3种方法“链地址法”
** 将所有关键字为同义词的记录存储在同一线性链表中。该线性链表的定义在hash.h中的HTentry
*/
#include <malloc.h>
#include <string.h>
#include "hash.h"
/*
**--------------------------------------------------------------
** 输入:"ID标识"作为哈希函数的参数
** 输出:哈希后的值
** 作用:使用了Fletcher's checksum算法的哈希函数来处理32位长的字符串以获得散列值。
**--------------------------------------------------------------
*/
/* Use Fletcher's checksum to compute 2-byte hash of string */
unsigned int hash(char *str)
{
unsigned int sum1= 0, check1;
unsigned long sum2= 0L;
while( '\0' != *str )
{
sum1 += (*str);
str++;
if ( 255 <= sum1 ) sum1 -= 255;
sum2 += sum1;
}
check1= sum2;
check1 %= 255;
check1= 255 - (sum1+check1) % 255;
sum1= 255 - (sum1+check1) % 255;
return( ( ( check1 << 8 ) | sum1 ) % HTMAXSIZE);
}
/*
**--------------------------------------------------------------
** 输入:无
** 输出:成功则返回哈希表头指针
** 作用:创建一个长度为HTMAXSIZE的哈希表,并初始化
**--------------------------------------------------------------
*/
HTtable *HTcreate()
{
int i;
HTtable *ht = (HTtable *) calloc(HTMAXSIZE, sizeof(HTtable));
if (ht != NULL) for (i=0; i<HTMAXSIZE; i++) ht[i] = NULL;/* Comment by CCR: Here Can Be Better,the Reason is:calloc在动态分配完内存后,自动初始化该内存空间为零,而malloc不初始化,里边数据是随机的垃圾数据。所以这句可以注释掉 */
return(ht);
}
/*
**--------------------------------------------------------------
** 输入:哈希表ht、"ID标识"key、Node中的索引值
** 输出:成功插入返回1,否则返回0
** 作用:将一个字符串以及索引值插入到哈希表中
**--------------------------------------------------------------
*/
int HTinsert(HTtable *ht, char *key, int data)
{
unsigned int i = hash(key);
struct HTentry *entry;
if ( i >= HTMAXSIZE )
return(0);
entry = (struct HTentry *) malloc(sizeof(struct HTentry));
if (entry == NULL) return(0);//判断内存是否分配成功
entry->key = key;
entry->data = data;
//将同一hash值的链表挂到当前对象entry后面,再将当前对象entry置于队首
entry->next = ht[i];
ht[i] = entry;
return(1);
}
/*
**--------------------------------------------------------------
** 输入:哈希表、"ID标识"
** 输出:给出指定"ID标识"在Node中的索引值,若没找到返回0
** 作用:返回指定"ID标识"在Node中的索引值
**--------------------------------------------------------------
*/
int HTfind(HTtable *ht, char *key)
{
unsigned int i = hash(key);
struct HTentry *entry;
if ( i >= HTMAXSIZE )
return(NOTFOUND);
entry = ht[i];
while (entry != NULL)
{
//哈希冲突处理:链地址法
if (strcmp(entry->key,key) == 0 ) return(entry->data);
entry = entry->next;
}
return(NOTFOUND);
}
/*
**--------------------------------------------------------------
** 输入:哈希表、"ID标识"
** 输出:寻找指定"ID标识"是否存在于哈希表中,若没找到返回NULL,找到则返回指向"ID标识"的指针
** 作用:判断指定"ID标识"是否存在于哈希表中
**--------------------------------------------------------------
*/
char *HTfindKey(HTtable *ht, char *key)
{
unsigned int i = hash(key);
struct HTentry *entry;
if ( i >= HTMAXSIZE )
return(NULL);
entry = ht[i];
while (entry != NULL)
{
if ( strcmp(entry->key,key) == 0 ) return(entry->key);
entry = entry->next;
}
return(NULL);
}
/*
**--------------------------------------------------------------
** 输入:哈希表
** 输出:
** 作用:回收哈希表的内存
**--------------------------------------------------------------
*/
void HTfree(HTtable *ht)
{
struct HTentry *entry,
*nextentry;
int i;
for (i=0; i<HTMAXSIZE; i++)
{
entry = ht[i];
while (entry != NULL)
{
nextentry = entry->next;
free(entry);
entry = nextentry;
}
}
free(ht);
}
--------------------------------------------------------
哈希表这一数据结构是用内存空间来提高时间效率的算法,理想情况下(不存在冲突)的哈希算法的时间复杂度是常数O(1)。但是实际情况是即便开辟了足够多的一连串的内存空间,如果哈希函数选取不当,还是会发生冲突。EPANET中的哈希函数的选取是使用了Fletcher's checksum算法的哈希函数来处理32位长的字符串以获得散列值,这个哈希算法的优劣本人还无法去评断。但是注意,EPANET中的冲突处理是采用链地址法,而EPANET中默认提供的哈希地址个数是HTMAXSIZE个,在hash.h中是这样定义的#define HTMAXSIZE 1999。如果我们的模型有5W个左右的节点与管段,那么这2000个地址空间,平均每个地址空间会挂有一个长度为25的线性链表。而哈希函数算法不一定这么优秀,可能某个地址空间挂了一个长度为上百甚至上千的线性链表,那么查询效率就低下了。所以,如果运行EPANET的机子有足够多的内存,比如8G以上,那么就可以试着修改hash.h中的#define HTMAXSIZE 1999。将整个1999改的大些,那么运行效率也就可以提高了。
EPANET中的哈希文件——hash.c的更多相关文章
- EPANET中读取INPUT文件的函数文件——INPUT3.C
/* ********************************************************************** INPUT3.C -- Input data par ...
- EPANET中读取INPUT文件的函数文件——INPUT1.C/INPUT2.C/INPUT3.C
首先介绍下这3个文件的关系:可以说INPUT1.C的函数粒度最大,它的函数getdata()就完成了整个INPUT文件数据的读入,该函数又调用了INPUT2.C中的部分函数,INPUT2.C文件中的函 ...
- Java集合类中的哈希总结
JAVA集合类中的哈希总结 目 录 1.哈希表 2.Hashtable.HashMap.ConcurrentHashMap.LinkedHashMap.TreeMap区别 3.Hashtable.Ha ...
- 哈希表(Hash)的应用
$hs=@() #定义数组 $hs=@{} #定义Hash表,使用哈希表的键可以直接访问对应的值,如 $hs["王五"] 或者 $hs.王五 的值为 75 $hs=@''@ #定义 ...
- Java中的哈希
Java中的哈希 前言 在开发中经常用到HashMap.HashSet等与哈希有关的数据结构,一直只知道这些哈希的数据结构不保证顺序,不清楚具体什么情况.所以在这里大致总结一下. Java的Has ...
- ORACLE中Scalar subquery Caching的hash table大小测试浅析
前阵子总结了这篇"ORACLE当中自定义函数性优化浅析"博客,里面介绍了标量子查询缓存(scalar subquery caching),如果使用标量子查询缓存,ORACLE会 ...
- 词典(二) 哈希表(Hash table)
散列表(hashtable)是一种高效的词典结构,可以在期望的常数时间内实现对词典的所有接口的操作.散列完全摒弃了关键码有序的条件,所以可以突破CBA式算法的复杂度界限. 散列表 逻辑上,有一系列可以 ...
- 文件hash、上传,实现文件上传重复验证
在平台开发中,我们往往对性能要求十分严苛,每一个字段.接口都有严格的要求. 系统中文件流操作十分占用资源,这里为大家介绍对文件上传进行哈希校验---同一文件只允许上传一次到服务器,其他的上传只要指向文 ...
- Python 中的哈希表
Python 中的哈希表:对字典的理解 有没有想过,Python中的字典为什么这么高效稳定.原因是他是建立在hash表上.了解Python中的hash表有助于更好的理解Python,因为Pytho ...
随机推荐
- CentOS下httpd下php 连接mysql 本机可以,127.0.0.1不能访问
你看到的这个文章来自于http://www.cnblogs.com/ayanmw php代码很简单: $server="127.0.0.1"; println("Begi ...
- 奇怪吸引子---YuWang
奇怪吸引子是混沌学的重要组成理论,用于演化过程的终极状态,具有如下特征:终极性.稳定性.吸引性.吸引子是一个数学概念,描写运动的收敛类型.它是指这样的一个集合,当时间趋于无穷大时,在任何一个有界集上出 ...
- cocos2d-x 3.0rc2中读取sqlite文件
cocos2d-x 3.0rc2中读取sqlite文件的方式,在Android中直接读取软件内的会失败.须要复制到可写的路径下 sqlite3* dbFile = NULL; std::string ...
- Tomcat不能自动编译JSP文件问题的一种解决方法
今天碰到一个非常奇怪的问题,机器环境是JDK8.Tomcat8,把jQuery MiniUI ( for Java Eclipse)下载后导入到Eclipse中,首页可以显示,但运行操作数据库的页面出 ...
- android studio 翻译插件
插件下载地址 https://github.com/Skykai521/ECTranslation/releases 使用说明: http://gold.xitu.io/entry/573d8d92a ...
- adding validation annotators to model classes 在linq to EntityFrame的Model中添加前台验证validation annotators
The same solution can be applied for LINQ to SQL. The snippet the article shows for using the Metada ...
- 安装mmseg出错 config.status: error: cannot find input file: src/Makefile.in
aclocallibtoolize --forceautomake --add-missingautoconfautoheadermake clean
- 将数据库表导入到solr索引
将数据库表导入到solr索引 编辑solrcofnig.xml添加处理器 <requestHandler name="/dataimport" class="org ...
- Cubieboard2裸机开发之(一)点亮板载LED
前言 CUbieboard2板载两个LED,一个绿色的,一个蓝色的,其中绿色LED通过三极管与PH20管脚连接,蓝色LED通过三极管与PH21管脚连接,这里只以蓝色LED为例,电路原理图如图1和图2所 ...
- HTML5新特性之Web Worker
1.概述 JavaScript语言采用的是单线程模型,也就是说,所有任务排成一个队列,一次只能做一件事.随着电脑计算能力的增强,这一点带来很大的不便,无法充分发挥JavaScript的潜能.龙其考虑到 ...