从堆中删除元素
Removing elements from heap
我做了一堆。我很好奇我的删除功能是否有微妙的问题:
int Heap::remove() {
if (n == 0)
exit(1);
int temp = arr[0];
arr[0] = arr[--n];
heapDown(0);
arr[n] = 0;
return temp;
}
void Heap::heapDown(int i)
{
int l = left(i);
int r = right(i);
// comparing parent to left/right child
// each has an inner if to handle if the first swap causes a second swap
// ie 1 -> 3 -> 5
// 3 5 1 5 1 3
if (l < n && arr[i] < arr[l])
{
swap(arr[i], arr[l]);
heapDown(l);
if (r < n && arr[i] < arr[r])
{
swap(arr[i], arr[r]);
heapDown(r);
}
}
else if (r < n && arr[i] < arr[r])
{
swap(arr[i], arr[r]);
heapDown(r);
if (l < n && arr[i] < arr[l])
{
swap(arr[i], arr[l]);
heapDown(l);
}
}
}
这是我的输出
i1i2i3i4i5i6i7
p
Active heap: 7 4 6 1 3 2 5
r
Removed 7
r
Removed 6
p
Active heap: 5 3 4 1 2
这是我老师的示例输出:
p
Active heap : 7 4 6 1 3 2 5
r
Removed 7
r
Removed 6
p
Active heap : 5 4 2 1 3
s
Heapsorted : 1 2 3 4 5
虽然我们的输出完全不同,但我似乎确实坚持 maxheap 原则,即让所有节点都面向父节点>子节点(在每种情况下我都尝试过)。我尝试从头开始做这样的算法,所以也许我只是在做一些非常奇怪和错误的事情(如果它是>O(lg n),我只会认为它是"错误的",因为删除是为了堆)。我的删除有什么特别"错误"的地方吗?谢谢
http://ideone.com/PPh4eQ
首先,我假设你的意思是除了你不需要它之外,因为我们在C++标准库中设置了一个完整的堆管理函数,包括make_heap、push_heap、pop_heap,甚至sort_heap。
也就是说,我想我知道你的问题是什么。堆中有不必要的元素移动。它处理堆积上的交换算法:左右两侧都存在相同的问题,因此我将展示第一个问题:
if (l < n && arr[i] < arr[l])
{
swap(arr[i], arr[l]);
heapDown(l);
if (r < n && arr[i] < arr[r])
{
swap(arr[i], arr[r]);
heapDown(r);
}
}
这里的逻辑对于最小运动不是最佳的。被下推的元素的"较小"状态必须属于两个基本类别之一,并且对每个类别采取不同的操作:
- 元素不小于左或右。什么都不做。
- 元素小于左或右,仅与最大的元素交换,然后仅向下驱动到该子树中。
该列表中上面的 #2 是代码中的问题。 您交换较小的,然后是较大的,如果项目<左><右。我希望这一点是清楚的。如果你想要一个建议来修复你的逻辑,我可以提供一个,但我认为如果你理解我上面描述的内容,你可能会有一个处理它。>左>
剧情透露
void Heap::heapDown(int i)
{
int l = left(i);
int r = right(i);
int x = 0;
if (l < n && arr[i] < arr[l])
{
x = l;
if (r < n && arr[l] < arr[r])
x = r;
}
else if (r < n && arr[i] < arr[r])
x = r;
if (x != 0)
{
swap(arr[i], arr[x]);
heapDown(x);
}
}
注意:;如果不是很明显,这就是尾递归的定义,因此可以很容易地转换为一个简单的迭代循环。
相关文章:
- C++如何通过用户输入删除列表元素
- 使用函数"remove"删除重复元素
- 如何通过 getter 函数删除矢量的元素?
- 从控制台中删除最后打印的元素
- 如何从存储在std::映射中的std::集中删除元素
- 从嵌套在std::映射中的std::列表中删除元素的最佳方式
- 删除列表中的第n个元素
- 从矢量中删除元素后出现隔离错误
- 删除映射和分割错误中的一个过去结束元素
- 如何使用remove_if从矢量中删除元素
- 如何从使用 for 循环中的矢量大小的矢量中删除元素
- 从矢量中删除空元素
- 关于比较两个无序数组并删除 a[] 中可以在 b[] 中找到的元素的问题
- 删除指针数组 (C++) 中的元素
- 删除列表 c++ 中的最后 3 个元素
- 比较 2 个向量并从第二个向量中删除在第一个 - c++ 中找不到的元素
- 为什么通过 vector<reference_wrapper> 的元素删除引用的值<T>不会使向量无效?
- 从std::multiset的第i个元素删除到末尾
- 删除 [] 是否等于每个元素删除.C++
- std::列出元素删除后节点的内存回收