寻找第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>
相关文章推荐
- instanceof运算符
- linux下支持伪静态和rewrite的实例
- This file is already open in an editor问题的解决方法
- 软考网络工程师
- leetcode---Remove Duplicates from Sorted Array
- Python简单的爬取网页信息并生成json文件与乱码解决小记
- android:interpolator
- Effective Java读书笔记(三):泛型、枚举、注解、异常
- Problem E: 建立链表(线性表)
- 总结
- struts、hibernate、spring这三个框架和J2EE是什么关系?
- spring事务隔离级别
- shell编程入门
- poj 1017 非常非常经典的贪心的算法
- L1-8. 求整数段和
- April Fools Day Contest 2016 F. Ace It!
- 第十八章读书笔记
- 浅谈动态规划算法设计
- 实践--课程表(仿超级课程表展示课表)
- 集合的遍历