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

寻找第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>


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值