点击打开链接
下面再介绍STL中与堆相关的4个函数——建立堆make_heap(),在堆中添加数据push_heap(),在堆中删除数据pop_heap()和堆排序sort_heap():
头文件 #include
下面的_First与_Last为可以随机访问的迭代器(指针),_Comp为比较函数(仿函数),其规则——如果函数的第一个参数小于第二个参数应返回true,否则返回false。
建立堆
make_heap(_First, _Last, _Comp)
默认是建立最大堆的。对int类型,可以在第三个参数传入greater
在堆中添加数据 ///只对最后一个元素进行堆 排序 所以加数据要在最后一位加
push_heap (_First, _Last)
要先在容器中加入数据,再调用push_heap ()
在堆中删除数据 /// 栈顶元素与最后的元素进行了交换(跑到最后去了)
pop_heap(_First, _Last)
要先调用pop_heap()再在容器中删除数据
堆排序
sort_heap(_First, _Last)
排序之后就不再是一个合法的heap了
#include
#include
#include
#include
using namespace std;
void PrintfVectorInt(vector &vet)
{
for (vector::iterator pos = vet.begin(); pos != vet.end(); pos++)
printf("%d ", *pos);
putchar('\n');
}
int main()
{
const int MAXN = 20;
int a[MAXN];
int i;
for (i = 0; i < MAXN; ++i)
a[i] = rand() % (MAXN * 2);
//动态申请vector 并对vector建堆
vector *pvet = new vector(40);
pvet->assign(a, a + MAXN);
//建堆
make_heap(pvet->begin(), pvet->end());
PrintfVectorInt(*pvet);
//加入新数据 先在容器中加入,再调用push_heap()
pvet->push_back(25);
push_heap(pvet->begin(), pvet->end());
PrintfVectorInt(*pvet);
//删除数据 要先调用pop_heap(),再在容器中删除
pop_heap(pvet->begin(), pvet->end());
pvet->pop_back();
pop_heap(pvet->begin(), pvet->end());
pvet->pop_back();
PrintfVectorInt(*pvet);
//堆排序
sort_heap(pvet->begin(), pvet->end());
PrintfVectorInt(*pvet);
delete pvet;
return 0;
}
题意:给你m个数字集合 每个数字集合中有n个数字
从m个串中挑选一个数字加起来,共有n^m 中相加的方法
求按非降序的顺序输出前n个最小的和
思路:
利用堆的思想将求从m 个数字集合中挑选m 个数字相加
这个m个数相加的过程一步一步的进行
让现有的和与堆中的和进行比较,判断是否更改堆顶;
{
先让堆中的元素随意加入第i个数字 (以加入第一个为例)
然后让现在的堆顶 与 加入其他数字进行比较,判断是否需要更改
}
步骤:
利用两个数组和一个堆进行做
1 a[]表示在添加第i个数字前 的前n个小的和
{即输入第i个串之前 的和}
2 b[]表示当前输的第i串中的数字
3 heap[]表示堆储存
4
[1]
先将第一组串作为堆的基础(a[]有序的)
[2]
输入下一组串b (排序)
然后让堆中的每个数字都加上b[1];
接着让堆顶(为堆中最大数字)与 a[1...n]+b[2...n],进行比较
{
大于
就更新堆顶数字
小于
退出 (有优化的过程(因为提前对a[],b[]都排序了);
}
重复[2] 直到输入了m行
#include
#include
#include
#include
#include
#include
#include
using namespace std;
int heap[3000],a[3000],b[3000];
void adjust(int ind,int len)
{
int lch=ind<<1;
int rch=ind<<1|1;
int Max=ind;
if(ind<=len/2)
{
if(lch<=len&&heap[lch]>heap[Max])
Max=lch;
if(rch<=len&&heap[rch]>heap[Max])
Max=rch;
if(Max!=ind)
{
swap(heap[Max],heap[ind]);
adjust(Max,len);
}
}
}
int main()
{
int T;
int n,m;
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&m,&n);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
for(int i=1;i<=n;i++)
heap[i]=a[i];
for(int i=n/2;i>=1;i--)
adjust(i,n); ///一个数的时候的堆的创建
///为了使元素满足根大于左右孩子
for(int i=2;i<=m;i++)
{
sort(a+1,a+n+1); ///排序 优化if(heap[1]>a[k]+b[j])
for(int j=1;j<=n;j++)
scanf("%d",&b[j]);
sort(b+1,b+n+1);
for(int j=1;j<=n;j++)
heap[j]+=b[1]; ///建立拥有i个数字相加和的堆
for(int j=2;j<=n;j++)
{
for(int k=1;k<=n;k++)
{
if(heap[1]>a[k]+b[j]) ///堆顶与其他相加和进行比较
{
heap[1]=a[k]+b[j];
adjust(1,n);
}
else
break;
}
}
for(int j=1;j<=n;j++) ///用a[]来存 拥有i个数字相加和的前n个最小和
a[j]=heap[j];
}
sort(heap+1,heap+1+n);
for(int i=1;i
STL 堆
#include
#include
#include
#include
#include
#include
#include
using namespace std;
int heap[3000],a[3000],b[3000];
int main()
{
int n,m,T;
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&m,&n);
for(int i=0;ia[k]+b[j])
{
pop_heap(heap,heap+n); ///堆顶不会消失,移动到了最后
heap[n-1]=a[k]+b[j];
push_heap(heap,heap+n); ///只对最后一个元素进行重新堆排序
}
else
break;
}
}
for(int j=0;j