尋找第n個數 與前n個數的幾種方法
<span style="font-size:18px;">#include<iostream>
#include<string>
#include<functional>
#include<iterator>
#include<algorithm>
#include<queue>
#include<vector>
#include<set>
#include<cassert>
using namespace std;
//平均情況 O(n)
//前nth-1個元素是無序的 可以調快排
int NthElement(int* p,int left, int right, int nth);
int partition(int* p,int left, int right);
//O(nlogn)
const vector<int>* PartSortByqueue(int *p, int len,int k);
const vector<int>* PartSortByheap(int *p, int len, int k);
const vector<int>* PartSortBymultiset(int *p, int len, int k);
template<class T>
class display
{
public:
void operator()(const T& val)
{
cout << val << " ";
}
};
//劃分函數 返回軸值所在下標
int partition(int* p,int left, int right)
{
assert(nullptr!=p);
if (left > right)
{
return -1;
}
//軸值選取可以優化 否則會增大惡化概率
int key = p[left];
int i = left, j = right;
while (i < j)
{
while (i < j&&p[j] >= key)
{
--j;
}
p[i] = p[j];
while (i < j&&p[i] <= key)
{
++i;
}
p[j] = p[i];
}
p[i] = key;//很容易忘記這一句
return i;
}
//left right 爲閉區間 nth 爲第n個元素 從1開始
int NthElement(int* p,int left, int right, int nth)
{
assert(nullptr != p);
assert(left >= 0 && right >= 0 && nth > 0);
assert(left <= right&&nth>left&&nth<=right+1);
int index = partition(p, left, right);
if (index > nth - 1)
{
NthElement(p,left,index-1,nth);
}
else if (index < nth - 1)
{
NthElement(p, index+1, right, nth);
}
else
{
return p[index];
}
}
//使用堆(STL priority_queue)來求k個最大的數
const vector<int>* PartSortByqueue(int *p, int len,int k)
{
assert(nullptr != p&&len>0&&k>0&&k<=len);
//先將數組前k個元素建堆
priority_queue<int>* pPr= new priority_queue<int>(p,p+k);
//默認小根堆 最小元素在begin處
assert(nullptr!=pPr);
for (int i = k; k < len; ++k)
{
//新元素比最小元素小 則將該元素彈出 壓入新元素
if (p[k] > pPr->top())
{
pPr->pop();
pPr->push(p[k]);
}
}
vector<int>* pVec = new vector<int>();
pVec->reserve(len);
assert(nullptr!=pVec);
//priority_queue 不提供遍歷與迭代器 只能pop
while (!pPr->empty())
{
pVec->push_back(pPr->top());
pPr->pop();
}
copy(pVec->begin(), pVec->end(), ostream_iterator<int>(cout, " "));
puts("");
delete pPr;
return pVec;
}
//使用STL提供的堆算法 與vector 結合
const vector<int>* PartSortByheap(int *p, int len, int k)
{
assert(nullptr != p&&len>0 && k>0 && k <= len);
vector<int>* pVec=new vector<int>(p,p+k);
//默認小根堆
assert(nullptr != pVec);
make_heap(pVec->begin(), pVec->end(),less<int>());
for (int i = k; i < len; ++i)
{
if (p[i] > (*pVec)[0])
{
//默認也是小根堆
pop_heap(pVec->begin(),pVec->end(),less<int>());
/*
begin() 與end()-1 交換 最小元素已在最末位置
然後在區間first last-1 調用adjust_heap算法
*/
//將末尾元素彈出
pVec->pop_back();
//上邊完成堆得pop過程 下邊完成push過程
pVec->push_back(p[i]);
push_heap(pVec->begin(),pVec->end(),less<int>());
}
}
copy(pVec->begin(), pVec->end(), ostream_iterator<int>(cout, " "));
puts("");
return pVec;
}
const vector<int>* PartSortBymultiset(int *p, int len, int k)
{
assert(nullptr != p&&len>0 && k>0 && k <= len);
multiset<int, less<int>> mset(p,p+k);
for (int i = k; k < len; ++k)
{
if (p[i] > (*mset.begin()))
{
mset.insert(p[i]);
mset.erase(mset.begin());
}
}
vector<int>* pVec = new vector<int>(mset.rbegin(), mset.rend());
assert(nullptr != pVec);
copy(pVec->begin(), pVec->end(), ostream_iterator<int>(cout, " "));
puts("");
return pVec;
}
int main(void)
{
int array[] = { 10,11,9,3,1,5,7,4,2};
int len = sizeof(array) / sizeof(array[0]);
/*
cout << "NthElement :" << NthElement(array, 0, len - 1,2) << endl;
//左邊與右邊不保證有序
for_each(array, array + len, display<int>());
puts("");
*/
delete PartSortByqueue(array,len,3);
delete PartSortByheap(array,len,3);
delete PartSortBymultiset(array,len,3);
return 0;
}</span>