算法笔记:堆排序2.0

由于第一次写博客的狼狈(写了一堆话,忘了保存,导致重写),接下来写准备以(题目-分析-代码)的形式去写。

题目一:寻找一组数据中第K大的数

分析:

题目描述很简单,完全可以将所有的数据从大到小进行排序,选取第K个数,便可以解决我们的问题,这样的话,时间复杂度就将取决于我们排序算法的时间复杂度。排序里,快排和堆排都是不错的选择,时间复杂度o(NlogN)

但是其实题目一并没有要求我们要把所有数据有序啊,直接粗暴对所有数据进行排肯定效率不是最佳。

既然只找第K大的数,我们只需找到最大的K个数中最小的数!
K个节点的小根堆的根结点,正好符合我们的要求。

至于如何确最大K个数,我们可以直接选取,给的数据的前K个数,建一个小根堆,从K+1个元素开始到最后一个元素,将它与前面排序最小的元素进行比较,如果小于,不做处理,大于的话,把它与最小的元素交换,重新排序。当所有元素处理过后,我们便得到一个有最大K个的小根堆,选取他们的最小值(根结点),题目便解决了。

按照我们上边的方法,我最多执行(N-K+1)次K个元素的堆排,时间复杂度o((N-K+1)logK),当N>>K的时候近似o(NlogK)

代码

  1. 建堆
//调整堆
template<typename ElemType> void AdjustHeap(ElemType *array,const int &index,int end)
{
	bool flag = true;
	int temp;
	int begin = index;
	while (index-1+(begin-index+1)* 2 <= end&&flag)
	{
		if (array[begin] > array[begin * 2])
		{
			temp = begin * 2;
		}
		else
		{
			temp = begin;
		}

		if (begin * 2 + 1 <= end)
		{
			if (array[begin * 2 + 1] <array[begin * 2])
			{
				temp = begin * 2 + 1;
			}

		}

		if (begin == temp)
		{
			flag = false;
		}
		else
		{
			swap(array,begin, temp);
			begin = temp;
		}
	}
}


//建堆
template<typename ElemType> void CreateHeap(ElemType *array,const int &begin,const int &end)
{
	int distance = end - begin;
	for (int i = begin + distance / 2+1; i >= begin; i--)
	{
		AdjustHeap(array,i,end);
	}
}


//交换数据
template<typename ElemType> void  swap(ElemType *array, const int index1, const int index2)
{
	array[index1] = array[index1] ^ array[index2];
	array[index2] = array[index1] ^ array[index2];
	array[index1] = array[index1] ^ array[index2];  
}

2.选取第K大的数

#include "HeapSort2.0.h"
#include <iostream>
#include <cstdlib>

///      选取数据中第K大的数
///      @param elem    储存数据的数据指针  
///      @param n       数据量
///      @param k       选取的第K大的数
///      @param begin   数据储存开始的索引
///      @return        第K大的数  
  
template<typename ElemType> ElemType SelectKMaxNum(ElemType *elem,int n,int k,int begin)
{
	CreateHeap(elem, begin, k+begin-1);
	for (int i = k + 1; i <= n; i++)
	{
		if (elem[begin] < elem[i])
			swap(elem, begin, i);
		AdjustHeap(elem, begin, k);
	}
	return elem[begin];
}
int main()
{
	//数据开始的索引为1
	int elem[11] = { 0,12,15,89,3,64,8,9,6,3,2 };
	
	std::cout <<SelectKMaxNum(elem,10,3,1)<< std::endl;
	
	std::system("pause");
}

运行结果:

这里写图片描述:

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值