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

C++哈希表的實現(xiàn)思路剖析講解

 更新時間:2026年05月05日 09:31:38   作者:進擊的荊棘  
這篇文章主要介紹了C++哈希表的實現(xiàn)思路,文中詳解哈希概念,通過大量實例代碼帶你直觀理解,掌握查找優(yōu)化核心,夯實C++數(shù)據(jù)結(jié)構(gòu)基礎(chǔ),需要的朋友可以參考下

前言

哈希又稱散列,是一種組織數(shù)據(jù)的方式。從譯名來看,有散亂排列的意思。本質(zhì)就是通過哈希函數(shù)把關(guān)鍵字Key跟存儲位置建立一個哈希映射關(guān)系,查找時通過這個哈希函數(shù)計算出Key存儲的位置,進行快速查找。

1.直接定址法

當(dāng)關(guān)鍵字的范圍比較集中時,直接定址法就是非常簡單高效的方法,如一組關(guān)鍵字都在[0,99]之間,那么我們開一個100個數(shù)的數(shù)組,每個關(guān)鍵字的值直接就是存儲位置的下標(biāo)。再比如一組關(guān)鍵字值都在[a,z]的小寫字母,那么我們開一個26個數(shù)的數(shù)組,每個關(guān)鍵字ascii碼-'a'就是存儲位置的下標(biāo),也就是說直接定址法本質(zhì)就是用關(guān)鍵字計算出一個絕對位置或者相對位置。

字符串中的第一個唯一字符

class Solution {
public:
    int firstUniqChar(string s) {
        //桶思想
        vector<int> cnt(26,0);
        //統(tǒng)計次數(shù)
        for(auto i:s) cnt[i-'a']++;
        for(size_t i=0;i<s.size();i++) if(cnt[s[i]-'a']==1) return i;
        return -1;
    }
};

2.哈希沖突

直接定址法的缺點也非常明顯,當(dāng)關(guān)鍵字的范圍比較分散時,就很浪費內(nèi)存甚至內(nèi)存不夠用。假設(shè)只有數(shù)據(jù)范圍是[0,9999]的N個值,要映射到一個M個空間的數(shù)組中(一般情況下M>=N),那么就要借助哈希函數(shù)(hash function)hf,關(guān)鍵字key被放在數(shù)組的h(key)位置,要注意的是h(key)計算出的值必須在[0,M)之間。

這里存在的一個問題就是,兩個不同的key可能會映射到同一個位置,這種問題叫哈希沖突,或哈希碰撞。理想情況是找出一個好的哈希函數(shù)避免沖突,但是實際場景中,沖突是不可避免的,所以盡可能設(shè)計出優(yōu)秀的哈希函數(shù),減少沖突的次數(shù),同時也要去設(shè)計出解決沖突的方案。

3.負(fù)載因子

假設(shè)哈希表中已經(jīng)映射存儲了N個值,哈希表的大小為M,那么負(fù)載因子=N/M,負(fù)載因子有些地方也翻譯為荷載因子/裝載因子,英文為load factor。負(fù)載因子越大,哈希沖突的概率越高,空間利用率越高;負(fù)載因子越小,哈希沖突的概率越低,空間利用率越低。

4.將關(guān)鍵字轉(zhuǎn)成整數(shù)

將關(guān)鍵字映射到數(shù)組中位置,一般是整數(shù)好做映射計算,若不是整數(shù),要想辦法轉(zhuǎn)換成整數(shù)。

5.哈希函數(shù)

一個好的哈希函數(shù)應(yīng)該讓N個關(guān)鍵字被等概率的均勻的散列分布到哈希表的M個空間中,但是實際中卻很難做到,但是要盡量往這個方向去考量設(shè)計。

5.1除法散列法/除留余數(shù)法

●除法散列法也叫除留余數(shù)法,顧名思義,假設(shè)哈希表的大小為M,那么通過key除以M的余數(shù)作為映射位置的下標(biāo),也就是哈希函數(shù)為:h(key)=key%M。

