您的位置:首页 > 其它

寻找第n个数 与前n个数的几种方法

2016-04-02 20:06 453 查看

寻找第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>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: