• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            xiaoguozi's Blog
            Pay it forword - 我并不覺的自豪,我所嘗試的事情都失敗了······習(xí)慣原本生活的人不容易改變,就算現(xiàn)狀很糟,他們也很難改變,在過程中,他們還是放棄了······他們一放棄,大家就都是輸家······讓愛傳出去,很困難,也無法預(yù)料,人們需要更細(xì)心的觀察別人,要隨時注意才能保護(hù)別人,因?yàn)樗麄兾幢刂雷约阂裁础ぁぁぁぁ?/span>

            第一章 素?cái)?shù)判定法現(xiàn)狀

            現(xiàn)在,確定性素?cái)?shù)判定法已經(jīng)有很多種,常用的有試除法、威廉斯方法、艾德利曼和魯梅利法。它們的適用范圍各不相同,威廉斯方法比較適合10^2010^50之間的數(shù),艾德利曼和魯梅利法適合大于10^50的數(shù),對于32位機(jī)器數(shù),由于都小于10^10,所以一般都用試除法來判定。

            也許有人會問:“你為什么沒有提馬寧德拉.阿格拉瓦法呢?不是有人說它是目前最快的素?cái)?shù)判定法嗎?” 其實(shí)這是一個很大的誤解,阿格拉瓦法雖然是log(n)的多項(xiàng)式級算法,但目前只有理論上的意義,根本無法實(shí)用,因?yàn)樗臅r間復(fù)雜度是O(log(n)^12),這個多項(xiàng)式的次數(shù)太高了。就拿最慢的試除法跟它來比吧,試除法的時間復(fù)雜度為O(n^(1/2)*log(n)^2),當(dāng)n = 16時,log(n)^12 = 16777216,而n^(1/2)*log(n)^2 = 64,你看相差有多么大!如果要讓兩者速度相當(dāng),即log(n)^12 = n^(1/2)*log(n)^2,得出n = 10^43.1214,此時需要進(jìn)行的運(yùn)算次數(shù)為log(n)^12 = 10^25.873(注意:本文中log()函數(shù)缺省以2為底),這樣的運(yùn)算次數(shù)在一臺主頻3GHz的計(jì)算機(jī)上運(yùn)行也要10^8.89707年才能運(yùn)行完,看來我們這輩子是別指望看到阿格拉瓦法比試除法快的這一天啦!

            除了這些確定性素?cái)?shù)判定法外,還有基于概率的非確定性素?cái)?shù)判定法,最常用的就是米勒-拉賓法。

            對于32位機(jī)器數(shù)(四則運(yùn)算均為常數(shù)時間完成),試除法的時間復(fù)雜度是O(n^(1/2)),而米勒-拉賓法的時間復(fù)雜度只有O(log(n))。所以后者要比前者快得多,但是由于米勒-拉賓法的非確定性,往往我們在需要確定解時仍然要依靠速度較慢的試除法。那是否可以通過擴(kuò)展米勒-拉賓法,來找到一種更快的確定性素?cái)?shù)判定法呢?結(jié)論是肯定的,本文就帶你一起尋找這樣一種方法。

            第二章 2-偽素?cái)?shù)表的生成

            既然要擴(kuò)展米勒-拉賓法,那首先我們應(yīng)該知道為什么米勒-拉賓法是個非確定性素?cái)?shù)判定法?答案很簡單,由于偽素?cái)?shù)的存在。由于米勒-拉賓法使用費(fèi)爾馬小定理的逆命題進(jìn)行判斷,而該逆命題對極少數(shù)合數(shù)并不成立,從而產(chǎn)生誤判,這些使費(fèi)爾馬小定理的逆命題不成立的合數(shù)就是偽素?cái)?shù)。為了研究偽素?cái)?shù),我們首先需要生成偽素?cái)?shù)表,原理很簡單,就是先用篩法得出一定范圍內(nèi)的所有素?cái)?shù),然后逐一判定該范圍內(nèi)所有合數(shù)是否使以2為底數(shù)的費(fèi)爾馬小定理的逆命題不成立,從而得出該范圍內(nèi)的2-偽素?cái)?shù)表。我的程序運(yùn)行了100分鐘,得出了32位機(jī)器數(shù)范圍內(nèi)的2-偽素?cái)?shù)表,如下:

            341

            561

            645

            1105

            1387

            1729

            1905

            2047

            2465

            2701

            ...

            ...

            ...

            4286813749

            4288664869

            4289470021

            4289641621

            4289884201

            4289906089

            4293088801

            4293329041

            4294868509

            4294901761

            (共10403個,由于篇幅所限,中間部分省略。)

            第三章 尋找2-偽素?cái)?shù)的最小可判定底數(shù)

            對于2-偽素?cái)?shù)表的每一個偽素?cái)?shù),尋找最小的可以判定它們是合數(shù)的底數(shù),我把這個底數(shù)稱之為最小可判定底數(shù)。特別地,對于絕對偽素?cái)?shù),它的最小質(zhì)因子即是它的最小可判定底數(shù)。由于已經(jīng)證明了絕對偽素?cái)?shù)至少有三個質(zhì)因子,所以這個最小質(zhì)因子一定不大于n^(1/3)。下面就是我找到的最小可判定底數(shù)列表:

            341     3

            561     3

            645     3

            1105    5

            1387    3

            1729    7

            1905    3

            2047    3

            2465    5

            2701    5

            ...

            ...

            ...

            4286813749      3

            4288664869      3

            4289470021      5

            4289641621      3

            4289884201      3

            4289906089      3

            4293088801      3

            4293329041      3

            4294868509      7

            4294901761      3

            通過統(tǒng)計(jì)這個列表,我發(fā)現(xiàn)了一個規(guī)律,那就是所有的最小可判定底數(shù)都不大于n^(1/3),由前述可知,對于絕對偽素?cái)?shù),這個結(jié)論顯然成立。而對于非絕對偽素?cái)?shù),雖然直觀上覺得它應(yīng)該比絕對偽素?cái)?shù)好判定出來,但是我無法證明出它的最小可判定底數(shù)都不大于n^(1/3)。不過沒關(guān)系,這個問題就作為一個猜想留給數(shù)學(xué)家來解決吧,更重要的是我已經(jīng)通過實(shí)驗(yàn)證明了在32位機(jī)器數(shù)范圍內(nèi)這個結(jié)論成立。

            我們還有沒有更好的方法來進(jìn)一步減小最小可判定底數(shù)的范圍呢?有的!我們可以在計(jì)算平方數(shù)時進(jìn)行二次檢測,下面是進(jìn)行了二次檢測后重新計(jì)算的最小可判定底數(shù)列表:

            341     2

            561     2

            645     2

            1105    2

            1387    2

            1729    2

            1905    2

            2047    3

            2465    2

            2701    2

            ...

            ...

            ...

            4286813749      2

            4288664869      2

            4289470021      2

            4289641621      2

            4289884201      2

            4289906089      2

            4293088801      2

            4293329041      2

            4294868509      2

            4294901761      3

            很顯然,二次檢測是有效果的,經(jīng)過統(tǒng)計(jì),我發(fā)現(xiàn)了新的規(guī)律,那就是經(jīng)過二次檢測后所有的最小可判定底數(shù)都不大于n^(1/6),真的是開了一個平方呀,哈哈!這個結(jié)論的數(shù)學(xué)證明仍然作為一個猜想留給數(shù)學(xué)家們吧。我把這兩個猜想叫做費(fèi)爾馬小定理可判定上界猜想。而我已經(jīng)完成了對32位機(jī)器數(shù)范圍內(nèi)的證明。

            通過上面總結(jié)的規(guī)律,我們已經(jīng)可以設(shè)計(jì)出一個對32位機(jī)器數(shù)進(jìn)行素?cái)?shù)判定的 O(n^(1/6)*log(n)) 的確定性方法。但是這還不夠,我們還可以優(yōu)化,因?yàn)榇藭r的最小可判定底數(shù)列表去重后只剩下了5個數(shù)(都是素?cái)?shù)):{2,3,5,7,11}。天哪,就是前5個素?cái)?shù),這也太容易記憶了吧。

            不過在實(shí)現(xiàn)算法時,需要注意這些結(jié)論都是在2-偽素?cái)?shù)表基礎(chǔ)上得來的,也就是說不管如何對2的判定步驟必不可少,即使當(dāng)2>n^(1/6)時。

            還有一些優(yōu)化可以使用,經(jīng)過實(shí)驗(yàn),當(dāng)n>=7^6時,可以不進(jìn)行n^(1/6)上界限制,而固定地用{2,5,7,11}去判定,也是100%正確的。這樣就可以把判定次數(shù)降為4次以下,而每次判定只需要進(jìn)行4log(n)次乘除法(把取余運(yùn)算也看作除法),所以總的計(jì)算次數(shù)不會超過16log(n)。經(jīng)過實(shí)驗(yàn),最大的計(jì)算次數(shù)在n=4294967291時出現(xiàn),為496次。


            自己寫了個隨機(jī)化素?cái)?shù)判定算法:
             1 #include <iostream>
             2 #include <cmath>
             3 #include <algorithm>
             4 
             5 using namespace std;
             6 typedef unsigned __int64 longlong_t;
             7 
             8 bool _IsLikePrime(longlong_t n, longlong_t base)
             9 {
            10     longlong_t power = n-1;
            11     longlong_t result = 1;
            12     longlong_t x = result;
            13     longlong_t bits = 0;
            14     longlong_t power1 = power;
            15     //統(tǒng)計(jì)二進(jìn)制位數(shù)
            16     while (power1 > 0)
            17     {
            18         power1 >>= 1;
            19         bits++;
            20     }
            21     //從高位到低位依次處理power的二進(jìn)制位
            22     while(bits > 0)
            23     {
            24         bits--;
            25         result = (x*x)%n;
            26         //二次檢測
            27         if(result==1&&x!=1&&x!=n-1)
            28             return false;
            29 
            30         if ((power&((longlong_t)1<<bits)) != 0)
            31             result = (result*base)%n;
            32 
            33         x = result;
            34     }
            35     //費(fèi)爾馬小定理逆命題判定
            36     return result == 1;
            37 }
            38 inline bool JudgePrime(int n,int s)
            39 {
            40     srand(20);
            41     for(int i=0;i<s;i++){
            42         int a=rand()%(n-1)+1;
            43         if(!_IsLikePrime(n,a))
            44             return false;
            45     }
            46     return true;
            47 }
            48 int main()
            49 {
            50     int n;
            51     while(scanf("%d",&n)!=EOF){
            52         int num=0;
            53         int cnt=0;
            54         for(int i=0;i<n;i++){
            55             scanf("%d",&num);
            56             if(JudgePrime(num,20))
            57                 cnt++;
            58         }
            59         printf("%d\n",cnt);
            60     }
            61     return 0;
            62 }
            s越大,穩(wěn)定性越好,但效率會低點(diǎn)。原作者有更好的判定算法,對作者表示感謝。。
            posted @ 2008-01-26 09:37 小果子 閱讀(1202) | 評論 (0)編輯 收藏
             1#include <iostream>
             2#include <string>
             3#include <algorithm>
             4#include <hash_map>
             5
             6using namespace std;
             7
             8struct hashable{
             9    string i;
            10    hashable(string iv):i(iv){}
            11    operator size_t()const{
            12        int ret=i.size();
            13        for(int k=0;k!=i.size();++k){
            14            ret*=10;
            15            ret+=i[k]-'A';
            16        }

            17        return ret;
            18    }

            19    bool operator< (hashable r)const {
            20        return i<r.i;
            21    }

            22}
            ;
            23int main()
            24{
            25    hash_map<hashable,string> hm;
            26    hashable a("1");
            27    hm[a]="T";
            28    cout<<hm[a]<<endl;
            29}
            對自定義類型到string的示例
            posted @ 2008-01-26 09:20 小果子 閱讀(282) | 評論 (0)編輯 收藏

             

            Reference Type  Pointer Type

            所謂左值(lValue):是用來代表某個對象的一個東西。如果p是指向類型為T的某個對象,那么表達(dá)式*p不能只是返回類型為T的對象,而必須是返回一個lValue(左值)。

               平時總是拿起*p就直接賦值(對于簡單基本類型,例如int *p = &I ;  *p=3),沒想什么*p返回左值那么多。但是當(dāng)在自定義類中重栽*運(yùn)算符的時候,我們就要特別小心,要注意到這點(diǎn),返回為T& 才對。

            言規(guī)正傳

            iterator_traits的某些機(jī)制所蘊(yùn)涵的意義十分微妙而深遠(yuǎn),不過它的實(shí)現(xiàn)卻不是很復(fù)雜,不過這些東西看起來比較容易看懂,真正能夠靈活使用就需要花時間領(lǐng)悟了,為什么會采取這種方法解決問題,和其它的方法對比有什么好處和提高?這種明白這些問題才算掌握了trait的實(shí)質(zhì)。

            template< class Iterator>

            struct iterator_traits

            {

            typedef   typename Iterator::iterator_category   iterator_category;

            typedef   typename Iterator::value_type        value_type;

            typedef   typename Iterator::difference_type    difference_type;

            typedef   typename Iterator::pointer           pointer;

            typedef   typename Iterator::reference         reference    ;

            };

            template< class T>

            struct iterator_traits

            {

            typedef   random_access_iterator_tag   iterator_category;

            typedef   T        value_type;

            typedef   ptrdiff_t    difference_type;

            typedef   T*           pointer;

            typedef   T&         reference    ;

            };

            template< class T>

            struct iterator_traits

            {

            typedef   random_access_iterator_tag   iterator_category;

            typedef   T        value_type;

            typedef   ptrdiff_t    difference_type;

            typedef   T*           pointer;

            typedef   T&         reference    ;

            };

            當(dāng)你定義一個自己的算法,你需要關(guān)注這個機(jī)制,下面兩個理由就是你可能要用到iterator_traits

                 你必須返回某值,或者是申明臨時變量,而其它型別與iteratorvalue type 或者different type或者reference type 或者pointer type一致。

                 你的算法類似與advance,必須根據(jù)iterator的分類來決定不同的實(shí)現(xiàn)方法(提高效率,在編譯時候進(jìn)行判斷而不是在運(yùn)行的時候進(jìn)行判斷),沒有traits機(jī)制,你只好在‘一般化但是沒效率’或者‘有效率但是過度狹隘’中進(jìn)行抉擇。

            當(dāng)定義一個Iterator 類,就得在改類中定義五個嵌套的類型,如上面的五個所示。要不然就得針對你的Iterator類,明白的令iterator_traitsIterator特化,就像iterator_traits要明白的針對指針而特化一樣。第一種做法總是比較簡單,尤其是STL的一個輔助類,base class iterator,讓事情變得更簡單了。

            template< class Category,

            class Value,

            class Distance =ptrdiff_t,

            class Pointer = Value*,

            class Reference = Value &

            >

            struct iterator

            {

            typedef Category iterator_category;

            typedef Value      value_type;

            typedef Distance difference_type;

            typedef Pointer     pointer;

            typedef Reference   reference;

            };

                 為了確保iterator_traits能夠?qū)π碌?/span>iterator class有適當(dāng)?shù)亩x,最簡單的方法就是從iterator類派生自己的iterator?;?/span>iterator不含任何成員函數(shù)和成員變量,所以繼承不存在額外的開銷。

            posted @ 2008-01-13 11:34 小果子 閱讀(1933) | 評論 (1)編輯 收藏

            說來慚愧,使用了很久Visual Stdio 2003了,只知道MFC升級到了7.0,ATL也升級到了7.0,對于這兩個經(jīng)典的類庫做了一些研究,但一直沒有注意C++標(biāo)準(zhǔn)庫的變化。

                 今天嘗試的使用了stdext::hash_map這個庫,果然不錯。下面寫下一些心得。

                 hash_map類在頭文件hash_map中,和所有其它的C++標(biāo)準(zhǔn)庫一樣,頭文件沒有擴(kuò)展名。如下聲明:

                      #include <hash_map>
                      using namespace std;
                      using namespace stdext;

                 hash_map是一個聚合類,它繼承自_Hash類,包括一個vector,一個list和一個pair,其中vector用于保存桶,list用于進(jìn)行沖突處理,pair用于保存key->value結(jié)構(gòu),簡要地偽碼如下:

                      class hash_map<class _Tkey, class _Tval>
                      {
                      private:
                           typedef pair<_Tkey, _Tval> hash_pair;
                           typedef list<hash_pair>    hash_list;
                           typedef vector<hash_list>  hash_table;
                      };

                 當(dāng)然,這只是一個簡單模型,C++標(biāo)準(zhǔn)庫的泛型模版一向以嵌套復(fù)雜而聞名,初學(xué)時看類庫,無疑天書啊。微軟的hash_map類還聚合了hash_compare仿函數(shù)類,hash_compare類里有聚合了less仿函數(shù)類,亂七八糟的。

                 下面說說使用方法:

                 一、簡單變量作為索引:整形、實(shí)性、指針型
                 其實(shí)指針型也就是整形,算法一樣。但是hash_map會對char*, const char*, wchar_t*, const wchar_t*做特殊處理。
                 這種情況最簡單,下面代碼是整形示例:
                        hash_map<int, int> IntHash;
                        IntHash[1] = 123;
                        IntHash[2] = 456;

                        int val = IntHash[1];
                        int val = IntHash[2];
                 實(shí)型和指針型用法和整形一樣,原理如下:
                 1、使用簡單類型作索引聲明hash_map的時候,不需要聲明模版的后兩個參數(shù)(最后一個參數(shù)指名hash_map節(jié)點(diǎn)的存儲方式,默認(rèn)為pair,我覺得這就挺好,沒必要修改),使用默認(rèn)值就好。
                 2、對于除過字符串的其它簡單類型,hash_map使用模版函數(shù) size_t hash_value(const _Kty& _Keyval) 計(jì)算hash值,計(jì)算方法是經(jīng)典的掩碼異或法,自動溢出得到索引hash值。微軟的工程師也許開了一個玩笑,這個掩碼被定義為0xdeadbeef(死牛肉,抑或是某個程序員的外號)。
                 3、對于字符串指針作索引的時候,使用定類型函數(shù)inline size_t hash_value(const char *_Str)或inline size_t hash_value(const wchar_t *_Str)計(jì)算hash值,計(jì)算方法是取出每一個字符求和,自動溢出得到hash值。對于字符串型的hash索引,要注意需要自定義less仿函數(shù)。
                 因?yàn)槲覀冇欣碛烧J(rèn)為,人們使用hash表進(jìn)行快速查找的預(yù)期成本要比在hash表中插入的預(yù)期成本低得多,所以插入可以比查找昂貴些;基于這個假設(shè),hash_map在有沖突時,插入鏈表是進(jìn)行排序插入的,這樣在進(jìn)行查詢沖突解決的時候就能夠更快捷的找到需要的索引。
                 但是,基于泛型編程的原則,hash_map也有理由認(rèn)為每一種類型都支持使用"<"來判別兩個類型值的大小,這種設(shè)計(jì)恰好讓字符串類型無所適從,眾所周知,兩個字符串指針的大小并不代表字符串值的大小。見如下代碼:
                      hash_map<const char*, int> CharHash;
                      CharHash["a"] = 123;
                      CharHash["b"] = 456;

                      char szInput[64] = "";
                      scanf("%s", szInput);

                      int val = CharHash[szInput];

                 最終的結(jié)果就是無論輸入任何字符串,都無法找到對應(yīng)的整數(shù)值。因?yàn)檩斎氲淖址羔樖莝zInput指針,和"a"或"b"字符串常量指針的大小是絕對不會相同。解決方法如下:
                 首先寫一個仿函數(shù)CharLess,繼承自仿函數(shù)基類binary_function(當(dāng)然也可以不繼承,這樣寫只是符合標(biāo)準(zhǔn),而且寫起來比較方便,不用被類似于指針的指針和指針的引用搞暈。

                      struct CharLess : public binary_function<const char*, const char*, bool>
                      {
                      public:
                           result_type operator()(const first_argument_type& _Left, const second_argument_type& _Right) const
                           {
                                return(stricmp(_Left, _Right) < 0 ? true : false);
                           }
                      };

                 很好,有了這個仿函數(shù),就可以正確的使用字符串指針型hash_map了。如下:

                      hash_map<const char*, int, hash_compare<const char*, CharLess> > CharHash;
                      CharHash["a"] = 123;
                      CharHash["b"] = 456;

                      char szInput[64] = "";
                      scanf("%s", szInput);

                      int val = CharHash[szInput];
                 
                 現(xiàn)在就可以正常工作了。至此,簡單類型的使用方法介紹完畢。

                 二、用戶自定義類型:比如對象類型,結(jié)構(gòu)體。
                 這種情況比價復(fù)雜,我們先說簡單的,對于C++標(biāo)準(zhǔn)庫的string類。
                 
                 慶幸的是,微軟為basic_string(string類的基類)提供了hash方法,這使得使用string對象做索引簡單了許多。值得注意(也值得郁悶)的是,雖然支持string的hash,string類卻沒有重載比較運(yùn)算符,所以標(biāo)準(zhǔn)的hash_compare仿函數(shù)依舊無法工作。我們繼續(xù)重寫less仿函數(shù)。
                     
                      struct string_less : public binary_function<const string, const string, bool>
                      {
                      public:
                           result_type operator()(const first_argument_type& _Left, const second_argument_type& _Right) const
                           {
                                return(_Left.compare(_Right) < 0 ? true : fase);
                           }
                      };
                       
                 好了,我們可以書寫如下代碼:
                       
                      hash_map<string, int, hash_compare<string, string_less> > StringHash;
                      StringHash["a"] = 123;
                      StringHash["b"] = 456;

                      string strKey = "a";

                      int val = CharHash[strKey];
                 
                 這樣就可以了。
                 
                 對于另外的一個常用的字符串類CString(我認(rèn)為微軟的CString比標(biāo)準(zhǔn)庫的string設(shè)計(jì)要灑脫一些)更加復(fù)雜一些。很顯然,標(biāo)準(zhǔn)庫里不包含對于CString的支持,但CString卻重載了比較運(yùn)算符(郁悶)。我們必須重寫hash_compare仿函數(shù)。值得一提的是,在Virtual Stdio 2003中,CString不再是MFC的成員,而成為ATL的成員,使用#include <atlstr.h>就可以使用。我沒有采用重寫hash_compare仿函數(shù)的策略,而僅僅是繼承了它,在模版庫中的繼承是沒有性能損耗的,而且能讓我偷一點(diǎn)懶。
                 首先重寫一個hash_value函數(shù):
                 
                      inline size_t CString_hash_value(const CString& str)
                      {
                           size_t value = _HASH_SEED;
                           size_t size  = str.GetLength();
                           if (size > 0) {
                                size_t temp = (size / 16) + 1;
                                size -= temp;
                                for (size_t idx = 0; idx <= size; idx += temp) {
                                     value += (size_t)str[(int)idx];
                                }
                           }
                           return(value);
                      }
                 
                 其次重寫hash_compare仿函數(shù):
                 
                      class CString_hash_compare : public hash_compare<CString>
                      {
                      public:
                           size_t operator()(const CString& _Key) const
                           {
                                return((size_t)CString_hash_value(_Key));
                           }
              
                           bool operator()(const CString& _Keyval1, const CString& _Keyval2) const
                           {
                                return (comp(_Keyval1, _Keyval2));
                           }
                      };
                       
                 上面的重載忽略了基類對于less仿函數(shù)的引入,因?yàn)镃String具備比較運(yùn)算符,我們可以使用默認(rèn)的less仿函數(shù),在這里映射為comp。好了,我們可以聲明新的hash_map對象如下:

                      hash_map<CString, int, CString_hash_compare> CStringHash;

                 其余的操作一樣一樣的。

                 下來就說說對于自定義對象的使用方法:首先定義
                 
                      struct IHashable
                      {
                           virtual unsigned long hash_value() const = 0;
                           virtual bool operator < (const IHashable& val) const = 0;
                           virtual IHashable& operator = (const IHashable& val) = 0;
                      };
                 
                 讓我們自寫的類都派生自這里,有一個標(biāo)準(zhǔn),接下來定義我們的類:
                 
                      class CTest : public IHashable
                      {
                      public:
                           int m_value;
                           CString m_message;
                      public:
                           CTest() : m_value(0)
                           {
                           }
                       
                           CTest(const CTest& obj)
                           {
                                m_value = obj.m_value;
                                m_message = obj.m_message;
                           }
                      public:
                           virtual IHashable& operator = (const IHashable& val)
                           {
                                m_value   = ((CTest&)val).m_value;
                                m_message = ((CTest&)val).m_message;
                                return(*this);
                           }
                       
                           virtual unsigned long hash_value() const
                           {
                                // 這里使用類中的m_value域計(jì)算hash值,也可以使用更復(fù)雜的函數(shù)計(jì)算所有域總的hash值
                                return(m_value ^ 0xdeadbeef 
                           }
                       
                           virtual bool operator < (const IHashable& val) const
                           {
                                return(m_value < ((CTest&)val).m_value);
                           }
                      };
                 
                 用這個類的對象做為hash索引準(zhǔn)備工作如下,因?yàn)榻涌谥幸?guī)定了比較運(yùn)算符,所以這里可以使用標(biāo)準(zhǔn)的less仿函數(shù),所以這里忽略:
                 
                      template<class _Tkey>
                      class MyHashCompare : public hash_compare<_Tkey>
                      {
                      public:
                           size_t operator()(const _Tkey& _Key) const
                           {
                                return(_Key.hash_value());
                           }
                       
                           bool operator()(const _Tkey& _Keyval1, const _Tkey& _Keyval2) const
                           {
                                return (comp(_Keyval1, _Keyval2));
                           }
                      };
                       
                 下來就這樣寫:
                 
                      CTest test;
                      test.m_value = 123;
                      test.m_message = "This is a test";
                 
                      MyHash[test] = 2005;
                       
                      int val = MyHash[test];
                 
                 可以看到正確的數(shù)字被返回。
                 
                 三、關(guān)于hash_map的思考:
                 
                 1、性能分析:采用了內(nèi)聯(lián)代碼和模版技術(shù)的hash_map在效率上應(yīng)該是非常優(yōu)秀的,但我們還需要注意如下幾點(diǎn):
                 
                 * 經(jīng)過查看代碼,字符串索引會比簡單類型索引速度慢,自定義類型索引的性能則和我們選擇hash的內(nèi)容有很大關(guān)系,簡單為主,這是使用hash_map的基本原則。
                 * 可以通過重寫hash_compair仿函數(shù),更改里面關(guān)于桶數(shù)量的定義,如果取值合適,也可以得到更優(yōu)的性能。如果桶數(shù)量大于10,則牢記它應(yīng)該是一個質(zhì)數(shù)。
                 * 在自定義類型是,重載的等號(或者拷貝構(gòu)造)有可能成為性能瓶頸,使用對象指針最為索引將是一個好的想法,但這就必須重寫less仿函數(shù),理由同使用字符串指針作為索引。

            posted @ 2008-01-12 18:31 小果子 閱讀(9692) | 評論 (0)編輯 收藏

                    想自己開始學(xué)語言的時候,因?yàn)楦静恢朗裁磿?,所以看到基本是一些國?nèi)的,水平一般的書,如果你剛開始學(xué)c or c++,推薦c++創(chuàng)始人寫的<<the c++ programming language>>,即使是學(xué)有所成的人,再看此書也有很大收獲我想,慢慢品味,會有收獲的。。。以后我會將自己學(xué)習(xí)此書的筆記寫在此,各位路過的大牛指點(diǎn)指點(diǎn)。。。^_^

            posted @ 2007-12-15 23:22 小果子 閱讀(222) | 評論 (0)編輯 收藏
            僅列出標(biāo)題
            共58頁: First 50 51 52 53 54 55 56 57 58 
            伊人久久综合热线大杳蕉下载| 久久青青国产| 亚洲人成无码久久电影网站| 久久久黄片| 观看 国产综合久久久久鬼色 欧美 亚洲 一区二区 | 色综合久久88色综合天天| 久久久久久午夜成人影院 | 99久久精品午夜一区二区| 7777精品久久久大香线蕉| 四虎影视久久久免费观看| 手机看片久久高清国产日韩| 久久久精品波多野结衣| 狠狠久久综合| 伊人久久大香线蕉AV一区二区| 精品久久久久一区二区三区 | 国内精品久久久久影院日本| 久久综合给久久狠狠97色| 久久久免费精品re6| 99久久99久久久精品齐齐| 久久综合欧美成人| 欧美粉嫩小泬久久久久久久 | 亚洲精品无码久久毛片| 久久99九九国产免费看小说| 2021国产精品久久精品| 人妻久久久一区二区三区| 国内精品九九久久久精品| 91精品观看91久久久久久| 少妇久久久久久被弄到高潮| 久久精品国产乱子伦| 久久精品九九亚洲精品天堂| 精品乱码久久久久久夜夜嗨| 性做久久久久久久久久久| 99久久99久久久精品齐齐 | 性做久久久久久久久久久| 精品国产乱码久久久久软件| 久久久久久久久久久久中文字幕 | 国产一区二区精品久久| 人妻无码久久精品| 久久久精品2019免费观看| 亚州日韩精品专区久久久| 97久久精品国产精品青草|