代码改变世界

STL make_heap push_heap pop_heap sort_heap

2015-04-05 20:32  youxin  阅读(869)  评论(0编辑  收藏  举报

 

make_heap:

default (1)
template <class RandomAccessIterator>
  void make_heap (RandomAccessIterator first, RandomAccessIterator last);
custom (2)
template <class RandomAccessIterator, class Compare>
  void make_heap (RandomAccessIterator first, RandomAccessIterator last,
                  Compare comp );
Make heap from range

Rearranges the elements in the range [first,last) in such a way that they form a heap.

heap is a way to organize the elements of a range that allows for fast retrieval of the element with the highest value at any moment (with pop_heap), even repeatedly, while allowing for fast insertion of new elements (with push_heap).

The element with the highest value is always pointed by first. The order of the other elements depends on the particular implementation, but it is consistent throughout all heap-related functions of this header.

The elements are compared using operator< (for the first version), or comp (for the second): The element with the highest value is an element for which this would return false when compared to every other element in the range.

The standard container adaptor priority_queue calls make_heappush_heap and pop_heap automatically to maintain heap properties for a container.

comp:

Binary function that accepts two elements in the range as arguments, and returns a value convertible to bool. The value returned indicates whether the element passed as first argument is considered to be less than the second in the specific strict weak ordering it defines.
The function shall not modify any of its arguments.
This can either be a function pointer or a function object.

make_heap(_First, _Last, _Comp)

默认是建立最大堆的。对int类型,可以在第三个参数传入greater<int>()得到最小堆。

 

  int A[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };

  make_heap(A, A + 10);
  for(int i=0;i<10;i++)
   cout<<A[i]<<" ";

输出:9 8 6 7 4 5 2 0 3 1 

vector<int> B(A,A+10);

make_heap(B.begin(),B.end(),greater<int>());//min-heap
cout<<B[0]<<endl;

输出0.

pop_heap(B.begin(),B.end()); B.pop_back();
cout<<B[9]<<endl;

可以看到,pop_heap会把堆顶元素放到序列末尾,即b.back()处。

 

// range heap example
#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[] = {10,20,30,5,15};
  std::vector<int> v(myints,myints+5);

  std::make_heap (v.begin(),v.end());
  std::cout << "initial max heap   : " << v.front() << '\n';

  std::pop_heap (v.begin(),v.end()); v.pop_back();
  std::cout << "max heap after pop : " << v.front() << '\n';

  v.push_back(99); std::push_heap (v.begin(),v.end());
  std::cout << "max heap after push: " << v.front() << '\n';

  std::sort_heap (v.begin(),v.end());

  std::cout << "final sorted range :";
  for (unsigned i=0; i<v.size(); i++)
    std::cout << ' ' << v[i];

  std::cout << '\n';

  return 0;
}

输出:

initial max heap : 30
max heap after pop : 20
max heap after push: 99
final sorted range : 5 10 15 20 99

在堆中添加数据

push_heap (_First, _Last)

要先在容器中加入数据,再调用push_heap ()

 

在堆中删除数据

pop_heap(_First, _Last)

要先调用pop_heap()再在容器中删除数据

 

堆排序

sort_heap(_First, _Last)

排序之后就不再是一个合法的heap了

 

 

make_heap()是生成一个堆,大顶堆或小顶堆
make_heap(_RAIter,_RAIter) 默认生成大顶堆
make_heap(_RAIter,_RAIter,_Compare) _Compare有两种参数,一种是greater(生成小顶堆),一种是less(生成大顶堆)
push_heap()是向堆中插入一个元素,并且使堆的规则依然成立
push_heap(_RAIter,_RAIter) 默认为大顶堆
push_heap(_RAIter,_RAIter,_Compare) _Compare有两种参数,一种是greater(小顶堆),一种是less(大顶堆)
调用push_heap之前必须调用make_heap创建一个堆
首先数组push_back插入元素,然后再调用push_heap,它会使最后一个元素插到合适位置
注意,push_heap中的_Compare和make_heap中的_Compare参数必须是一致的,不然会插入堆失败,最后一个元素还是在最后位置,导致插入失败
pop_heap()是在堆的基础上,弹出堆顶元素。
pop_heap(_RAIter,_RAIter) 默认为大顶堆
pop_heap(_RAIter,_RAIter,_Compare) _Compare有两种参数,一种是greater(小顶堆),一种是less(大顶堆)
比如pop_heap(nums.begin(), nums.end(),greater<int>()),它会将堆顶元素(即为数组第一个位置)和数组最后一个位置对调,然后你可以调用数组pop_back,删除这个元素
注意,pop_heap中的_Compare和make_heap中的_Compare参数必须是一致的,不然会失败
———————————————— 

 

陈硕 内存的多路归并排序:

https://github.com/chenshuo/recipes/blob/master/algorithm/mergeN.cc 

#include <algorithm>
#include <iostream>
#include <iterator>
#include <vector>

typedef int Record;
typedef std::vector<Record> File;

struct Input
{
  Record value;
  size_t index;
  const File* file;

  explicit Input(const File* f)
    : value(-1),
      index(0),
      file(f)
  { }

  bool next()
  {
    if (index < file->size())
    { value = (*file)[index];
      ++index;
      return true;
    } else {
      return false;
    }
  }

  bool operator<(const Input& rhs) const
  {
    // make_heap to build min-heap, for merging
    return value > rhs.value;
  }
};

File mergeN(const std::vector<File>& files)
{
  File output;
  std::vector<Input> inputs;

  for (size_t i = 0; i < files.size(); ++i) {
    Input input(&files[i]);
    if (input.next()) {
      inputs.push_back(input);
    }
  }

  std::make_heap(inputs.begin(), inputs.end());
  while (!inputs.empty()) {
    std::pop_heap(inputs.begin(), inputs.end());
    output.push_back(inputs.back().value);

    if (inputs.back().next()) {
      std::push_heap(inputs.begin(), inputs.end());
    } else {
      inputs.pop_back();
    }
  }

  return output;
}

int main()
{
  const int kFiles = 32;
  std::vector<File> files(kFiles);
  for (int i = 0; i < kFiles; ++i) {
    File file(rand() % 1000);
    std::generate(file.begin(), file.end(), &rand);
    std::sort(file.begin(), file.end());
    files[i].swap(file);
  }

  File output = mergeN(files);

  std::copy(output.begin(), output.end(),
            std::ostream_iterator<Record>(std::cout, "\n"));
}