【问题标题】:Why is number of array accesses during the union and find operations said to be of the order lg(N) in Weighted QuickUnion?为什么联合期间的数组访问次数和查找操作在加权快速联合中的顺序为 lg(N)?
【发布时间】:2018-01-27 22:41:52
【问题描述】:

快速联合算法的通用代码。

public class QuickUnionUF
{
 private int[] id;
 public QuickUnionUF(int N)
 {
   id = new int[N];
   for (int i = 0; i < N; i++) id[i] = i;
 }
 private int root(int i)
 {
   while (i != id[i]) i = id[i];
   return i;
 }
 public boolean connected(int p, int q)
 {
   return root(p) == root(q);
 }
 public void union(int p, int q)
 {
   int i = root(p);
   int j = root(q);
   id[i] = j;
 }
}

这里很明显,对于像“初始化”、“联合”和“查找是否已连接”这样的联合操作,数组访问的数量将是 N 的数量级(这从代码中很清楚)。

但是,我的书声称,如果我们将 QuickUnion 修改为加权 QuickUnion,那么数组访问的数量将变为 lg(N) 的数量级。但是我看不出代码是怎么回事。

对加权 QuickUnion 所做的唯一更改是 union() 函数中的部分,如下所示:

 int i = root(p);
 int j = root(q);
 if (i == j) return;
 if (sz[i] < sz[j]) { id[i] = j; sz[j] += sz[i]; }
 else { id[j] = i; sz[i] += sz[j]; } 

这里我们维护额外的数组sz[i] 计算以 i 为根的树中的对象数。

但是在这里,我看不到 union 的数组访问次数是多少 lg(N)。数组访问的顺序必须是 N,因为我们必须调用 root() 方法两次。即使对于“查找是否已连接”操作,它的 lg(N) 顺序又如何?

我对他们如何获得 lg(N) 感到困惑。有人可以解释一下吗?

【问题讨论】:

    标签: java arrays algorithm math


    【解决方案1】:

    加权联合保留了对于每棵高度 h 和大小 n 的树,h ≤ log(n)+1 的不变量。

    这对于初始的一组树来说是微不足道的,n=1h=1

    假设我们合并两棵树,高度为 h₁、h₂,大​​小为 n₁、n₂n₁ ≥ n₂

    加权并集确保新高度为 h₁h₂ + 1,新大小为 n₁ + n₂。在这两种情况下,都会保留不变量:

    h₁ ≤ log(n₁) + 1 ⇒ h₁ ≤ log(n₁+n₂) + 1

    h₂ ≤ log(n₂) + 1 ⇒ h₂ + 1 ≤ log(n₂) + 2 ⇒ h₂ + 1 ≤ log(2n₂) + 1 ⇒ h₂ + 1 ≤ log(n₁+n₂) + 1

    因为 n₁ ≥ n₂

    【讨论】:

      【解决方案2】:

      当然, 现在,很明显,如果 root 方法的复杂度是 lg(n) 的阶,那么 union 也会有 lg(n)。

      加权快速联合保证了 lg(n) 的复杂性。方法如下:

      WQU(加权快速联合算法)将元素保存为多个树结构。 root 方法找到包含元素 i 的树的根。所以它的复杂度是受这种树的最大高度限制的。

      现在让 h(i) 是包含元素 i 的树的高度,而 w(i) 是该树的大小(重量)。 我们强加 h(i)

      因为我们将树绑定到另一个树的根。新树的高度最多可以是max(h(i), h(j)) + 1。

      假设 w(i) h(i) 我们不用担心,高度不会改变。如果不是,则新高度将为 h(i)+1。 w(i) + w(j) &gt;= 2 * w(i) =&gt; lg (w(i) + w(j)) &gt;= lg(2*w(i)) =&gt; log (new size) &gt;= 1 + lg(w(i)) &gt;= 1 + h(i). So h(i) + 1 &lt;= log(new size) 因此,约束仍然存在(新树的高度小于新权重的对数),这意味着,在最坏的情况下,对于大小为 N 的树,根方法最多需要 lg(N)步骤。

      【讨论】:

      • 这个证明一定是错的,因为你根本没有使用按等级联合。
      • Ofc 我做了,假设:w(i) + w(j) > 2 * w(i)。那是 w(j) > w(i) 因为 i 是要附加的树,它的权重小于 j 的权重。
      【解决方案3】:

      在未修改的版本中,您会获得线性依赖关系,因为到父级的链接可以是任意的。因此,在最坏的情况下,您最终可能会得到一个长列表(即,如果您位于列表的末尾,则必须遍历所有其他元素)。

      修改(按等级联合)旨在通过使较小的子树成为较大子树的根的子树来生成较浅的树。这种启发式使树更加平衡,即从任何叶子到其根的路径长度变为O(log n)。请记住,具有k 节点的完整二叉树的高度是O(log k)

      更正式的证明,请参考现有文献。

      附加说明:我提到按等级联合只是一种启发式方法。理想情况下,您会希望根据两个子树的高度做出决定。但是,跟踪高度非常困难。这就是为什么您通常使用与高度相关的子树的大小。

      【讨论】:

      • 谢谢。我想我可以直观地感受到你在说什么。但我想知道树的最大高度的数量级为 lg(n) 的数学证明。
      • 我写了数学证明作为答案。我想提一下,重量比身高更好。我认为按高度进行联合只能保证 O(sqrt(n)),但我不确定。
      猜你喜欢
      • 1970-01-01
      • 2022-10-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-10-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多