堆排序--topk问题

求TopK问题—堆排序

问题:求一个N个元素的数组中前K大的数,或者前K小的数、
解决思路:使用堆排序;
求前K大的数----建小堆:首先从数组的前K个数中构建一个小堆,堆顶的元素就是K个数中的最小值,然后将后面N-K个元素依次和堆顶元素比较,如果
大于
堆顶的值就替换堆顶元素。这样遍历后就找到了前K个值。

求前K小的数—建大堆:从数组前K个中建大堆,堆顶的元素是目前的最大值,然后用其余N-K个元素和堆顶的元素比较,比堆顶元素小的替换,然后调整堆。

void adjustDown(int* a, int parent, int size)
{
	int child = 2 * parent + 1;

	while (child < size)
	{
		if (child + 1 < size && a[child + 1] < a[child])
		{
			child++;
		}

		if (a[parent] > a[child])
		{
			int tmp = a[parent];
			a[parent] = a[child];
			a[child] = tmp;

			parent = child;
			child = 2 * parent + 1;
		}
		else {
			break;
		}
	}
}

int* heapsort(int* arr, int size, int topK)
{
	if (topK > size)
	{
		return nullptr;
	}

	int* newArr = new int[topK];
	for (int i = 0; i < topK; ++i)
	{
		newArr[i] = arr[i];
	}

	// 建堆

	for (int i = (topK - 2) / 2; i >= 0; i--)
	{
		adjustDown(newArr, i, topK);
	}


	//此时已经是有个有序的小堆了,
	//然后把剩下size-topK个元素和堆顶元素比较,小于堆顶的入堆,然后调整堆

	for (int i = topK; i < size; i++)
	{
		if (arr[i] > newArr[0])
		{
			newArr[0] = arr[i];
			adjustDown(newArr, 0, topK);
		}
	}

	return newArr;
}

int main()
{
	int arr[10] = { 5, 3, 6, 1, 2 ,4, 8, 9, 7, 10};
	int k = 5;

	int* ret = heapsort(arr, 10, 5);
	for (int i = 0; i < 5; i++)
	{
		printf("%d ", ret[i]);
	}

	return 0;
}

你可能感兴趣的:(数据结构,c/c++,面试题,排序算法,算法,数据结构)