C语言中的hash函数

C语言中的hash函数,第1张

Hash,一般翻译做"散列",也有直接音译为"哈希"的,就是把任意长度的输入(又叫做预映射, pre-image),通过散列算法,变换成固定长度的输出,该输出就是散列值。这种转换是一种压缩映射,也就是,散列值的空间通常远小于输入的空间,不同的输入可能会散列成相同的输出,而不可能从散列值来唯一的确定输入值。简单的说就是一种将任意长度的消息压缩到某一固定长度的消息摘要的函数

HASH主要用于信息安全领域中加密算法,它把一些不同长度的信息转化成杂乱的128位的编码里,叫做HASH值 也可以说,hash就是找到一种数据内容和数据存放地址之间的映射关系。Hash算法在信息安全方面的应用主要体现在以下的3个方面:文件校验、数字签名、鉴权协议

程程序实现

// 说明:Hash函数(即散列函数)在程序设计中的应用目标 ------ 把一个对象通过某种转换机制对应到一个

//size_t类型(即unsigned long)的整型值。

// 而应用Hash函数的领域主要是 hash表(应用非常广)、密码等领域。

// 实现说明:

// ⑴、这里使用了函数对象以及泛型技术,使得对所有类型的对象(关键字)都适用。

// ⑵、常用类型有对应的偏特化,比如string、char、各种整形等。

// ⑶、版本可扩展,如果你对某种类型有特殊的需要,可以在后面实现专门化。

// ⑷、以下实现一般放在头文件中,任何包含它的都可使用hash函数对象。

//------------------------------------实现------------------------------------------------

#include <string>

using std::string;

inlinesize_thash_str(const char s)

{

unsigned long res = 0;

for (; s; ++s)

res = 5 res + s;

returnsize_t(res);

}

template <class Key>

struct hash

{

size_toperator () (const Key& k) const;

};

// 一般的对象,比如:vector< queue<string> >;的对象,需要强制转化

template < class Key >

size_thash<Key>::operator () (const Key& k) const

{

size_tres = 0;

size_tlen = sizeof(Key);

const char p = reinterpret_cast<const char>(&k);

while (len--)

{

res = (res<<1)^p++;

}

return res;

}

// 偏特化

template<>

size_thash< string >::operator () (const string& str) const

{

return hash_str(strc_str());

}

typedef char PChar;

template<>

size_thash<PChar>::operator () (const PChar& s) const

{

return hash_str(s);

}

typedef const char PCChar;

template<>

size_thash<PCChar>::operator () (const PCChar& s) const

{

return hash_str(s);

}

template<> size_t hash<char>::operator () (const char& x) const { return x; }

template<> size_t hash<unsigned char>::operator () (const unsigned char& x) const { return x; }

template<> size_t hash<signed char>::operator () (const signed char& x) const { return x; }

template<> size_t hash<short>::operator () (const short& x) const { return x; }

template<> size_t hash<unsigned short>::operator () (const unsigned short& x) const { return x; }

template<> size_t hash<int>::operator () (const int& x) const { return x; }

template<> size_t hash<unsigned int>::operator () (const unsigned int& x) const { return x; }

template<> size_t hash<long>::operator () (const long& x) const { return x; }

template<> size_t hash<unsigned long>::operator () (const unsigned long& x) const { return x; }

// 使用说明:

//

// ⑴、使用时首先由于是泛型,所以要加上关键字类型。

//

// ⑵、其次要有一个函数对象,可以临时、局部、全局的,只要在作用域就可以。

//

// ⑶、应用函数对象作用于对应类型的对象。

//----------------------- hash函数使用举例 -------------------------

#include <iostream>

#include <vector>

#include <string>

using namespace std;

int main()

{

vector<string> vstr⑵;

vstr[0] = "sjw";

vstr[1] = "suninf";

hash<string> strhash; // 局部函数对象

cout << " Hash value: " << strhash(vstr[0]) << endl;

cout << " Hash value: " << strhash(vstr[1]) << endl;

cout << " Hash value: " << hash< vector<string> >() (vstr) << endl;

cout << " Hash value: " << hash<int>() (100) << endl; // hash<int>() 临时函数对象

return 0;

}

应该是在最初选定一个函数,之后保持不变。

否则的话,如何进行查找呢?随机选一个函数,表中相应的位置没有并不能说明表中真的没有。难道这组哈希函数集所有的哈希函数都试一遍?这个函数集中函数的个数至少要比表的大小要大(满足universal性质的必要条件),全部试一遍还不如遍历一下表。

 Redis的数据类型

Redis的数据类型共有五种:string,list,hash,set,zset;

String 字符串相对来说做平常,key-value,类似是hashmap的用法;

List 队列,可以双向的存值,设计时,也可以简单用来当队列模式;

Hash 字典,一个key 对应多个值;

Set 无序的集合;

Zset 有序的集合;

列表 list

Redis列表是简单的字符串列表,按照插入顺序排序。你可以添加一个元素导列表的头部(左边)或者尾部(右边)

列表 list—— 基本命令

lpush

语法:lpush key value [value„]

作用:将一个或多个值 value 插入到列表 key 的表头(最左边),从左边开始加入值,从左到右的顺序依次插入到表头

返回值:数字,新列表的长度

rpush

语法:rpush key value [value„]

作用:将一个或多个值 value 插入到列表 key 的表尾(最右边),各个 value 值按从左到右 的顺序依次插入到表尾

返回值:数字,新列表的长度

lrange

语法:lrange key start stop

作用:获取列表 key 中指定区间内的元素,0 表示列表的第一个元素,以 1 表示列表的第二个元素;

start ,

stop 是列表的下标值,也可以负数的下标, -1 表示列表的最后一个元素, -2 表示列表的倒 数第二个元素,以此类推。