●當(dāng)使用除法散列法時,要盡量避免M為某些值,如2的冪,10的冪等。若是2^x,那么key%2^x本質(zhì)相當(dāng)于保留key的后x位,那么后x位相同的值,計算出的哈希值都是一樣的,就沖突了。如{63,31}看起來沒有關(guān)聯(lián)的值,若M是16,也就是2^4,那么計算出的哈希值都是15,因為63的二進制后8位是00111111,31的二進制后8位是00111111。若是10^x,就更明顯了,保留的都是10進制的后x位,如:{112,12312},若M是100,也就是10^2,那么計算出的哈希值都是12。

●當(dāng)使用除法散列法時,建議M取不太接近2的整數(shù)次冪的一個質(zhì)數(shù)(素數(shù))。

●需要說明的是,Java的HashMap采用除法散列法時就是2的整數(shù)次冪做哈希表的大小M,這樣的話,就不用取模,而可以直接位運算,相對而言位運算比模更高效一些。但它不是單純的去取模,比如M是2^16次方,本質(zhì)是取后16位,那么用key`=key>>16,然后把key和key`異或的結(jié)果作為哈希值。也就是說我們映射出的值還是在[0,M)范圍內(nèi),但是盡量讓key所有的位都參與計算,這樣映射出的哈希值更均勻一些。所以建議M取不太接近2的整數(shù)次冪的一個質(zhì)數(shù)的理論是大多數(shù)數(shù)據(jù)結(jié)構(gòu)書籍中寫的理論,但實踐中需靈活運用。

5.2乘法散列法(了解)

●乘法散列法對哈希表大小M沒有要求,它的大思路第一步:用關(guān)鍵字K乘上常數(shù)A(0<A<1),并抽出K*A的小數(shù)部分。第二步:后再用M乘以K*A的小數(shù)部分,在向下取整。

●h(key)=floor(Mx((Axkey)%1.0)),其中floor表示對表達式進行向下取整,A∈(0,1),這里最重要的是A的值應(yīng)該如何設(shè)定,Knuth認(rèn)為A=(√5-1)/2=0.6180339887……(黃金分割點)比較好。

●乘法散列法對哈希表大小M是沒有要求的,假設(shè)M位1024,key為1234,A=0.6180339887,A*key=762.6539420558,取小數(shù)部分為0.6539420558,Mx((Axkey)%1.0)=0.6539420558*1024=669.6366651392,那么h(1234)=669。

5.3全域散列法(了解)

●若存在一個惡意的對手,他針對我們提供的散列函數(shù),特意構(gòu)造出一個發(fā)生嚴(yán)重沖突的數(shù)據(jù)集,比如,讓所有關(guān)鍵字全部落入同一個位置中。這種情況是可以存在的,只要散列函數(shù)是公開且確定的,就可以實現(xiàn)此攻擊。解決方法就是給散列函數(shù)增加隨機性,攻擊者就無法找出確定可以導(dǎo)致最壞情況的數(shù)據(jù)。這種方法叫做全域散列。

●h(key)=((axkey+b)%P)%M,P需要選一個足夠大的質(zhì)數(shù),a可以隨機選[1,P-1]之間的任意整數(shù),b可以隨機選[0,P-1]之間的任意整數(shù),這些函數(shù)構(gòu)成了一個P*(P-1)組全域散列函數(shù)組。假設(shè)P=17,M=6,a=3,b=4,則h(8)=((3x8+4)%17)%6=5。

●需要注意每次初始化哈希表時,隨機選取全域散列函數(shù)組中的一個散列函數(shù)使用,后續(xù)增刪查改都固定使用這個散列函數(shù),否則每次哈希都是隨機選一個散列函數(shù),那么插入是一個散列函數(shù),查找又是另一個散列函數(shù),就會導(dǎo)致找不到插入的key了。

5.4其它方法(了解)

●上面的幾種方法是《算法導(dǎo)論》書籍中講解的方法。

