/**
* @Description: topk问题-堆排序
* @Author: Jaryn
* 1、使用前K个元素构成小顶堆
* 2、后k的元素如果大于堆顶元素,就交换,然后调整树
* @Date: 2019/11/21 14:57
*/
public class TopK_HeapSort {
public static void main(String[] args) {
int[] data = new int[]{100,1,3,4,2,8,9,5,6,7,32,56,99,3,4,8,7,23,87,32,4,6};
int kthLargest = findKthLargest(data, 6);
System.out.println(kthLargest);
}
public static int findKthLargest(int[] nums, int k) {
int[] tree = new int[k];
for(int i=0; i<k; i++) {
tree[i] = nums[i];
}
head(tree, k);
for(int i=k; i<nums.length; i++) {
if(tree[0] < nums[i]) {
tree[0] = nums[i];
adjustTree(tree, k, 0);
}
}
return tree[0];
}
public static void head(int[] tree, int k) {
for(int i=(k-1)/2; i>=0; i--) {
adjustTree(tree, k, i);
}
}
/**
*
* 小顶堆从i节点开始调整
* @param tree
* @param k 堆的大小
* @param i 准备操作的节点的下标
*/
public static void adjustTree(int[] tree, int k, int i) {
// 因为调起递归,所以添加判断
if(i >= k) {
return;
}
// 确定i节点的左右孩子
int left = 2*i+1;
int right = 2*i+2;
int min = i;
// 判断左孩子和父节点的大小
if(left < k && tree[left] < tree[min]) {
min = left;
}
// 判断右孩子和父节点的大小
if(right < k && tree[right] < tree[min]) {
min = right;
}
if(min != i) {
// 交换节点,但是可能交换后会造成树的结构不符合规范,所以需要递归处理;
swap(tree, min, i);
// 因为父节点i下放一级,可能造成原先的结构
adjustTree(tree, k, min);
}
}
/**
* 交换元素
* @param tree
* @param i
* @param j
*/
public static void swap(int[] tree, int i, int j) {
int temp = tree[i];
tree[i] = tree[j];
tree[j] = temp;
}
}
topk问题-堆排序
最新推荐文章于 2022-11-22 13:44:19 发布