哈希的定义

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

哈希简介

  • Hash算法可以将一个数据转换为一个标志,这个标志和源数据的每一个字节都有十分紧密的关系。
  • Hash算法还具有一个特点,就是很难找到逆向规律。基本不可能从结果推算出输入,所以又称为不可逆的算法
  • Hash算法是一个广义的算法,也可以认为是一种思想,使用Hash算法可以提高存储空间的利用率,可以提高数据的查询效率,也可以做数字签名来保障数据传递的安全性。所以Hash算法被广泛地应用在互联网应用中。
  • Hash算法也被称为散列算法,Hash算法虽然被称为算法,但实际上它更像是一种思想。Hash算法没有一个固定的公式,只要符合散列思想的算法都可以被称为是Hash算法

常见的哈希算法

  • MD4
  • MD5
  • SHA-1及其他

哈希的用途

  • 文件校验
  • 数字签名
  • 鉴权协议

std::hash的测试示例

对于内置的类型,C++标准库中已经提供了std::hash函数计算哈希值,但如果是自己自定义的类型想求哈希值的话,则需要自己定义哈希值的求值方式。

#include <iostream>
#include <functional>
#include <string>
#include <iomanip>


int main()
{
	std::string strInput = "Peaceful in the present world, quiet in the years";
	std::hash<std::string> szHash;
	size_t hashVal = szHash(strInput);
	std::cout << std::quoted(strInput) << "'s hash=" << hashVal << "\n";

	//
	char buffer1[] = "Everything is fine";
	char buffer2[] = "Everything is fine";
	std::string strBuffer1(buffer1);
	std::string strBuffer2(buffer2);

	std::hash<char*> ptrHash;
	std::hash<std::string> strHash;

	//C++14引入std::quoted用于给字符串添加双引号
	std::cout << std::quoted(buffer1) << "'s hash<char*>=" << ptrHash(buffer1) << std::endl;
	std::cout << std::quoted(buffer2) << "'s hash<char*>=" << ptrHash(buffer2) << std::endl;
	std::cout << std::quoted(strBuffer1) << "'s hash<std::string>=" << strHash(strBuffer1) << std::endl;
	std::cout << std::quoted(strBuffer2) << "'s hash<std::string>=" << strHash(strBuffer2) << std::endl;

	//boolalpha是使bool型变量按照false、true的格式输出,如不使用该标识符,则会按照1、0的格式输出
	std::cout << "same hashes:\n" << std::boolalpha;
	std::cout << "buffer1 and buffer2: " << (ptrHash(buffer1) == ptrHash(buffer2)) << '\n';//false
	std::cout << "strBuffer1 and strBuffer2: " << (strHash(strBuffer1) == strHash(strBuffer2)) << '\n';//true

	return 0;
}

输出结果:

"Peaceful in the present world, quiet in the years"'s hash=1772844349
"Everything is fine"'s hash<char*>=3806338771
"Everything is fine"'s hash<char*>=1493957927
"Everything is fine"'s hash<std::string>=1559491232
"Everything is fine"'s hash<std::string>=1559491232
same hashes:
buffer1 and buffer2: false
strBuffer1 and strBuffer2: true

C++ 官方提供的 demo

链接地址:https://en.cppreference.com/w/cpp/utility/hash

#include <iostream>
#include <iomanip>
#include <functional>
#include <string>
#include <unordered_set>
 
struct S {
    std::string first_name;
    std::string last_name;
};
bool operator==(const S& lhs, const S& rhs) {
    return lhs.first_name == rhs.first_name && lhs.last_name == rhs.last_name;
}
 
// custom hash can be a standalone function object:
struct MyHash
{
    std::size_t operator()(S const& s) const noexcept
    {
        std::size_t h1 = std::hash<std::string>{}(s.first_name);
        std::size_t h2 = std::hash<std::string>{}(s.last_name);
        return h1 ^ (h2 << 1); // or use boost::hash_combine
    }
};
 
// custom specialization of std::hash can be injected in namespace std
template<>
struct std::hash<S>
{
    std::size_t operator()(S const& s) const noexcept
    {
        std::size_t h1 = std::hash<std::string>{}(s.first_name);
        std::size_t h2 = std::hash<std::string>{}(s.last_name);
        return h1 ^ (h2 << 1); // or use boost::hash_combine
    }
};
 
int main()
{
    std::string str = "Meet the new boss...";
    std::size_t str_hash = std::hash<std::string>{}(str);
    std::cout << "hash(" << std::quoted(str) << ") = " << str_hash << '\n';
 
    S obj = { "Hubert", "Farnsworth" };
    // using the standalone function object
    std::cout << "hash(" << std::quoted(obj.first_name) << ", "
              << std::quoted(obj.last_name) << ") = "
              << MyHash{}(obj) << " (using MyHash)\n" << std::setw(31) << "or "
              << std::hash<S>{}(obj) << " (using injected std::hash<S> specialization)\n";
 
    // custom hash makes it possible to use custom types in unordered containers
    // The example will use the injected std::hash<S> specialization above,
    // to use MyHash instead, pass it as a second template argument
    std::unordered_set<S> names = {obj, {"Bender", "Rodriguez"}, {"Turanga", "Leela"} };
    for(auto& s: names)
        std::cout << std::quoted(s.first_name) << ' ' << std::quoted(s.last_name) << '\n';
}

输出结果:

hash("Meet the new boss...") = 1861821886482076440
hash("Hubert", "Farnsworth") = 17622465712001802105 (using MyHash)
                            or 17622465712001802105 (using injected std::hash<S> specialization) 
"Turanga" "Leela"
"Bender" "Rodriguez"
"Hubert" "Farnsworth"
Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