start ,stop 超出列表的范围不会出现错误。

返回值:指定区间的列表

lindex

语法:lindex key index

作用:获取列表 key 中下标为指定 index 的元素,列表元素不删除,只是查询。

0 表示列表的第一个元素,以 1 表示列表的第二个元素;

start ,

stop 是列表的下标值,也可以负数的下标, -1 表示列表的最后一个元素, -2 表示列表的倒数第二个元素,以此类推。

返回值:指定下标的元素;index 不在列表范围,返回nil

llen

语法:llen key

作用:获取列表 key 的长度 返回值:数值,列表的长度; key 不存在返回0

lrem

语法:lrem key count value

作用:根据参数count的值,移除列表中与参数value相等的元素,

count>0,从列表的左侧向右开始移 除;

count<0从列表的尾部开始移除;

count=0 移除表中所有与value相等的值。

返回值:数值,移除的元素个数

lset

语法:lset key index value

作用:将列表 key 下标为 index 的元素的值设置为 value。

返回值:设置成功返回 ok ; key 不存在或者 index 超出范围返回错误信息

linsert

语法:linsert key BEFORE(前)|AFTER(后) pivot value

作用:

将值value插入到列表key当中位于值pivot之前或之后的位置。

key不存在,pivot不在列表中, 不执行任何 *** 作。

返回值:命令执行成功,返回新列表的长度。没有找到 pivot 返回 -1, key 不存在返回 0。

RPOP key

移除列表的最后一个元素,返回值为移除的元素。

RPOPLPUSH source destination

移除列表的最后一个元素,并将该元素添加到另一个列表并返回

LPOP key

移除列表的第一个元素,返回值为移除的元素。

使用场景

1 消息队列

队列模式的情况下,可以使用,左进右出的原则,但不建议使用,因为现在市面上有很多成熟的消息中间件,没有必要造轮子;

2.排行榜

某一段时间统计数据的排行榜可以放在list里面,需要分页的话,也可以使用lrange start stop实现;

3 list类型的lpush命令和lrange命令能实现最新列表的功能,每次通过lpush命令往列表里插入新的元素,然后通过lrange命令读取最新的元素列表,如朋友圈的点赞列表、评论列表。

但是,并不是所有的最新列表都能用list类型实现,因为对于频繁更新的列表,list类型的分页可能导致列表元素重复或漏掉,举个例子,当前列表里由表头到表尾依次有(E,D,C,B,A)五个元素,每页获取3个元素,用户第一次获取到(E,D,C)三个元素,然后表头新增了一个元素F,列表变成了(F,E,D,C,B,A),此时用户取第二页拿到(C,B,A),元素C重复了。只有不需要分页(比如每次都只取列表的前5个元素)或者更新频率低(比如每天凌晨更新一次)的列表才适合用list类型实现

哈希类型hash

redis hash是一个 string 类型的 field 和 value 的映射表,hash特别适合用于存储对象,每个 hash 可以存储 232 - 1键值对(40多亿);

哈希类型 hash—— 基本命令

hset /hget /hmset /hmget /hgetall /hkeys /hvals /hexists

hset

语法:hset hash 表的key field value

作用:将哈希表 key 中的域 field 的值设为value ,如果 key 不存在,则新建 hash 表,执行赋值,如果有 field ,则覆盖值。

返回值: ①如果 field 是 hash 表中新field,且设置值成功,返回 1 ②如果 field 已经存在,旧值覆盖新值,返回0

hget

语法:hget key field

作用:获取哈希表 key 中给定域 field 的值

返回值:field 域的值,如果 key 不存在或者 field 不存在返回nil

hmset

语法:hmset key field value [field value„]

说明:同时将多个field-value(域-值)设置到哈希表key中,此命令会覆盖已经存在的field, hash表key不存在,创建空的hash表,执行hmset

返回值:设置成功返回ok, 如果失败返回一个错误

hmget

语法:hmget key field [field„]

作用:获取哈希表key中一个或多个给定域的值

返回值:返回和field顺序对应的值,如果field不存在,返回nil

hgetall

语法:hgetall key

作用:获取哈希表key中所有的域和值

返回值:以列表形式返回hash中域和域的值 ,key不存在,返回空hash

hdel

语法:hdel key field [field„]

作用:删除哈希表 key 中的一个或多个指定域 field,不存在 field 直接忽略

返回值:成功删除的 field 的数量

hkeys

语法:hkeys key

作用:查看哈希表 key 中的所有 field 域

返回值:包含所有 field 的列表,key 不存在返回空列表

hvals

语法:hvals key

作用:返回哈希表中所有域的值 返回值:包含哈希表所有域值的列表,key 不存在返回空列表

hexists

语法:hexists key field

作用:查看哈希表 key 中,给定域 field 是否存在

返回值:如果 field 存在,返回 1, 其他返回0

使用场景

1、购物车

以用户id为key,商品id为field,商品数量为value,恰好构成了购物车的3个要素,如下图所示。

2、hash还是比较适合存储对象(key field value)或者是字典表(type,key,vlaue),刚好符合对象的要素,但string + json也可以存储,两则比较有什么区别?

 String  + json    Hash

效率很  高           高

容量      低           低

灵活性  低           高

序列化  简单       复杂

以上就是关于C语言中的hash函数全部的内容,包括:C语言中的hash函数、请问算法导论中的全域哈希(universal hashing)是每一组 *** 作选定一个哈希函数,还是每次 *** 作选定一个、redis中list和hash的基本命令和使用场景等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/web/9284872.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2023-04-26
下一篇2023-04-26

发表评论

登录后才能评论

评论列表(0条)

    保存