您的位置:首页 > 其它

郭郭自学笔记(2):堆排序2.0

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

题目一:寻找一组数据中第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)

代码

建堆

//调整堆
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");
}


运行结果:


:
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: