📜  锦标赛树(赢家树)和二叉堆

📅  最后修改于: 2021-10-28 02:06:17             🧑  作者: Mango

给定一个由 N 名球员组成的团队。最少需要多少场比赛才能找到第二好的球员?

我们可以使用基于锦标赛树(二叉堆)的对手参数。

锦标赛树是最小(最大)堆的一种形式,它是一个完整的二叉树。每个外部节点代表一个玩家,内部节点代表获胜者。在锦标赛树中,每个内部节点都包含获胜者,每个叶节点都包含一个玩家。

在具有 N 个叶子(外部)节点的二叉树中将有 N-1 个内部节点。有关详细信息,请参阅此帖子(在帖子中给出的等式中输入 n = 2)。

很明显,要从 N 个玩家中选出最好的玩家,要淘汰 (N-1) 个玩家,即我们需要最少 (N-1) 场比赛(比较)。数学上我们可以证明。在二叉树中,I = E – 1,其中 I 是内部节点的数量,E 是外部节点的数量。这意味着要找到数组的最大或最小元素,我们需要 N-1(内部节点)比较。

第二佳球员

在最佳球员选择期间探索的信息可用于最小化追踪次佳球员的比较次数。例如,我们可以在(N + log 2 N – 2) 次比较中选择第二好的球员。

下图将锦标赛树(获胜者树)显示为最大堆。请注意,失败者树的概念是不同的。

上面的树包含代表玩家的 4 个叶节点,有 3 个级别 0、1 和 2。最初在级别 2 进行 2 场比赛,一场介于 5 和 3 之间,另一场介于 7 和 8 之间。下一步,再进行一场比赛在 5 到 8 点之间进行以得出最终的获胜者。总的来说,我们需要 3 次比较。对于第二好的玩家,我们需要追踪最终获胜者参与的候选人,这导致 7 为第二好。

有序数组的中位数

锦标赛树可以有效地用于查找排序数组的中值。假设,给定 M 个相等大小 L 的排序数组(为简单起见)。我们可以将所有这些排序的数组附加到锦标赛树上,每个叶子一个数组。我们需要一棵高度为CEIL (log 2 M)的树来拥有至少 M 个外部节点。

考虑一个例子。给定 3 (M = 3) 个最大大小为 5 个元素的已排序整数数组。

{ 2, 5, 7, 11, 15 } ---- Array1
{1, 3, 4} ---- Array2
{6, 8, 12, 13, 14} ---- Array3

锦标赛树的高度应该是多少?我们需要构建一个高度 log 2 3 .= 1.585 = 2 四舍五入到下一个整数的锦标赛树。高度为 2 的二叉树将有 4 个叶子,我们可以将数组附加到这些叶子上,如下图所示。

在第一场比赛后,树出现如下,

我们可以观察到获胜者来自 Array2。因此,来自 Array2 的下一个元素将潜入,游戏将沿着上一届锦标赛的获胜者路径进行。

请注意,无穷大用作哨兵元素。根据节点中保存的数据,我们可以选择哨兵字符。例如,我们通常将指针存储在节点中而不是键中,因此 NULL 可以作为哨兵。如果任何数组耗尽,我们将用哨兵填充相应的叶子和即将到来的内部节点。

第二场比赛后,树出现如下,

下一个获胜者来自 Array1,因此 Array1 数组的下一个元素为 5 将潜入下一轮,下一场比赛沿 2 的路径进行。

比赛可以继续,直到我们得到中值元素,即 (5+3+5)/2 = 7th 元素。请注意,还有更好的算法可用于查找已排序数组并集的中值,有关详细信息,请参见下面给出的相关链接。

通常,对于大小为 L 1 、L 2 … L m 的M 个排序列表,需要O((L 1 + L 2 + … + L m ) * logM) 的时间复杂度来合并所有数组,并且O(m*logM)找到中位数的时间,其中m是中位数位置。

从 10 亿个未排序元素中选择最小的 100 万个元素:

作为一个简单的解决方案,我们可以对十亿个数字进行排序并选择前一百万个。

在有限的内存系统上排序十亿个元素并选择前一百万似乎是不切实际的。我们可以使用锦标赛树方法。任何时候都只有树的元素在内存中。

将大数组(可能存储在磁盘上)拆分为每个大小为 100 万的较小数组(或者甚至可以由机器排序的更小数组)。对这 1000 个小型数组进行排序,并将它们作为单独的文件存储在磁盘上。构建一个可以有至少 1000 个叶节点的锦标赛树(树的高度为 10,因为 2 9 < 1000 < 2 10 ,如果单个文件更小,我们将需要更多的叶节点)。每个叶节点都有一个引擎,可以从存储在磁盘上的排序文件中选择下一个元素。我们可以玩锦标赛树游戏来提取前一百万个元素。

总成本 = 排序 1000 个列表,每个列表 100 万个 + 树构建 + 锦标赛

执行
我们需要以自下而上的方式构建树。首先填充所有叶节点。从树的最左边开始并沿着宽度填充(即从 2 k-1到 2 k – 1,其中 k 是树的深度)并玩游戏。经过几个例子练习后,编写代码将很容易。实现在下面的代码中讨论

使用最小比较的第二个最小元素

相关文章
查找数组中最小和次小的元素。
使用最小比较的第二个最小元素

如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程学生竞争性编程现场课程