最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

c++中std::hash以及萬(wàn)能hash的使用方式

 更新時(shí)間:2023年08月07日 10:05:07   作者:米安r  
這篇文章主要介紹了c++中std::hash以及萬(wàn)能hash的使用方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教

c++ std::hash以及萬(wàn)能hash的使用

首先是標(biāo)準(zhǔn)庫(kù)中的std::hash函數(shù),對(duì)于內(nèi)置的類型,標(biāo)準(zhǔn)庫(kù)中是已經(jīng)提供了的(包括std::string),但是若是自己自定義的類型想要求其哈希值的話,就需要自己定義其哈希值的求值方式。

下面是簡(jiǎn)單示范

#include <map>
#include <unordered_map>
#include <unordered_set>
#include <iostream>
using std::cout;
using std::endl;
class MyClass 
{
public:
    MyClass():str("hello"), data(0) {}
    bool operator==(const MyClass& rhs) const{return (data == rhs.data) && (str == rhs.str); }  //注意要重載這個(gè)==,
                                                                                                //因?yàn)閡nordered_set或者unordered_map
                                                                                                //中需要對(duì)元素是否相同進(jìn)行判斷
public: //
    int data;
    std::string str;
};
//注意這里是將自己寫(xiě)的偏特化也同樣加入到std中,因?yàn)樗哪0迨窃趕td里面的,
//具體形式可以自己簡(jiǎn)單查看一下源碼中的實(shí)現(xiàn)形式
//然后照著寫(xiě)一個(gè)自己的版本就行了。
namespace std	
{
    template<>
    struct hash<MyClass>: public __hash_base<size_t, MyClass>   //標(biāo)準(zhǔn)庫(kù)中有這個(gè)繼承,查看一下其實(shí)只是繼承兩個(gè)typedef而已,
                                                                //所以不寫(xiě)這個(gè)繼承在這個(gè)例子中也是可以運(yùn)行的
                                                                //但為了更好的使用這個(gè)hash,寫(xiě)上去會(huì)比較好
    {
        size_t operator()(const MyClass& rhs) const noexcept    //這個(gè)const noexpect一定要寫(xiě)上去
        {
            return (std::hash<int>()(rhs.data)) ^ (std::hash<std::string>()(rhs.str) << 1); //當(dāng)然,可以使用其他的方式來(lái)組合這個(gè)哈希值,
                                                                                            //這里是cppreference里面的例子,產(chǎn)生的數(shù)夠亂就行。
        }
    };
}
int main()
{
    MyClass c;
    std::hash<MyClass> myHash;  //創(chuàng)建一個(gè)函數(shù)對(duì)象
    std::cout << myHash(c) << std::endl;
	//注意這第三個(gè)參數(shù)是typename _Hash = hash < _Value >, 是可寫(xiě)可不寫(xiě)的,因?yàn)樗怯心J(rèn)形式的,寫(xiě)出來(lái)就是這樣
    std::unordered_map<MyClass, char, std::hash<MyClass>> m;	//這第三個(gè)參數(shù)
    std::unordered_set<MyClass> s;	//和上面的是一個(gè)意思,第二個(gè)參數(shù)是typename _Hash = hash < _Value >,可寫(xiě)可不寫(xiě), 這里我是沒(méi)寫(xiě)的。
    s.insert(c);
    s.insert(c);
    std::cin.get();
}

另外一種方式是使用侯捷老師在講的“萬(wàn)能哈希函數(shù)”原理只要明白可變模板參數(shù)的使用方法就不會(huì)太難,下面是他課上使用的代碼

#include <string>
using std::string;
class Customer
{
public:
    string mFirstName;
    string mLastName;
    string mAge;
    Customer(string firstName, string lastName, string age):mFirstName(firstName),mLastName(lastName),mAge(age){}
    bool operator ==(const Customer& c) const
    {
        return (mFirstName == c.mFirstName && mLastName == c.mLastName && mAge == c.mAge);
    }
};
class CustomerHash
{
public:
    std::size_t operator()(const Customer& c) const
    {
        return hash_val(c.mFirstName, c.mLastName, c.mAge);
    }
    template <typename... Types>
    size_t hash_val(const Types&... args)const
    {
        size_t seed = 0;
        hash_value(seed, args...);
        return seed;
    }
    template <typename T, typename... Types>
    void hash_value(size_t& seed,
                         const T& firstArg,
                         const Types&... args) const
    {
        hash_combine(seed, firstArg);
        hash_value(seed, args...);
    }
    template <typename T>
    void hash_value(size_t& seed,
                         const T& val) const
    {
        hash_combine(seed, val);
    }
    template<typename T>
    void hash_combine(size_t& seed,
                             const T& val) const
    {
        seed ^= std::hash<T>()(val) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
    }
};
int main()
{
    std::unordered_multiset<Customer, CustomerHash> set;
}

