这是我发送到 Perl Beginners 邮件列表的电子邮件的略微修改版本,回答了同样的问题。
说
my $hash_info = %hash;
将为您提供0(如果哈希为空)或用于的比率
总桶数。这些信息几乎,但不完全,
对你没用。要了解这意味着什么,您必须首先
了解散列的工作原理。
让我们使用 Perl 5 实现一个哈希。我们需要的第一件事是
哈希函数。散列函数将字符串转换成,希望,
唯一编号。真正的强散列函数的例子是
MD5 或 SHA1,但它们对于普通使用来说往往太慢了,所以
人们倾向于使用较弱的(即产生较少独特输出的那些)
哈希表的函数。 Perl 5 使用 Bob Jenkins [一次一个]
算法,它在唯一性和速度之间取得了很好的折衷。对于我们的
例如,我将使用一个非常弱的散列函数:
#!/usr/bin/perl
use strict;
use warnings;
sub weak_hash {
my $key = shift;
my $hash = 1;
#multiply every character in the string's ASCII/Unicode value together
for my $character (split //, $key) {
$hash *= ord $character;
}
return $hash;
}
for my $string (qw/cat dog hat/) {
print "$string hashes to ", weak_hash($string), "\n";
}
由于散列函数返回的数字范围大于我们想要的范围,因此您通常使用modulo 来缩小它给出的数字范围
返回:
#!/usr/bin/perl
use strict;
use warnings;
sub weak_hash {
my $key = shift;
my $hash = 1;
#multiply every character in the string's ASCII/Unicode value together
for my $character (split //, $key) {
$hash *= ord $character;
}
return $hash;
}
for my $string (qw/cat dog hat/) {
# the % operator is constraining the number
# weak_hash returns to 0 - 10
print "$string hashes to ", weak_hash($string) % 11, "\n";
}
现在我们有了一个散列函数,我们需要在某个地方保存密钥
和价值。这称为哈希表。哈希表通常是
其元素称为存储桶的数组(这些存储桶
比率正在谈论)。一个桶将保存所有的键/值
散列到相同数字的对:
#!/usr/bin/perl
use strict;
use warnings;
sub weak_hash {
my $key = shift;
my $hash = 1;
for my $character (split //, $key) {
$hash *= ord $character;
}
return $hash;
}
sub create {
my ($size) = @_;
my @hash_table;
#set the size of the array
$#hash_table = $size - 1;
return \@hash_table;
}
sub store {
my ($hash_table, $key, $value) = @_;
#create an index into $hash_table
#constrain it to the size of the hash_table
my $hash_table_size = @$hash_table;
my $index = weak_hash($key) % $hash_table_size;
#push the key/value pair onto the bucket at the index
push @{$hash_table->[$index]}, {
key => $key,
value => $value
};
return $value;
}
sub retrieve {
my ($hash_table, $key) = @_;
#create an index into $hash_table
#constrain it to the size of the hash_table
my $hash_table_size = @$hash_table;
my $index = weak_hash($key) % $hash_table_size;
#get the bucket for this key/value pair
my $bucket = $hash_table->[$index];
#find the key/value pair in the bucket
for my $pair (@$bucket) {
return $pair->{value} if $pair->{key} eq $key;
}
#if key isn't in the bucket:
return undef;
}
sub list_keys {
my ($hash_table) = @_;
my @keys;
for my $bucket (@$hash_table) {
for my $pair (@$bucket) {
push @keys, $pair->{key};
}
}
return @keys;
}
sub print_hash_table {
my ($hash_table) = @_;
for my $i (0 .. $#$hash_table) {
print "in bucket $i:\n";
for my $pair (@{$hash_table->[$i]}) {
print "$pair->{key} => $pair->{value}\n";
}
}
}
my $hash_table = create(3);
my $i = 0;
for my $key (qw/a b c d g j/) {
store($hash_table, $key, $i++);
}
print_hash_table($hash_table);
print "the a key holds: ", retrieve($hash_table, "a"), "\n";
从这个例子中我们可以看出,一个桶有可能有
比其他更多的键/值对。这是一个糟糕的情况
in. 它会导致该存储桶的哈希变慢。这是其中之一
使用哈希返回的已用桶与总桶的比率
标量上下文。如果哈希表明只有几个桶正在
用过,但它们是散列中的很多键,那么你知道你有一个
问题。
要了解有关哈希的更多信息,请在此处就我所说的内容提出问题,
或read about them。