题目来自剑指Offer
题目
思路:求最小的k个数,建立一个容量为k的大根堆。插入元素时,堆不满直接插入,堆满且数小插入。
使用堆的原因:适用于海量数据。使用堆不用把海量数据一次性放入内存,也不用打乱源数据的顺序。
代码:借助STL的堆
#include <iostream>
#include <algorithm>
#include <vector>
#include <assert.h>
using namespace std;
void OutPut(vector<int>& Heap)
{
vector<int>::iterator itCur = Heap.begin();
while(itCur != Heap.end())
{
cout<<*itCur<<" ";
itCur++;
}
}
void FindTopKMin(int nArr[],int nLen,int nTopK)
{
assert(nLen > 0 && nLen >= nTopK);
vector<int> Heap(nArr,nArr + nTopK);
make_heap(Heap.begin(),Heap.end());//默认为大根堆
//TopK比较
for (int i = nTopK;i < nLen;i++)
{
if (nArr[i] < Heap[0])
{
Heap[0] = nArr[i];
make_heap(Heap.begin(),Heap.end());
}
}
//输出结果
sort_heap(Heap.begin(),Heap.end());
OutPut(Heap);
}
int main()
{
int nTopK = 8;
int nLen = 10;
int nArr[10] = {1,3,8,5,3,20,15,9,20,18};
FindTopKMin(nArr,nLen,nTopK);
system("pause");
return 1;
}
代码:自己手写堆
#include <iostream>
#include <assert.h>
using namespace std;
const int TOP_K = 8;
int nMaxSize = TOP_K;
int nCurSize = 0;
int arrHeap[TOP_K + 1];
void Adjust(int nPos)
{
assert(nPos > 0);
int nData = arrHeap[nPos];
int nParentPos = nPos;
int nChildPos = nPos << 1;
while(nChildPos <= nCurSize)
{
if (nChildPos < nCurSize && arrHeap[nChildPos] < arrHeap[nChildPos + 1])
{
nChildPos++;
}
if (nData < arrHeap[nChildPos])
{
arrHeap[nParentPos] = arrHeap[nChildPos];
nParentPos = nChildPos;
nChildPos <<= 1;
}
else
{
break;
}
}
assert(nParentPos > 0 && nParentPos <= nCurSize);
arrHeap[nParentPos] = nData;
}
void Insert(int nPos,int nData)
{
arrHeap[0] = nData;
int nChildPos = nCurSize;
int nParentPos = nChildPos >> 1;
while(arrHeap[nParentPos] < nData)
{
arrHeap[nChildPos] = arrHeap[nParentPos];
nChildPos = nParentPos;
nParentPos = nParentPos >> 1;
}
arrHeap[nChildPos] = nData;
}
void Insert(int nData)
{
assert(nCurSize >= 0);
if (nCurSize < nMaxSize)
{
++nCurSize;
Insert(nCurSize,nData);
}
else
{
assert(nCurSize == nMaxSize);
if (arrHeap[1] > nData) //比最大值小,则插入堆
{
arrHeap[1] = nData;
Adjust(1);
}
}
}
void Sort()
{
assert(nCurSize > 0);
while(nCurSize > 0)
{
cout<<arrHeap[1]<<" ";
arrHeap[1] = arrHeap[nCurSize];
Adjust(1);
nCurSize--;
}
}
int main()
{
int nArr[10] = {1,3,8,5,3,20,15,9,20,18};
for (int nCur = 0;nCur < 10;nCur++)
{
Insert(nArr[nCur]);
}
cout<<"元素输出:"<<endl;
Sort();
cout<<endl;
system("pause");
return 1;
}
把堆封装成类:
#include <iostream>
#include <assert.h>
using namespace std;
const int TOP_K = 8;
class CTopKMin
{
public:
CTopKMin(int nMaxSize = TOP_K);
void Init();
void Insert(int nData);
bool IsMax();
void Sort();
void Output();
private:
void Adjust(int nPos);
void Insert(int nPos,int nData);
private:
int* m_pHeap;
int m_nCurSize;
int m_nMaxSize;
};
CTopKMin::CTopKMin(int nMaxSize)
{
m_nCurSize = 0;
m_nMaxSize = nMaxSize;
m_pHeap = new int[m_nMaxSize + 1];
assert(m_nMaxSize > 0);
}
void CTopKMin::Init()
{
m_nCurSize = 0;
}
void CTopKMin::Insert(int nData)
{
assert(m_nCurSize >= 0);
if (m_nCurSize < m_nMaxSize)
{
++m_nCurSize;
Insert(m_nCurSize,nData);
}
else
{
assert(m_nCurSize == m_nMaxSize);
if (m_pHeap[1] > nData) //比最大值小,则插入堆
{
m_pHeap[1] = nData;
Adjust(1);
}
}
}
void CTopKMin::Insert(int nPos,int nData)
{
m_pHeap[0] = nData;
int nChildPos = m_nCurSize;
int nParentPos = nChildPos >> 1;
while(m_pHeap[nParentPos] < nData)
{
m_pHeap[nChildPos] = m_pHeap[nParentPos];
nChildPos = nParentPos;
nParentPos = nParentPos >> 1;
}
m_pHeap[nChildPos] = nData;
}
void CTopKMin::Adjust(int nPos)
{
assert(nPos > 0);
int nData = m_pHeap[nPos];
int nParentPos = nPos;
int nChildPos = nPos << 1;
while(nChildPos <= m_nCurSize)
{
if (nChildPos < m_nCurSize && m_pHeap[nChildPos] < m_pHeap[nChildPos + 1])
{
nChildPos++;
}
if (nData < m_pHeap[nChildPos])
{
m_pHeap[nParentPos] = m_pHeap[nChildPos];
nParentPos = nChildPos;
nChildPos <<= 1;
}
else
{
break;
}
}
assert(nParentPos > 0 && nParentPos <= m_nCurSize);
m_pHeap[nParentPos] = nData;
}
bool CTopKMin::IsMax()
{
assert(m_nCurSize > 0);
int nChildPos = m_nCurSize;
int nParentPos = m_nCurSize >> 1;
while(nChildPos > 1 && m_pHeap[nChildPos] <= m_pHeap[nParentPos])
{
nChildPos--;
nParentPos = nChildPos >> 1;
}
if (nChildPos == 1)
{
return true;
}
else
{
return false;
}
};
void CTopKMin::Sort()
{
assert(m_nCurSize > 0);
while(m_nCurSize > 0)
{
cout<<m_pHeap[1]<<" ";
m_pHeap[1] = m_pHeap[m_nCurSize];
Adjust(1);
m_nCurSize--;
}
}
void CTopKMin::Output()
{
for (int nCur = 1;nCur <= m_nCurSize;nCur++)
{
cout<<m_pHeap[nCur]<<" ";
}
cout<<endl;
}
int main()
{
int nArr[10] = {1,3,8,5,3,20,15,9,20,18};
CTopKMin topKMin;
for (int nCur = 0;nCur < 10;nCur++)
{
topKMin.Insert(nArr[nCur]);
topKMin.Output();
}
if (topKMin.IsMax())
{
cout<<"大顶堆!"<<endl;
}
else
{
cout<<"不是大顶堆!"<<endl;
}
cout<<"元素输出:"<<endl;
topKMin.Sort();
cout<<endl;
system("pause");
return 1;
}