c++11中std::hash用法

哈希的定義

Hash,一般翻譯做散列、雜湊,或音譯為哈希,是把任意長(zhǎng)度的輸入(又叫做預(yù)映射pre-image)通過(guò)散列算法變換成固定長(zhǎng)度的輸出,該輸出就是散列值。

這種轉(zhuǎn)換是一種壓縮映射,也就是,散列值的空間通常遠(yuǎn)小于輸入的空間,不同的輸入可能會(huì)散列成相同的輸出,所以不可能從散列值來(lái)確定唯一的輸入值。

簡(jiǎn)單的說(shuō)就是一種將任意長(zhǎng)度的消息壓縮到某一固定長(zhǎng)度的消息摘要的函數(shù)。

哈希簡(jiǎn)介

  • Hash算法可以將一個(gè)數(shù)據(jù)轉(zhuǎn)換為一個(gè)標(biāo)志,這個(gè)標(biāo)志和源數(shù)據(jù)的每一個(gè)字節(jié)都有十分緊密的關(guān)系。
  • Hash算法還具有一個(gè)特點(diǎn),就是很難找到逆向規(guī)律。基本不可能從結(jié)果推算出輸入,所以又稱為不可逆的算法
  • Hash算法是一個(gè)廣義的算法,也可以認(rèn)為是一種思想,使用Hash算法可以提高存儲(chǔ)空間的利用率,可以提高數(shù)據(jù)的查詢效率,也可以做數(shù)字簽名來(lái)保障數(shù)據(jù)傳遞的安全性。所以Hash算法被廣泛地應(yīng)用在互聯(lián)網(wǎng)應(yīng)用中。
  • Hash算法也被稱為散列算法,Hash算法雖然被稱為算法,但實(shí)際上它更像是一種思想。Hash算法沒(méi)有一個(gè)固定的公式,只要符合散列思想的算法都可以被稱為是Hash算法

常見(jiàn)的哈希算法

  • MD4
  • MD5
  • SHA-1及其他

哈希的用途

  • 文件校驗(yàn)
  • 數(shù)字簽名
  • 鑒權(quán)協(xié)議

std::hash的測(cè)試示例

對(duì)于內(nèi)置的類型,C++標(biāo)準(zhǔn)庫(kù)中已經(jīng)提供了std::hash函數(shù)計(jì)算哈希值,但如果是自己自定義的類型想求哈希值的話,則需要自己定義哈希值的求值方式。

#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用于給字符串添加雙引號(hào)
	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型變量按照f(shuō)alse、true的格式輸出,如不使用該標(biāo)識(shí)符,則會(huì)按照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;
}

輸出結(jié)果:

"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';
}

輸出結(jié)果:

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"

