用于唯一元素存储的数据结构



我正在寻找一个数据结构,它最好执行相等的O(1)?在添加/删除/检索元素时,针对任意数量的元素。

以下是一些附加指南,

  • 检索元素不应涉及慢速keys()
  • 元素必须始终是唯一的并已定义
  • 元素顺序不重要
  • 元素的添加或删除不应涉及对其他元素的迭代
  • 检索到的元素列表中的间隙是可容忍的,并且可以用undef值表示

请提出比更好的解决方案

sub uniqArrayFactory {
  my $members = [];
  my $seen = {};
  my $gaps = [];
  return sub {
    my (%arg) = @_;
    return $members if $arg{members};
    my $m;
    if (defined ($m = $arg{del})) {
      return if !$seen->{$m};
      ${ $seen->{$m} } = undef;
      push @$gaps, delete($seen->{$m});
    }
    elsif (defined ($m = $arg{add})) {
      return if $seen->{$m};
      if (@$gaps) {
        $seen->{$m} = pop @$gaps;
        ${ $seen->{$m} } = $m;
      }
      else {
        push @$members, $m;
        $seen->{$m} = ( $members->[-1] );
      }
    }
    return $m;
  };
}

更新(用法)

my $fa = uniqArrayFactory();
$fa->(add => 10);
$fa->(del => 10);
my $members = $fa->(mebers => 1);

keyseach确实慢得令人惊讶。但是,如果您将每个元素存储为哈希值,并使用values,事情会更快地降低。带

use strict;
use warnings;
use Benchmark qw(:all);
my $i;
my $fa;
my %hash;
my %compare = (
  uarray => sub {
    $fa->(add => $i++);
    my $memb = $fa->(members => 1);
    for my $v (@$memb) { next if !defined $v; }
  },
  hash => sub {
    $hash{ $i } = $i;
    for my $v (values %hash) {}
    $i++;
  },
);
$i = 0; $fa = uniqArrayFactory(); %hash = ();
cmpthese(10000, %compare);
sub uniqArrayFactory {
  my $members = [];
  my $seen = {};
  my $gaps = [];
  return sub {
    my (%arg) = @_;
    return $members if exists $arg{members};
    my $m;
    if (defined ($m = $arg{del})) {
      return if !$seen->{$m};
      ${ $seen->{$m} } = undef;
      push @$gaps, delete($seen->{$m});
    }
    elsif (defined ($m = $arg{add})) {
      return if $seen->{$m};
      if (@$gaps) {
        $seen->{$m} = pop @$gaps;
        ${ $seen->{$m} } = $m;
      }
      else {
        push @$members, $m;
        $seen->{$m} = ( $members->[-1] );
      }
    }
    return $m;
  };
}

我得到:

         Rate   hash uarray
hash   3205/s     --    -6%
uarray 3401/s     6%     --

具有讽刺意味的是,Tie::IxHash的动机可能是希望按指定顺序检索哈希的密钥,但它可能与您想要的一样接近。

Tie::IxHash实现中,键和值存储在数组引用中。keys返回一组密钥的副本,但类似(tied %hash)->[1]的东西会让你直接访问它

Tie::IxHash中移除元素是O(n)。一个可能的解决方法是用undef替换值,而不是删除它们。也就是说,更喜欢

$ixhash{$obsolete_key} = undef;

delete $ixhash{$obsolete_key};

或者,如果您能够集中删除内容——如果您能够组织代码,使您通常在同一时间对多个键调用delete,并在对哈希的其他操作之间调用——那么就有机会改进Tie::IxHash

相关内容

  • 没有找到相关文章

最新更新