揭秘Perl關聯數組和哈希表聯系
本文和大家重點討論一下Perl關聯數組和哈希表的概念,Perl關聯數組,又稱為哈希表(hashtable),是一種非常好用的數據結構。希望通過本文的介紹你對Perl關聯數組的概念有深入的了解。
Perl關聯數組和哈希表
Perl關聯數組,又稱為哈希表(hashtable),是一種非常好用的數據結構。
在程序中,我們可能會遇到需要消重的問題,舉一個最簡單的模型:
有一份用戶名列表,存儲了10000個用戶名,沒有重復項;
還有一份黑名單列表,存儲了2000個用戶名,格式與用戶名列表相同;
現在需要從用戶名列表中刪除處在黑名單里的用戶名,要求用盡量快的時間處理。
這個問題是一個小規模的處理量,如果實際一點,2個表都可能很大,比如有2億條記錄。
我最開始想到的方法,就是做一個嵌套的循環,設用戶名表有M條記錄,黑名單列表有N條記錄,那么,循環的次數是M*N次!
PHP版代碼:
- <?php
- foreach($arrayMas$keyM=>$nameM){
- foreach($arrayNas$nameN){
- if($nameM==$nameN){
- //本行執行了M*N次!
- unset($arrayM[$keyM]);
- }
- }
- }
- return$arrayM;
- ?>
另一種方式,利用數組索引。
PHP是一種弱類型的語言,不像C語言那樣有嚴格的變量類型限制。C語言的數組,每一個元素的類型必須一致,而且索引都是從0開始。
PHP的數組,可以用字符串作為索引,也稱為Perl關聯數組。
數組索引,有一個天然的限制就是不會重復,而且訪問的時候不需要查找,可以直接定位。
還是剛才的那個問題,我們采用另一種辦法。
把黑名單列表的用戶名組織到一個數組里,數組的索引就是用戶名。
然后,遍歷用戶列表的時候,只需直接用isset查詢那個用戶名是否存在即可。
PHP版代碼:
- <?php
- $arrayarrayHash=array();
- foreach($arrayNas$nameN){
- //本行執行了N次。
- $arrayHash[$nameN]=1;
- }
- foreach($arrayMas$keyM=>$nameM){
- if(isset($arrayHash[$nameM])){
- //本行執行了M次!
- unset($arrayM[$keyM]);
- }
- }
- return$arrayM;
- ?>
可以看到,優化過的代碼,循環次數是M+N次。
假如M和N都是10000,優化前,循環了1億次;優化后,只循環了20000次,差了5000倍!
如果第二個程序耗時1秒,則第一個程序需要將近一個半小時!
最近在做Perl的開發,Perl在處理文本的時候有很高的效率,同樣,它也支持Perl關聯數組!
只是語法和PHP的那種類C的方式有很大不同,以第二段代碼為例,Perl版的實現:
- #!/usr/bin/perl
- my%arrayHash;
- for(my$i=0;$i<@arrayN;++$i){
- $arrayHash{$arrayN[$i]}=1;
- }
- for(my$i=0;$i<@arrayM;++$i){
- if($arrayHash{$arrayM[$i]}){
- $arrayM[$i]=undef;
- }
- }
Perl關聯數組是@開頭,哈希是以%開頭,unset實際上就是undef。
Perl的哈希和數組都是有具體類型的,而且向函數傳遞變量的時候要傳引用,我剛學時間不長,快被搞暈了。
不過,現在剛剛實現了一個以hash方式進行IP位置查找的算法,平均比較次數大概在3次左右,比傳統的折半查找方式少了很多次,它大概需要8次以上的比較。
剛剛做了一個小的性能測試,對10萬個IP進行查找,在我的臺式機上,耗時15秒,平均每秒7500次,感覺還不錯,呵呵。不過,還是喜歡PHP的數組,真的很強大 。