题目
1.题目要求:
给定一个数组,用最短时间求其中最大的k个数。
编写函数
void FindMax(int Array[],int k,int size,int kMax[])
//k为需要查找的最大元素个数,size为数组大小,kMax存储最大的k个元素
有一个大数组,要求找出数组的最大值、最小值。要求用最短的时间完成最大值与最小值的查找。
2.题目分析:
这里我用的是堆排序(优先队列)
因为查找出最大值只要用大根堆一个个弹出根节点就可以
代码分析:
1.向上调整堆的构造:
解析都写注释里了bushi
void swap(int* a, int* b) {
int t = *a;
*a = *b;
*b = t;
}
// 向上调整堆
void heapify(int arr[], int n, int i) {//把大的放在根节点 下滤 大根堆的构造
int smallist = i;
int left = 2 * i + 1;//左节点
int right = 2 * i + 2;//右节点
//n是大小
if (left < n && arr[left] > arr[smallist])
smallist = left;
if (right < n && arr[right] > arr[smallist])
smallist = right;
if (smallist != i) {
//交换
swap(&arr[i], &arr[smallist]); //与根节点交换 这时候的根节点已经与子节点交换
heapify(arr, n, smallist); //这个时候的smallist是一个较小的节点
}
}
关于堆的构造可以看这两个:
【从堆的定义到优先队列、堆排序】 10分钟看懂必考的数据结构——堆
ps:讲的很好怎么就这么少人点赞呢,不理解
2.查找最大数
// 查找最大的K个数
void FindMax(int Array[], int k, int size, int kMax[]) {
//传入数组 ,传入需要找的最大k的个数 传入数组的大小 传入需要保存的数组
// 构建最小堆
for (int i = size / 2 - 1; i >= 0; i--) //从中间开始 这时候的i需要-1 数组从零开始
heapify(Array, size, i);// 从下面的节点开始向上构建堆结构 都是每个根节点的传入
//最上面的根节点i是零
// 提取最大的K个数
for (int i = 0; i < k && i < size; i++) {
kMax[i] = Array[0];
Array[0] = Array[size - i - 1];//把最右叶子节点作为根节点(最后一个元素)
//比如i=0,size=7时
/* 15 7
/ \ / \ / \
10 13 -> 10 13 -> 10 13
/ \ / \ / \ / \ / \ /
4 5 6 7 4 5 6 7 4 5 6 */
size--;
heapify(Array, size, 0);//每次弹出后要重新构建堆
}
}
3.完整代码
#include <stdio.h>
#include <stdlib.h>
// 交换两个元素
void swap(int* a, int* b) {
int t = *a;
*a = *b;
*b = t;
}
// 向上调整堆
void heapify(int arr[], int n, int i) {//把大的放在根节点 下滤 大根堆的构造
int smallist = i;
int left = 2 * i + 1;//左节点
int right = 2 * i + 2;//右节点
//n是大小
if (left < n && arr[left] > arr[smallist])
smallist = left;
if (right < n && arr[right] > arr[smallist])
smallist = right;
if (smallist != i) {
//交换
swap(&arr[i], &arr[smallist]); //与根节点交换 这时候的根节点已经与子节点交换
heapify(arr, n, smallist); //这个时候的smallist是一个较小的节点
}
}
// 查找最大的K个数
void FindMax(int Array[], int k, int size, int kMax[]) {
//传入数组 ,传入需要找的最大k的个数 传入数组的大小 传入需要保存的数组
// 构建最小堆
for (int i = size / 2 - 1; i >= 0; i--) //从中间开始 这时候的i需要-1 数组从零开始
heapify(Array, size, i);// 从下面的节点开始向上构建堆结构 都是每个根节点的传入
//最上面的根节点i是零
// 提取最大的K个数
for (int i = 0; i < k && i < size; i++) {
kMax[i] = Array[0];
Array[0] = Array[size - i - 1];//把最右叶子节点作为根节点(最后一个元素)
//比如i=0,size=7时
/* 15 7
/ \ / \ / \
10 13 -> 10 13 -> 10 13
/ \ / \ / \ / \ / \ /
4 5 6 7 4 5 6 7 4 5 6 */
size--;
heapify(Array, size, 0);//每次弹出后要重新构建堆
}
}
// 测试
int main() {
int Array[] = { 3, 2, 1, 5, 6, 4 };
int k = 3;
int kMax[3];
FindMax(Array, k, sizeof(Array) / sizeof(Array[0]), kMax);
for (int i = 0; i < k; i++) {
printf("%d ", kMax[i]);
}
return 0;
}
ps:
构建堆的时间复杂度为O(logN)
只是很简单的对于堆排序的应用,查查资料什么的包学会的
1230

被折叠的 条评论
为什么被折叠?