●《殷人昆 數(shù)據(jù)結(jié)構(gòu):用面向?qū)ο蠓椒ㄅcC++語言描述(第二版)》和《數(shù)據(jù)結(jié)構(gòu)(C語言版) 嚴(yán)蔚敏_吳偉民》等教材型書籍上面還給出平方取中法、折疊法、隨機數(shù)法、數(shù)學(xué)分析法等,這些方法相對更適用于一些局限的特定場景。

6.處理哈希沖突

實際中哈希表一般還是選擇除法散列法作為哈希函數(shù),當(dāng)然哈希表無論選擇什么哈希函數(shù)也避免不了沖突,那么插入數(shù)據(jù)時,如何解決沖突?主要有兩種方法,開放定址法鏈地址法。

6.1開放定址法

在開放定址法中所有的元素都放在哈希表中,當(dāng)一個關(guān)鍵字key用哈希函數(shù)計算出的位置沖突了,則按照某種規(guī)則找到一個沒有存儲數(shù)據(jù)的位置進行存儲,開放定址法中負(fù)載因子一定是小于1的。這里的規(guī)則有三種:線性探測、二次探測、雙重探測。

線性探測

●從發(fā)生沖突的位置開始,依次線性向后探測,直到尋找到下一個沒有存儲數(shù)據(jù)的位置為止,若走到哈希表尾,則繞回到哈希表頭的位置。

●h(key)=hash0=key%M,hash0位置沖突了,則線性探測公式為:hc(key,i)=hashi=(hash0+i)%M,i={1,2,3,…,M-1},因為負(fù)載因子小于1,則最多探測M-1次,一定能找到一個存儲key的位置。

●線性探測的比較簡單且容易實現(xiàn),線性探測的問題假設(shè),hash0位置連續(xù)沖突,hash0,hash1,hash2位置已經(jīng)存儲數(shù)據(jù)了,后續(xù)映射到hash0,hash1,hash2,hash3的值都會爭奪hash3位置,這種現(xiàn)象叫做群集/堆積。下面的二次探測可以一定程度改善這個問題。

●下面演示{19,30,5,36,13,20,21,12}等這一組值映射到M=11的表中。

h(19)=8,h(30)=8,h(5)=5,h(36)=3,h(13)=2,h(20)=9,h(21)=10,h(12)=1

二次探測

●從發(fā)生沖突的位置開始,依次左右二次方跳躍式探測,直到尋找到下一個沒有存儲數(shù)據(jù)的位置為止,若往右走到哈希表尾,則回繞到哈希表頭的位置;若往左走到哈希表頭,則繞回到哈希表尾的位置;

●h(key)=hash0=key%M,hash0位置沖突了,則二次探測公式為:hc(key,i)=hashi=(hash0?i^2)%M,i={1,2,3…,M/2}

●二次探測當(dāng)hashi=(hash0-i^2)%M時,當(dāng)hashi<0時,需要hashi+=M

●下面演示{19,30,52,63,11,22}等這一組值映射到M=11的表中。

h(19)=8,h(30)=8,h(52)=8,h(63)=8,h(11)=0,h(22)=0

雙重散列(了解)

●第一個哈希函數(shù)計算出的值發(fā)生沖突,使用第二個哈希函數(shù)計算出一個跟key相關(guān)的偏移量值,不斷往后探測,直到尋找到下一個沒有存儲數(shù)據(jù)的位置為止。

●h1(key)=hash0=key%M,hash0位置沖突了,則雙重探測公式為:hc(key,i)=hashi=(hash0+i*h2(key))%M,i={1,2,3,…,M}。

●要求h2(key)<M且h2(key)和M互為質(zhì)數(shù),有兩種簡單的取值方法:1、當(dāng)M為2整數(shù)冪時,h2(key)從[0,M-1]任選一個奇數(shù);2、當(dāng)M為質(zhì)數(shù)時,h2(key)=key%(M-1)+1