總結(jié)

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • C++教程之進(jìn)制轉(zhuǎn)換的實(shí)現(xiàn)方法

    C++教程之進(jìn)制轉(zhuǎn)換的實(shí)現(xiàn)方法

    在C++中進(jìn)行進(jìn)制轉(zhuǎn)換可以通過(guò)標(biāo)準(zhǔn)庫(kù)函數(shù)或自定義算法實(shí)現(xiàn),本文主要為大家整理了兩種常見(jiàn)場(chǎng)景的轉(zhuǎn)換方法及示例代碼,有需要的小伙伴可以根據(jù)需求進(jìn)行選擇
    2025-04-04
  • C++JSON庫(kù)CJsonObject詳解(輕量簡(jiǎn)單好用)

    C++JSON庫(kù)CJsonObject詳解(輕量簡(jiǎn)單好用)

    CJsonObject是基于cJSON全新開(kāi)發(fā)一個(gè)C++版的JSON庫(kù),CJsonObject的最大優(yōu)勢(shì)是輕量簡(jiǎn)單好用,開(kāi)發(fā)效率極高,對(duì)多層嵌套json的讀取和生成使用非常簡(jiǎn)單,喜歡的朋友一起看看吧
    2021-04-04
  • C++實(shí)現(xiàn)順序表的常用操作(插入刪出查找輸出)

    C++實(shí)現(xiàn)順序表的常用操作(插入刪出查找輸出)

    實(shí)現(xiàn)順序表的插入,刪除,查找,輸出操作在C語(yǔ)言中經(jīng)常用到。下面小編給大家整理實(shí)現(xiàn)代碼,一起看下吧
    2016-08-08
  • C語(yǔ)言編程計(jì)算信噪比SNR理解學(xué)習(xí)

    C語(yǔ)言編程計(jì)算信噪比SNR理解學(xué)習(xí)

    這篇文章主要介紹了C語(yǔ)言編程信噪比SNR計(jì)算的理解學(xué)習(xí),信噪比,英文名稱叫做SNR或S/N(SIGNAL-NOISE RATIO)。是指一個(gè)電子設(shè)備或者電子系統(tǒng)中信號(hào)與噪聲的比例
    2021-10-10
  • Qt中QAbstractButton::setAutoRepeat設(shè)置按住按鈕自動(dòng)重復(fù)

    Qt中QAbstractButton::setAutoRepeat設(shè)置按住按鈕自動(dòng)重復(fù)

    QAbstractButton::setAutoRepeat接口用于設(shè)置按鈕自動(dòng)重復(fù)功能,本文就來(lái)介紹一下Qt中QAbstractButton::setAutoRepeat設(shè)置按住按鈕自動(dòng)重復(fù),感興趣的可以了解一下
    2026-06-06
  • 詳解c/c++賦值函數(shù)(重載=號(hào)運(yùn)算符)

    詳解c/c++賦值函數(shù)(重載=號(hào)運(yùn)算符)

    大家都知道c++里的各種運(yùn)算符都是用函數(shù)實(shí)現(xiàn)的,比如=就等號(hào)函數(shù),所以當(dāng)用=給一個(gè)對(duì)象賦值的時(shí)候,實(shí)際調(diào)用的是=號(hào)所對(duì)應(yīng)的=號(hào)函數(shù)。下面通過(guò)本文給大家介紹c/c++賦值函數(shù)(重載=號(hào)運(yùn)算符),感興趣的朋友一起看看吧
    2018-08-08
  • C++實(shí)現(xiàn)五子棋小游戲

    C++實(shí)現(xiàn)五子棋小游戲

    這篇文章主要為大家詳細(xì)介紹了C++實(shí)現(xiàn)五子棋小游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-05-05
  • Qt實(shí)現(xiàn)自定義矩陣布局

    Qt實(shí)現(xiàn)自定義矩陣布局

    這篇文章主要為大家詳細(xì)介紹了Qt實(shí)現(xiàn)自定義矩陣布局,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-08-08
  • opencv3/C++輪廓的提取與篩選方式

    opencv3/C++輪廓的提取與篩選方式

    今天小編就為大家分享一篇opencv3/C++輪廓的提取與篩選方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2019-12-12
  • C++使用宏實(shí)現(xiàn)動(dòng)態(tài)庫(kù)加載

    C++使用宏實(shí)現(xiàn)動(dòng)態(tài)庫(kù)加載

    開(kāi)發(fā)的時(shí)候,有些項(xiàng)目不能靜態(tài)鏈接動(dòng)態(tài)庫(kù),需要程序運(yùn)行時(shí)加載動(dòng)態(tài)庫(kù)。本文將使用宏來(lái)實(shí)現(xiàn)動(dòng)態(tài)庫(kù)的加載,感興趣的小伙伴可以跟隨小編一起了解一下
    2022-12-12

最新評(píng)論

湖南省| 吉安市| 浠水县| 突泉县| 从江县| 苍溪县| 昌宁县| 白玉县| 开鲁县| 肃宁县| 深水埗区| 仪征市| 高邮市| 呼伦贝尔市| 海伦市| 翼城县| 库车县| 通州区| 富平县| 自治县| 周至县| 中卫市| 临澧县| 肇州县| 凤山市| 麻城市| 鄂州市| 廉江市| 湛江市| 交口县| 襄樊市| 深水埗区| 安岳县| 集安市| 西和县| 九江市| 会昌县| 平武县| 顺义区| 东山县| 米易县|