找出无序数组中最小的前k个数

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/WUDAIJUN/article/details/8460439
/*
	DJ.W 2013.1.3
	算法描述:找出一无序整型数组arr[n]中最小的前k个数
	算法思路:为k个元素建一个大顶堆min[k],初始化为数组arr的前k个元素
			  调整这k个元素使其满足大顶堆性质
			  此时min[0]为大顶堆中最大的元素,依次用arr[j](k<=j<n)与min[0]相比较
			  如果arr[j]小于min[0] 则将min[0]换为arr[j] 并调整大顶堆 继续向后比较
			  最终min[k]即为所求
	算法复杂度:初始建立k个元素的大顶堆复杂度O(k) 之后比较和调整复杂度O(n-k+(n-k)*lgk)
				即算法复杂度为O(n+(n-k)*lgk)
*/

#include<iostream>
using namespace std;

/*
	堆调整算法 从pos出开始向下调整 使得以pos为根的子树满足大顶堆性质
				前提是pos的孩子子树已经满足大顶堆性质
*/
void ShiftDown(int*arr, int pos, int maxIndex)
{
	//调整算法迭代版	
	int temp = arr[pos];
	for (int child = 2*pos+1; child<=maxIndex; child = child*2+1)
	{
		//使child指向两个子节点中大的那一个
		if (child<maxIndex && arr[child]<arr[child+1])
			++child;

		//如果子节点比父节点的值大 则交换并继续向下调整
		if (arr[child] > temp)
		{
			arr[pos] = arr[child];
			pos = child;
		}
		else
			break;
	}
	arr[pos] = temp;
	
	//调整算法递归版
	/*
	int leftchild = 2*pos+1;
	int rightchild = 2*pos+2;
	int maxchild;

	if (leftchild > maxIndex)
		return;

     //得到值更大的孩子的下标
	if (leftchild<maxIndex && arr[leftchild] < arr[rightchild])
		maxchild = rightchild;
	else
		maxchild = leftchild;

	//如果孩子中最大的值比pos的值大 则替换并继续调整
	if (arr[maxchild] > arr[pos])
	{
		int temp = arr[maxchild];
		arr[maxchild] = arr[pos];
		arr[pos] = temp;

		ShiftDown(arr, maxchild, maxIndex);
	}
	*/
}
bool MinK(int* arr, int size, int k, int* &pRet)
{
	if (k > size)
		return false;

	pRet = new int[k];
	
	//初始化堆
	for (int i=0; i<k; i++)
		pRet[i] = arr[i];

	//调整为大顶堆
	for (int j=(k-1)/2; j>=0; j--)
		ShiftDown(pRet, j, k);
	
	//依次用arr[k...n-1]和堆中最大元素比较
	for (i=k; i<size; i++)
	{
		//如果arr[i]更小 则更新pRet[0] 调整堆 
		if (arr[i] < pRet[0])
		{
			pRet[0] = arr[i];
			ShiftDown(pRet, 0, k-1);
		}
	}
	return true;
}

int main()
{
	int a[6] = {4, 1, 5, 2, 3, 0};
	int* pMinK = NULL;

	MinK(a, 6, 3, pMinK);

	cout<<"原数组为: "<<endl;
	for (int i=0; i<6; i++)
		cout<<a[i]<<" ";
	cout<<endl;

	cout<<"最小的3个数为"<<endl;
	for (i=0; i<3; i++)
		cout<<pMinK[i]<<" ";
	cout<<endl;

	delete []pMinK;
	
	return 0;
}

猜你喜欢

转载自blog.csdn.net/WUDAIJUN/article/details/8460439