今天练习了几道堆的题目,下面总结两道。
这两道题目基本思想都一致,一个是大根堆,一个是小根堆。
大根堆题目:数组中的第K个最大元素
其实这道题目用其他基本常见的排序做法也可以解决,但是在这里,正好可以选择基于堆排序的方法来实现。
我们也可以使用堆排序来解决这个问题——建立一个大根堆。
做 k - 1 次删除操作后堆顶元素就是我们要找的答案。
部分代码如下:
void maxHeapify(int* a, int i, int heapSize) {
int l = i * 2 + 1, r = i * 2 + 2, largest = i;//l是左孩子,r是右孩子
if (l < heapSize && a[l] > a[largest]) {//左孩子存在且左孩子大于该结点值
largest = l;
}
if (r < heapSize && a[r] > a[largest]) {//右孩子存在且右孩子大于该结点值
largest = r;
}
if (largest != i) {//不相等则是调整过
int t = a[i];
a[i] = a[largest];
a[largest] = t;
maxHeapify(a, largest, heapSize);//对调整交换后的结点继续进行调整
}
}
void buildMaxHeap(int* a, int heapSize) {
for (int i = heapSize / 2; i >= 0; --i) {//i = heapSize / 2的意义是从倒着数第一个非叶子结点的结点开始建堆
maxHeapify(a, i, heapSize);
}
}
int findKthLargest(int* nums, int numsSize, int k) {
int heapSize = numsSize;
buildMaxHeap(nums, heapSize);//调整第一次
for (int i = numsSize - 1; i >= numsSize - (k - 1); --i) {//求第k大,再调整k-1次
int t = nums[0];
nums[0] = nums[i];
nums[i] = t;
--heapSize;//去除首项,将末项放在首项,下面进行堆调整
maxHeapify(nums, 0, heapSize);
}
return nums[0];//调整k-1次后最大的
}
小根堆题目:最小的k个数
其实两道题目用常规做法都不难,大家了解题目后会发现,其实性质一样,都可以用基于堆排序的方法来实现,这道题与上道题基本上一模一样,只是这里采用的是小根堆罢了。
void minHeapify(int* a, int i, int heapSize) {
int l = i * 2 + 1, r = i * 2 + 2, largest = i;//l是左孩子,r是右孩子
if (l < heapSize && a[l] < a[largest]) {//左孩子存在且左孩子小于该结点值
largest = l;
}
if (r < heapSize && a[r] < a[largest]) {//右孩子存在且右孩子小于该结点值
largest = r;
}
if (largest != i) {//不相等则是调整过
int t = a[i];
a[i] = a[largest];
a[largest] = t;
minHeapify(a, largest, heapSize);//对调整交换后的结点继续进行调整
}
}
void buildMinHeap(int* a, int heapSize) {
for (int i = heapSize / 2; i >= 0; --i) {//i = heapSize / 2的意义是从倒着数第一个非叶子结点的结点开始建堆
minHeapify(a, i, heapSize);
}
}
int* getLeastNumbers(int* arr, int arrSize, int k, int* returnSize){
int heapSize = arrSize;
int*mn=(int*)malloc(sizeof(int)*k);
*returnSize=k;
if(k==0)return mn;
int p=0;
buildMinHeap(arr, heapSize);
mn[p++]=arr[0];//这里因为上面已经调整好一次,所以给mn加入一个值
for (int i = arrSize - 1; i >= arrSize - (k - 1); --i) {//再调整k-1次
int t = arr[0];
arr[0] = arr[i];
arr[i] = t;
--heapSize;//去除首项,将末项放在首项,下面进行堆调整
minHeapify(arr, 0, heapSize);
mn[p++]=arr[0];//每调整好一次,为mn添一个值
}
return mn;
}
这两道题目本身题目简单,程序也简单易懂,可以帮助大家很好的理解堆排序的调整过程以及其基本思想。