●保證h2(key)與M互質(zhì)是因為根據(jù)固定的偏移量所尋址的所有位置將形成一個群,若最大公約數(shù)p=g c d(M,h1(key))>1,那么所能尋址的位置的個數(shù)為M/P<M,使得對于一個關(guān)鍵字來說無法充分領(lǐng)用整個散列表。例:若初始探測位置為1,偏移量為3,整個散列表大小為12,那么所能尋址的位置為{1,4,7,10},尋址個數(shù)為12/g c d(12,3)=4

●下面演示{19,30,52,74}等這一組值映射到M=11的表中,設(shè)h2(key)=key%10+1

6.2開放定址法代碼實現(xiàn)

開放地址法在實踐中,不如下面鏈地址法,因為開發(fā)定址法解決沖突不管使用哪種方法,占用的都是哈希表中的空間,始終存在互相影響的問題。所以開放定址法,簡單選擇線性探測實現(xiàn)。

開發(fā)定址法的哈希表結(jié)構(gòu)

enum State{
    EXIST,EMPTY,DELETE
};
template<class K,class V>
struct HashData{
    pair<K,V> _kv;
    State _state=EMPTY;
};
 template<class K,class V>
 class HashTable{
 private:
    vector<HashData<K,V>> _tables;
    int _n;
 };

要注意這里需要給每個存儲值的位置加一個狀態(tài)標(biāo)識,否則刪除一些值后,回影響后面沖突的值的查找。如下圖,刪除30,回導(dǎo)致查找20失敗,當(dāng)我們給每個位置加一個狀態(tài)標(biāo)識{EXIST,EMPTY,DELETE},刪除30就可以不用刪除值,而是把狀態(tài)改成DELETE,那么查找20是時遇到EMPTY才能停止,就可以找到20.

h(19)=8,h(30)=8,h(5)=5,h(36)=3,h(13)=2,h(20)=9,h(21)=10,h(12)=1

擴容

哈希表負(fù)載因子控制在0.7,當(dāng)負(fù)載因子到0.7以后就需要擴容,按照2倍擴容,但是同時要保持哈希表是一個質(zhì)數(shù),第一個是質(zhì)數(shù),2倍后就不是質(zhì)數(shù)了。那么如何解決?一種方案就是上面1.4.1除法散列中的Java HashMap的使用2的整數(shù)冪,但是計算時不能直接取模的改進方法。另一種方案時sgi版本的哈希表使用的方法,給了一個近似2倍的質(zhì)數(shù)表,每次取質(zhì)數(shù)表獲取擴容后的大小。

inline unsigned long __stl_next_prime(unsigned long n){
    //Note:assumes long is at least 32 bits
    static const int __stl_num_primes=28;
    static const unsigned long __stl_prime_list[__stl_num_primes]={
        53, 97, 193, 389, 769,
		1543, 3079, 6151, 12289, 24593,
		49157, 98317, 196613, 393241, 786433,
		1572869, 3145739, 6291469, 12582917, 25165843,
		50331653, 100663319, 201326611, 402653189, 805306457,
		1610612741, 3221225473, 4294967291
    };
    const unsigned long* first=__stl_prime_list;
    const unsigned long* last=__stl_prime_list+__stl_num_primes;
    const unsigned long* pos=lower_bound(first,last,n);
    return pos==last?*(last-1):*pos;
}

key不能取模的問題

當(dāng)key是string/Date等類型是,key不能取模,那么需要給HashTable增加一個仿函數(shù),這個仿函數(shù)支持把key轉(zhuǎn)換成一個可以取模的整型,若key可以轉(zhuǎn)換為整型并且不容易沖突,那么這個仿函數(shù)就用默認(rèn)參數(shù)即可,若這個key不能轉(zhuǎn)換成整型,就需要自己實現(xiàn)一個仿函數(shù)傳給這個參數(shù),實現(xiàn)這個仿函數(shù)的要求就是盡量key的每個值都參與到計算中,讓不同的key轉(zhuǎn)換出的整型值不同。string做哈希表的key非常常見,所以可以把sring特化一下。

