几种查找数组的前K个最小值的算法
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
几种查找数组的前K个最小值的算法
好久没有写博客了,这一段时间主要在准备为将来找工作复习,今天我就总结一下关于如何查找数组的前K个最小值实现方法,查找前K个最小值实现方法很多,主要的思想包括如下的几种:
1、对数组进行排序,然后前K个元素就是需要查找的元素,排序的方法可以采用快速排序,但是我们知道在快速排序中如果已经是有序的数组,采用快速排序的时间复杂度是O(N^2),为了解决这种问题,通常选择随机选择一个数组值pivot作为基准,将数组分为S1 =; pivot,这样就能避免快速排序中存在的问题,或者采用随机选择三个元素,然后取中间值作为基准就能避免快速算法的最差时间复杂度,这种方法的前K个数字是有序的。
2、既然是选择前K个对象,那么就没必要对所有的对象进行排序,可以采用快速选择的思想获得前K个对象,比如首先采用快速排序的集合划分方法划分集合:S1,pivot,S2,然后比较K是否小于S1的个数,如何小于,则直接对S1进行快速排序,如果K的个数超过S1,那么对S2进行快速排序,排序完成之后,取数组的前K 个元素就是数组的前K个最小值。这种实现方法肯定比
第一种的全快速排序要更快速。
3、将数组转换为最小堆的情况,根据最小堆的特性,第一个元素肯定就是数组中的最小值,这时候我们可以
将元素保存起来,然后将最后一个元素提升到第一个元素,重新构建最小堆,这样进行K次的最小堆创建,就
找到了前K个最小值,这是运用了最小堆的特性,实质
上是最小堆的删除实现方法。这种算法的好处是实现了
数组的原地排序,并不需要额外的内存空间。
4、接下来的这种思想有点类似桶排序,首先给定一个K个大小的数组b,然后复制数组a中的前K个数到数组b中,将这K个数当成数组a的前K个最小值,对数组
b创建最大堆,这时候再次比较数组a中的其他元素,如果其他元素小于数组b的最大值(堆顶),则将堆顶的值进行替换,并重新创建最大堆。这样遍历一次数组就找
到了前K个最小元素。这种方法运用了额外的内存空间,特别当选择的K值比较大时,这种方法有待于权衡一下。
这种方法对于海量数据来说是有较好的作用,对于
海量数据不能全部存放在内存中,这时候创建一个较小
的数组空间,然后创建最大堆,从硬盘中读取其他的数据,进而实现前K个数据的查找。
这是比较传统的几种方法,当然还存在其他的选择
方式,我在这边就不阐述了,从上面几种方法的可知,
查找方法都充分运用了运用了数据结构和算法的特性。因此数据结构的灵活运用对算法的实现有很多的好处。下面是我的实现代码,数组中前K个元素我通过打印的方式实现,并没有保存到新的数组中:
#include;
#include;
#include;
#include;
#include;
#define LEN 500000
#define K 100
/*堆的性质*/
#define LEFTSON(i) (2*(i)+1)
#define RIGHTSON(i) (2*((i)+1))
#define PARENT(i) (((i)-1)/2)
void swap(int *a, int *b)
{
assert(a != NULL && b != NULL);
if(a != b)
{
*a = *a ^ *b;
*b = *a ^ *b;
*a = *a ^ *b;
}
}
int partition(int *a, int left, int right) {
int pivot = a[right];
int i = left;
int j = left - 1;
assert(a != NULL);
for(i = left; i ; k)
quickselect(a, left, i - 1, k);
}
}
void QuickSelect(int *a, int size, int k)
{
assert(a != NULL);
quickselect(a, 0, size - 1, k);
}
/*最大堆*/
void max_heapify(int *a, int left, int right) {
int tmp = 0;
int child = left;
int parent = left;
assert(a != NULL);
for(tmp = a[parent]; LEFTSON(parent) ;= 0 ; -- i)
max_heapify(a,i,size - 1);
}
/*最小堆的实现*/
void min_heapify(int *a, int left, int right) {
int child = 0;
int tmp = 0;
int parent = left;
assert(a != NULL);
for(tmp = a[parent]; LEFTSON(parent) ; a[child + 1])
child ++;
if(a[child] ;= 0; -- i)
min_heapify(a, i, size - 1);
}
/*采用快速排序查找*/
void find_Kmin_num_1(int *a , int size, int k) {
int i = 0;
assert(a != NULL);
QuickSort(a, size);
#if 0
for(i = 0; i < k ; ++ i)
printf("%d\t",a[i]);
printf("\n");
#endif
}