pop_heap是怎么排序的?

看到机器就疯狂 2013-07-03 08:13:25
这个函数很令人不解,很错乱的一个函数。
...全文
419 10 打赏 收藏 转发到动态 举报
写回复
用AI写文章
10 条回复
切换为时间正序
请发表友善的回复…
发表回复
大树叶 2015-12-13
  • 打赏
  • 举报
回复
yes.是这样的
  • 打赏
  • 举报
回复
make_heap默认大根堆??
  • 打赏
  • 举报
回复
引用 6 楼 u010936098 的回复:
pop_heap就是拿走堆顶元素,然后进行调整以保证剩余元素依然是一个堆。 它不只是用来排序的,循环调用这个函数直到堆为空才是排序。堆数据还可以用来实现优先队列、获取(最大的)N个元素等。 堆的作用是帮助我们在logN的时间内找到所有元素的最大值,这一特性正好可以实现一个N*LogN的选择排序,也就产生了“堆排序”:

make_heap
while (堆不为空)
   pop_heap --》线性表首
用堆排序时,堆的优先级判断逻辑正好与我们排序的代先级逻辑正好相反,这是为了实现“原位转换”的堆排序。我们把表的前一部分组成堆,后一部分组成线性表(最开始时这一部分为空),每次从堆中pop,都会另堆收缩一个元素,空出来的位置正好在线性表的前面,因此我们每次都从堆中取出放在表首而不是表尾,这就要求从堆中取出的是最大值而不是最小值。
make_heap默认实现的是大根堆???
  • 打赏
  • 举报
回复
引用 6 楼 u010936098 的回复:
pop_heap就是拿走堆顶元素,然后进行调整以保证剩余元素依然是一个堆。 它不只是用来排序的,循环调用这个函数直到堆为空才是排序。堆数据还可以用来实现优先队列、获取(最大的)N个元素等。 堆的作用是帮助我们在logN的时间内找到所有元素的最大值,这一特性正好可以实现一个N*LogN的选择排序,也就产生了“堆排序”:

make_heap
while (堆不为空)
   pop_heap --》线性表首
用堆排序时,堆的优先级判断逻辑正好与我们排序的代先级逻辑正好相反,这是为了实现“原位转换”的堆排序。我们把表的前一部分组成堆,后一部分组成线性表(最开始时这一部分为空),每次从堆中pop,都会另堆收缩一个元素,空出来的位置正好在线性表的前面,因此我们每次都从堆中取出放在表首而不是表尾,这就要求从堆中取出的是最大值而不是最小值。
线性表要求表首是最大值??
橡木疙瘩 2013-07-03
  • 打赏
  • 举报
回复
pop_heap就是拿走堆顶元素,然后进行调整以保证剩余元素依然是一个堆。 它不只是用来排序的,循环调用这个函数直到堆为空才是排序。堆数据还可以用来实现优先队列、获取(最大的)N个元素等。 堆的作用是帮助我们在logN的时间内找到所有元素的最大值,这一特性正好可以实现一个N*LogN的选择排序,也就产生了“堆排序”:

make_heap
while (堆不为空)
   pop_heap --》线性表首
用堆排序时,堆的优先级判断逻辑正好与我们排序的代先级逻辑正好相反,这是为了实现“原位转换”的堆排序。我们把表的前一部分组成堆,后一部分组成线性表(最开始时这一部分为空),每次从堆中pop,都会另堆收缩一个元素,空出来的位置正好在线性表的前面,因此我们每次都从堆中取出放在表首而不是表尾,这就要求从堆中取出的是最大值而不是最小值。
  • 打赏
  • 举报
回复
make_heap后: 45 20 35 5 3 不是由小到大排列,然后pop_heap: 35 20 3 5 45 把45挪到尾部来了, 可也不是按顺序排序的啊。
  • 打赏
  • 举报
回复
引用 3 楼 u010262792 的回复:
[quote=引用 2 楼 u010262792 的回复:] 首先弄清楚最大堆的性质:每个节点的数值都比它的孩子中的数值大,这样对一个构建好的最大堆来说,堆中最大的元素在堆顶,就是根节点。
刚才手残没写完就按了回复了。 然后堆排序的执行方法就是把根节点和最后一个节点互换,这样最后一个节点中就是最大的数值了。但是这个时候最大堆已经被破坏了,所以需要维护最大堆的性质,把刚才的堆重新变成最大堆。然后再把堆顶节点和倒数第二个节点互换,一直往复,就把堆中元素从小到大排列好了。[/quote] 好像不是由小到大排列的, 如:

  #include <iostream>     // std::cout
  #include <algorithm>    // std::make_heap, std::pop_heap, std::push_heap, std::sort_heap
  #include <vector>       // std::vector
  int main () {
  int myints[] = {3,20,35,5,45};
  std::vector<int> v(myints,myints+5);

  std::make_heap (v.begin(),v.end());
  std::cout << "initial max heap   : " << v.front() << '\n';
  for (unsigned i=0; i<v.size(); i++)
    std::cout << ' ' << v[i];
  std::cout << '\n';
  std::pop_heap (v.begin(),v.end());
  std::cout << "max heap after pop : " << v.front() << '\n';
  std::cout << "final sorted range :";
  for (unsigned i=0; i<v.size(); i++)
    std::cout << ' ' << v[i];
  std::cout << '\n';
  getchar();
  return 0;
}
程序猿Theg 2013-07-03
  • 打赏
  • 举报
回复
引用 2 楼 u010262792 的回复:
首先弄清楚最大堆的性质:每个节点的数值都比它的孩子中的数值大,这样对一个构建好的最大堆来说,堆中最大的元素在堆顶,就是根节点。
刚才手残没写完就按了回复了。 然后堆排序的执行方法就是把根节点和最后一个节点互换,这样最后一个节点中就是最大的数值了。但是这个时候最大堆已经被破坏了,所以需要维护最大堆的性质,把刚才的堆重新变成最大堆。然后再把堆顶节点和倒数第二个节点互换,一直往复,就把堆中元素从小到大排列好了。
程序猿Theg 2013-07-03
  • 打赏
  • 举报
回复
首先弄清楚最大堆的性质:每个节点的数值都比它的孩子中的数值大,这样对一个构建好的最大堆来说,堆中最大的元素在堆顶,就是根节点。
qzf362269994 2013-07-03
  • 打赏
  • 举报
回复
pop_heap算法 此操作取走根节点。对于大顶堆,取得的是堆中值最大的节点,对于小顶堆,取得的是堆中值最小的节点。STL实现并不是将这个节点直接删除,而是将其放在底层容器vector的尾端。而原尾端的节点插入到前面的适当位置。 我们首先保存原vector尾端的节点值,然后将根节点值存储在此处。为了实将原尾端节点的值插入适当位置,重新构建大顶堆,我们实施如下调整堆的操作: 先执行下溯(percolate down)操作:从根节点开始将空洞节点(一开始是根节点)和较大子节点交换,并持续向下进行,直到到达叶节点为止。然后将已保存的原容器vector尾端节点赋给这个已到达叶层的空洞节点。 注意,到这里并没有结束。因为这时候可能还没有满足大顶堆的特性。还需要执行一次上溯操作。这样,便重新构建了大顶堆

64,637

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