template<class K>
struct HashFunc{
    size_t operator()(const K& key){
        return (size_t)key;
    }
};
template<>
struct HashFunc<string>{
    size_t operator()(const string& s){
        //BKDR
        size_t hash=0;
        for(auto ch:s){
            hash+=ch;
            hash*=131;
        }
        return hash;
    }
};
template<class K,class V,class Hash=HashFunc<K>>
class HashTable{
private:
    vector<HashData<K,V>> _tables;
    int _n;
};

完整代碼示例

namespace open_address{
    template<class K,class V,class Hash=HashFunc<K>>
    class HashTable{
    public:
        HashTable()
            :_tables(__stl_next_prime(0))
            ,_n(0)
        {}
        bool Insert(const pair<K,V>& kv){
            if(Find(kv.first)){
                return false;
            }
            //負(fù)載因子>=0.7,擴容
            if(_n*10/_tables.size()>=0.7){
                //舊法,等于說把Insert接口的邏輯又實現(xiàn)了一遍
                // vector<HashData<K,V> nextables(_tables.size()*2);
                // for(auto& data:_tables){
                //     //舊表的數(shù)據(jù)映射到新表
                //     if(data._state==EXIST){
                //         size_t hash0=data._kv.first%newtables.size();
                //         //……
                //     }
                // }
                //現(xiàn)代寫法
                HashTable<K,V> newht;
                //newht._tables.resize(_tables.size()*2);
                newht._tables.resize(__stl_next_prime(_tables.size()+1));
                for(auto& data:_tables){
                    //舊表映射到新表
                    if(data._state==EXIST)
                        newht.Insert(data._kv);
                }
                _tables.swap(newht._tables);
            }
            size_t hash0=kv.first%_tables.size();
            size_t hash1=hash0;
            int i=1;
            int flag=1;
            while(_tables[hash1]._state==EXIST){
                //線性探測
                hash1=(hash0+i)%_tables.size();
                ++i;
                //二次探測
                /*hash1=(hash0+(i*i*flag))%_tables.size();
                if(hash1<_tables.size()){
                    hash1+=_tables.size();
                }
                if(flag==1)
                    flag=-1;
                else{
                    ++i;
                    flag=-1;
                }*/
            }
            _tables[hash1]._kv=kv;
            _tables[hash1]._state=EXIST;
            _n++;
            return false;
        }
        HashData<K,V>* Find(const K& key){
            size_t hash0=key%_tables.size();
            size_t hash1=hash0;
            int i=1;
            while(_tables[hash1]._state!=EMPTY){
                if(_tables[hash1]._kv.first==key&&_tables[hash1]._state==EXIST)
                    return &_tables[hash1];
                hash1=(hash0+i)%_tables.size();
                ++i;
            }
            return nullptr;
        }
        bool Erase(const K& key){
            HashData<K,V>* ret=Find(key);
            if(ret){
                ret->_state=DELETE;
                --_n;
                return true;
            }
            else return false;
        }
    private:
        vector<HashData<K,V>> _tables;
        int _n;
    };
}

6.3鏈地址法

解決沖突的思路

開放定址法中所有的元素都放在哈希表里,鏈地址法中所有的數(shù)據(jù)不再直接存儲在哈希表中,哈希表中存儲一個指針,沒有數(shù)據(jù)映射這個位置時,這個指針為空,有多個數(shù)據(jù)映射到這個位置時,我們把這些沖突的數(shù)據(jù)鏈接成一個鏈表,掛在哈希表這個位置下面,鏈地址法也叫拉鏈法或哈希桶。

●下面演示{19,30,5,36,13,20,21,12,24,96}等這一組值映射到M=11的表中。

h(19)=8,h(30)=8,h(5)=5,h(36)=3,h(13)=2,h(20)=9,h(21)=10,h(12)=1,h(24)=2,h(96)=88

擴容

開放定址法負(fù)載因子必須小于1,鏈地址法的負(fù)載因子就沒有限制了,可以大于1。負(fù)載因子越大,哈希沖突的概率越高,空間利用率越高;負(fù)載因子越小,哈希沖突的概率越低,空間利用率越低;stl中unordered_xxx的最大負(fù)載因子基本控制在1,大于1就擴容。

