在c++中只重新堆一个元素
Reheaping only one element in c++
我有一个在vector
和make_heap
上构建的堆。如果我只改变一个(现有的)元素的值,是否有O(log n)的方法来重新堆积,或者我必须再次调用make_heap
?
给定一个知道已经是堆的向量,如果您决定更改堆中隐藏的插槽中的单个项,则将堆最小程度地重新填充到有效堆状态的步骤包括以下步骤:
- 将修改后的元素与堆中最后一个元素交换。
- 对从末尾插入的元素执行"下推"操作。这涉及到与它的两个子元素中最大的元素重复交换,直到没有子元素剩余或没有交换发生。注意:不要包括序列中的最后一个元素,它仍然是你从#1修改的元素。
- 执行最后一次
push_heap(vec.begin(), vec.end())
。这会将修改后的元素堆积到正确的位置。
乍一看可能很复杂,但除了#2中的步骤之外,这里没有什么特别的。其余的只是您可能熟悉的常规堆操作。我希望这是有意义的。
样例代码这是一个可能的实现。显然,您的需求可能会有所不同。我只是把这些放在一起,所以我希望它至少有一点指导意义:
#include <iostream>
#include <algorithm>
#include <iterator>
#include <vector>
using namespace std;
int main()
{
// intialize random generator
srand((unsigned)time(0));
// will hold our heap
vector<int> vec;
for (int i=0;i<20;vec.push_back(++i));
random_shuffle(vec.begin(), vec.end());
cout << "Rand: ";
copy(vec.begin(), vec.end(), ostream_iterator<int>(cout, " "));
cout << endl;
// make a maxheap
less<int> cmp;
make_heap(vec.begin(), vec.end(), cmp);
// dump content to stdout
cout << "Heap: ";
copy(vec.begin(), vec.end(), ostream_iterator<int>(cout, " "));
cout << endl;
// pick an item in the heap to modify, for our purposes, vec[1]
vector<int>::iterator it = vec.begin()+1;
*it *=2;
// swap with the last element, then push-down the swapped-in element
// until we find its rightful home.
iter_swap(it, vec.end()-1);
while (distance(it, vec.end()) > 1)
{
// leave if no more children
size_t i = distance(vec.begin(), it);
if (2*i+1 >= vec.size()-1)
break;
// have one child. might have two
vector<int>::iterator itChild = vec.begin() + 2*i+1;
if (itChild+1 < vec.end()-1)
{
if (cmp(*itChild, *(itChild+1)))
itChild = itChild+1;
}
// no need to swap; we're done.
if (!cmp(*it, *itChild))
break;
// dump "before" picture
cout << " beg: ";
copy(vec.begin(), vec.end(), ostream_iterator<int>(cout, " "));
cout << endl;
// swap values and move to swapped child.
iter_swap(it, itChild);
it = itChild;
// dump "after" picture
cout << " end: ";
copy(vec.begin(), vec.end(), ostream_iterator<int>(cout, " "));
cout << endl;
}
// now push_heap our new value, which is still hanging out
// at the end where we left it.
push_heap(vec.begin(), vec.end(), cmp);
// final dump
cout << "Last: ";
copy(vec.begin(), vec.end(), ostream_iterator<int>(cout, " "));
cout << endl;
// verify make_heap likes what we made (should be the same).
make_heap(vec.begin(), vec.end(), cmp);
cout << "Heap: ";
copy(vec.begin(), vec.end(), ostream_iterator<int>(cout, " "));
cout << endl;
return EXIT_SUCCESS;
}
Rand: 15 14 8 5 1 17 10 13 3 20 11 19 6 4 9 2 18 7 12 16
Heap: 20 18 19 17 16 15 10 13 12 14 11 8 6 4 9 2 5 3 7 1
beg: 20 1 19 17 16 15 10 13 12 14 11 8 6 4 9 2 5 3 7 36
end: 20 17 19 1 16 15 10 13 12 14 11 8 6 4 9 2 5 3 7 36
beg: 20 17 19 1 16 15 10 13 12 14 11 8 6 4 9 2 5 3 7 36
end: 20 17 19 13 16 15 10 1 12 14 11 8 6 4 9 2 5 3 7 36
beg: 20 17 19 13 16 15 10 1 12 14 11 8 6 4 9 2 5 3 7 36
end: 20 17 19 13 16 15 10 5 12 14 11 8 6 4 9 2 1 3 7 36
Last: 36 20 19 13 17 15 10 5 12 16 11 8 6 4 9 2 1 3 7 14
Heap: 36 20 19 13 17 15 10 5 12 16 11 8 6 4 9 2 1 3 7 14
相关文章:
- 使用strcpy将char数组的元素复制到另一个数组
- 使用堆查找第K个最大元素的时间复杂性
- 查找矩阵C++中每一列和每一行的最小和最大元素
- C++使用另一个数组和新值初始化数组
- 如何将元素从向量转移到新数组?
- C++:添加新结构时,结构指针向量中的所有元素都会更新
- 高级选择排序 - 在一次迭代中搜索两个元素
- 将二维数组的所有元素插入到一维数组中
- 如何使用结构和指针推动和弹出一堆双打
- 删除 [] 后剩余的堆数组的剩余元素
- 如何改进一堆在已知值范围内评估变量的 else-if 条件?
- 在最小堆中查找最大元素
- 将一个数组的每个元素乘以另一个数组的每个元素,并对新的非常大的数组进行排序
- 如何仅将新添加的元素复制到std :: Deque中
- 删除前面元素并将新元素添加到最小堆 (std::p riority_queue)
- 添加和初始化新std::map元素的最有效方法是什么
- C++将字符从静态数组复制到动态数组会添加一堆随机元素
- 我正在尝试在函数中新内存新堆内存,但它给出了错误
- 使用Qt,其中工作线程创建新的GUI元素
- 在c++中只重新堆一个元素