gpt4 book ai didi

algorithm - 是否有任何保留位置的方法来展平二叉树?

转载 作者:塔克拉玛干 更新时间:2023-11-03 03:13:45 24 4
gpt4 key购买 nike

简短版:

It is possible将 2D 空间展平为 1D 空间,这样如果 2D 空间上的 2 个点靠得很近,那么它们到 1D 的映射也将靠得很近。同样,有没有什么方法可以将二叉树中的任意位置映射到数组中的平面索引,这样如果两个节点在树上靠得很近,那么它们在数组中也会靠得很近?


长版:

Tree 为标记二叉树的类型。

               A 
/ \
B C
/ \ / \
D E F G
/ \ / \ / \ / \
H I J K L M N O

中的位置可以由位串给出,其中0表示向左走1 表示向右走,空字符串是root (A)。例如,011 指向上面树上的K。此外,设两个节点之间的距离 为从一个节点到另一个节点所需的步数。

什么是从节点位置(位串)到自然数的 F::BitString -> Nat 映射,如果 distance(A, B) 很小,则|F(A) - F(B)| 小吗?

最佳答案

我认为TilmannZ's answer (它使用中缀排序)已经差不多了。考虑二叉树中的每个节点,除了根之外,都有三个邻居,并且在一维内存布局中,实际上只有两个可以相距 1。此外,没有想到很多其他有用的顺序。

我写了一个小Perl script它将默认排序与深度优先前缀排序和中缀排序进行比较。您可以在 Gnuplot 处输出输出获得以下情节(编辑:包括 van-Emde-Boas 布局): plot showing the memory locality of different node orderings

您可以看到原始排序对于小树距离的局部性相对较差,前缀排序和中缀排序都更好。不过,中缀排序产生了三者中最好的行为(例如,树距离为 3 的节点平均相隔 6 个内存索引)。它也是一条几乎是线性的曲线,这应该是一个很好的指标,表明你不能做得更好。 V.E.B.根据您的距离标准,评论中提到的布局至少对于较小的节点距离而言效果不佳。

为了完整起见,这是我使用的(有点快速和肮脏的)脚本:

#!/usr/bin/perl
# Compares node distances in memory for different layouts of the following
# binary tree:
# A
# / \
# B C
# / \ / \
# D E F G
# / \ / \ / \ / \
# H I J K L M N O
# / \ / \ / \ / \ / \ / \ / \ / \
# P Q R S T U V W X Y Z 0 1 2 3 4

# Calculates the real node distance.
sub dist($$)
{
my ($i, $j) = @_;
return 0 if ($i == $j);
($j,$i) = ($i,$j) if ($i > $j);
# $i<$j. Go one up from the larger node.
return 1 + dist($i, ($j-1)>>1);
}

# Determines the average memory distance for nodes as a function of tree distance.
sub get_dists($$)
{
my $tree = shift; # Original tree ordering
my $locality = shift; # Locality-based ordering

my %dists = ();
my %counts = ();

for (my $i=0; $i<length($tree); $i++)
{
for (my $j=$i; $j<length($tree); $j++)
{
# Find location of $i and $j in the locality-based ordering.
my $ni = substr($tree, $i, 1);
my $nj = substr($tree, $j, 1);
my $it = index($locality, $ni);
my $jt = index($locality, $nj);
my $d = (($i <= $j) ? ($j-$i) : ($i-$j));
my $dt = (($it <= $jt) ? ($jt-$it) : ($it-$jt));
my $treedist = dist($i, $j);
$dists{$treedist} += $dt;
$counts{$treedist}++;
}
}
foreach my $k (sort keys %counts)
{
$dists{$k} /= $counts{$k};
}
return %dists;
}

my $tree = "ABCDEFGHIJKLMNOPQRSTUVWXYZ01234"; # original (breadth-first prefix) ordering
my $prefix = "ABDHPQIRSEJTUKVWCFLXYMZ0GN12O34"; # depth-first prefix ordering
my $infix = "PHQDRISBTJUEVKWAXLYFZM0C1N2G3O4"; # infix ordering
my $veb = "ABCDHPQIRSEJTUKVMFLXYMZ0GN12O34"; # V.E.B. layout (hope I got it right)

my %original_dists = get_dists($tree, $tree);
my %prefix_dists = get_dists($tree, $prefix);
my %infix_dists = get_dists($tree, $infix);
my %veb_dists = get_dists($tree, $veb);

print "set key top left;\n";
print "set title 'Locality ratios';\n";
print "set xlabel 'tree distance';\n";
print "set ylabel 'avg. memory distance';\n";

print "plot '-' w lp title 'original', '-' w lp title 'prefix ordering', '-' w lp title 'infix ordering', '-' w lp title 'van-Emde-Boas layout';\n";

foreach my $k (sort keys %original_dists)
{
print "$k $original_dists{$k}\n";
}
print "e\n";
foreach my $k (sort keys %prefix_dists)
{
print "$k $prefix_dists{$k}\n";
}
print "e\n";
foreach my $k (sort keys %infix_dists)
{
print "$k $infix_dists{$k}\n";
}
print "e\n";
foreach my $k (sort keys %veb_dists)
{
print "$k $veb_dists{$k}\n";
}
print "e\n";

关于algorithm - 是否有任何保留位置的方法来展平二叉树?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35063641/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com