極端場景

若極端場景下,某個桶特別長怎么辦?可以考慮使用全域散列法,這樣就不容易被針對。但是假設(shè)不是被針對了,用來全域散列法,但是偶然情況下,某個桶很長,查找效率很低怎么辦?在Java8的HashMap中當(dāng)桶的長度超過一定閾值(8)時就把鏈表轉(zhuǎn)換成紅黑樹。一般情況下,不斷擴容,單個桶很長的場景還是比較少的。

6.4鏈地址法代碼實現(xiàn)

namespace hash_bukect{
    template<class K,class V>
    struct HashNode{
        pair<K,V> _kv;
        HashNode<K,V>* _next;
        HashNode(const pair<K,V>& kv)
            :_kv(kv)
            ,_next(nullptr)
        {}
    };
    template<class K,class V,class Hash=HashFunc<K>>
    class HashTable{
        typedef HashNode<K,V> Node;
    public:
        HashTable()
            :_tables(11)
            ,_n(0)
        {}
        inline unsigned long __stl_next_prime(unsigned long n){
            //Note:assumes long is at least 32 bits
            static const int __stl_num_primes=28;
            static const unsigned long __stl_prime_list[__stl_num_primes]={
                53, 97, 193, 389, 769,
		        1543, 3079, 6151, 12289, 24593,
		        49157, 98317, 196613, 393241, 786433,
		        1572869, 3145739, 6291469, 12582917, 25165843,
		        50331653, 100663319, 201326611, 402653189, 805306457,
		        1610612741, 3221225473, 4294967291
            };
            const unsigned long* first=__stl_prime_list;
            const unsigned long* last=__stl_prime_list+__stl_num_primes;
            const unsigned long* pos=lower_bound(first,last,n);
            return pos==last?*(last-1):*pos;
        }
        bool Insert(const pair<K,V>& kv){
            //當(dāng)負(fù)載因子為1時,擴容
            if(_n==_tables.size()){
                //直接復(fù)用Insert,不好
                /*HashTable<K,V> newht;
                newht._tables.resize(_tables.size()*2);
                for(int i=0;i<_tables.size();i++){
                    Node* cur=_tables[i];
                    while(cur){
                        newht.Insert(cur);
                        cur=cur->_next;
                    }
                }
                _tables.swap(newht);*/
                HashTable<K,V> newht;
                newht._tables.resize(_tables.size()*2);
                //newht._tables.resize(__stl_next_prime(_tables.size()+1));
                for(int i=0;i<_tables.size();i++){
                    Node* cur=_tables[i];
                    while(cur){
                        Node* next=cur->_next;
                        size_t hash1=cur->_kv.first%newht._tables.size();
                        //頭插
                        cur->_next=newht[hash1];
                        newht[hash1]=cur;
                        cur=next;
                    }
                    _tables[i]=nullptr;
                }
                _tables.swap(newht);
            }
            //頭插
            size_t hash1=kv.first%_tables.size();
            Node* newNode=new Node(kv);
            newNode->next=_tables[hash1];
            _tables[hash1]=newNode;
            ++_n;
            return true;
        }
        Node* Find(const K& key){
            size_t hash0=key%_tables.size();
            Node* cur=_tables[hash0];
            while(cur){
                if(cur->_kv.first==key)
                    return cur;
                cur=cur->_next;
            }
            return nullptr;
        }
        bool Erase(const K& key){
            //沒有這個值
            if(!Find(key)) return false;
            size_t hash0=key%_tables.size();
            Node* cur=_tables[hash0];
            Node* prev=nullptr;
            while(cur){
                if(cur->_kv==key){
                    //刪除的節(jié)點是鏈表的頭
                    if(!prev){
                        _tables[hash0]=cur->_next;
                    }
                    else{
                        prev->_next=cur->_next;
                    }
                    delete cur;
                    --_n;
                    return true;
                }
                prev=cur;
                cur=cur->_next;
            }
            return false;
        }
    private:
        vector<HashNode<K,V>*> _tables;
        size_t _n;
    };
}

以上就是C++哈希表的實現(xiàn)思路剖析講解的詳細(xì)內(nèi)容,更多關(guān)于C++哈希表的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • C++ 超全面講解多態(tài)

    C++ 超全面講解多態(tài)

    這篇文章主要介紹了C++多態(tài)的原理與實現(xiàn),多態(tài)是一種面向?qū)ο蟮脑O(shè)計思路,本身和C++不是強綁定的,其他語言當(dāng)中一樣有多態(tài),只不過實現(xiàn)的方式可能有所不同。下面來一起了解更多詳細(xì)內(nèi)容吧
    2022-04-04
  • 詳解編譯器編譯原理

    詳解編譯器編譯原理

    這篇文章主要介紹了詳解編譯器編譯原理的相關(guān)資料,需要的朋友可以參考下
    2017-06-06
  • C語言中const和指針的秘密你知道嗎

    C語言中const和指針的秘密你知道嗎

    這篇文章主要為大家詳細(xì)介紹了C語言中const和指針的秘密,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
    2022-02-02
  • C++基礎(chǔ)知識實例解析(一)

    C++基礎(chǔ)知識實例解析(一)

    這篇文章主要對C++基礎(chǔ)知識實例解析,通過四個簡短的案例,鞏固大家的基礎(chǔ)知識,需要的朋友可以參考下
    2015-08-08
  • C++ new與malloc和delete及free動態(tài)內(nèi)存管理及區(qū)別介紹

    C++ new與malloc和delete及free動態(tài)內(nèi)存管理及區(qū)別介紹

    這篇文章主要介紹了深入理解C++中的new/delete和malloc/free動態(tài)內(nèi)存管理,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-12-12
  • C++詳解實現(xiàn)Stack方法

    C++詳解實現(xiàn)Stack方法

    C++ Stack(堆棧)是一個容器類的改編,為程序員提供了堆棧的全部功能,也就是說實現(xiàn)了一個先進后出(FILO)的數(shù)據(jù)結(jié)構(gòu)
    2022-06-06
  • C++常用函數(shù)總結(jié)(algorithm 頭文件)

    C++常用函數(shù)總結(jié)(algorithm 頭文件)

    本文給大家詳細(xì)介紹了algorithm 頭文件中最常用的函數(shù)及其使用方法,當(dāng)然這只是其中的一部分,algorithm 頭文件中還有很多其他的函數(shù),感興趣的朋友一起看看吧
    2023-12-12
  • C++實現(xiàn)LeetCode(21.混合插入有序鏈表)

    C++實現(xiàn)LeetCode(21.混合插入有序鏈表)

    這篇文章主要介紹了C++實現(xiàn)LeetCode(21.混合插入有序鏈表),本篇文章通過簡要的案例,講解了該項技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下
    2021-07-07
  • OpenCV利用背景建模檢測運動物體

    OpenCV利用背景建模檢測運動物體

    這篇文章主要為大家詳細(xì)介紹了OpenCV利用背景建模檢測運動物體,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-01-01
  • 詳解C語言fscanf函數(shù)讀取文件教程及源碼

    詳解C語言fscanf函數(shù)讀取文件教程及源碼

    這篇文章主要為大家介紹了詳解C語言算法fscanf讀取文件示例教程,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步
    2022-02-02

最新評論

沙洋县| 晋中市| 黄陵县| 建宁县| 普定县| 定边县| 湖南省| 绩溪县| 永川市| 巴东县| 吉首市| 塘沽区| 和静县| 永州市| 惠安县| 新宾| 鄂托克前旗| 赤城县| 垣曲县| 孝义市| 商洛市| 平舆县| 通许县| 长泰县| 清徐县| 冕宁县| 武夷山市| 襄汾县| 康保县| 青冈县| 洛隆县| 永和县| 区。| 驻马店市| 英吉沙县| 石门县| 蒙城县| 陆良县| 东港市| 盱眙县| 拉萨市|