前提:左右子树必须已经是一个堆
如某节点的左右子树都是大堆,将这个树向下调整成大堆
public void adjustDown(int[] array, int begin, int size) {
int parent = begin;
int child = parent * 2 + 1;
while (child < size) {
if (child + 1 < array.length && array[child + 1] > array[child]) {
child++;
}
if (array[parent] < array[child]) {
int temp = array[parent];
array[parent] = array[child];
array[child] = temp;
parent = child;
child = child*2+1;
}else{
break;
}
}
}
public class MyHeap {
public int[] elem;
public int useSize;
public MyHeap() {
this.elem = new int[10];
}
//建一个最大堆
public void creatHeap(int[] array){
for (int i = 0 ; i < array.length; i++) {
this.elem[i] = array[i];
this.useSize++;
}
//确定最后一棵子树的父树
int child = this.useSize-1;
int parent = (child-1)/2;
//对于每棵子树进行调换大小的操作
for( ;parent>=0;parent--){
adjustDown(parent,this.useSize);
}
}
//向下调整
public void adjustDown(int parent,int size){
int child = parent*2+1;
while(child < size) {
if (child + 1 < len && this.elem[child + 1] > this.elem[child]) {
child++;
}
if (this.elem[parent] < this.elem[child]) {
int temp = this.elem[parent];
this.elem[parent] = this.elem[child];
this.elem[child] = temp;
parent = child;
child = parent * 2 + 1;
} else {
break;
}
}
}
前提:这个树已经是一个堆
如某树是一个大堆
向上调整用于 入堆或改变原来堆的叶子节点,再将其变为大堆
public void adjustUp(int[] arrays, int child){
int parent = (child-1)/2;
while(child > 0){
if(arrays[parent] < arrays[child]){
int temp = arrays[parent];
arrays[parent] = arrays[child];
arrays[child] = temp;
child = parent;
parent = (child-1)/2;
}else{
break;
}
}
}
数组尾插,不够扩容,向上转型
//this.elem已经是一个大堆啦
public void adjustUp(int child){
int parent = (child-1)/2;
while(child > 0){
if(this.elem[child] > this.elem[parent]){
int temp = this.elem[child];
this.elem[child] = this.elem[parent];
this.elem[parent] = temp;
child = parent;
parent = (child-1)/2;
}else{
break;
}
}
}
public void push(int val){
if(isFull()){
this.elem = Arrays.copyOf(this.elem,2*this.elem.length);
}
this.elem[this.useSize] = val;
this.useSize++;
adjustUp(this.useSize-1);
}
public boolean isFull(){
return this.useSize == this.elem.length;
}
//this.elem是一个大堆
public void pop(){
if(isEmpty()){
return;
}
int temp = this.elem[0];
this.elem[0] = this.elem[this.useSize -1];
this.elem[this.useSize -1] = temp;
this.useSize--;
adjustDown(0,this.useSize);
}
public boolean isEmpty(){
return this.useSize == 0;
}
默认是一个小堆
PriorityQueue<Integer> maxHeap = new PriorityQueue<>();
如果堆中的元素无法直接比较的话,可以用Java对象比较的两种方法
class Student {
private String name;
private int age;
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
class AgeComparator implements Comparator<Student>{
@Override
public int compare(Student o1, Student o2) {
//o1是前面的,o2是后面的
//从小到大
return o1.getAge()-o2.getAge();
//从大到小
// return o2.getAge()-o1.getAge();
}
}
public static void main(String[] args) {
//建最大堆
PriorityQueue<Student> maxHeap = new PriorityQueue<>(new AgeComparator());
maxHeap.offer(new Student("dong",18));
maxHeap.offer(new Student("gang",20));
maxHeap.offer(new Student("hui",16));
System.out.println(maxHeap);
}
public static void main(String[] args) {
PriorityQueue<Student> heap = new PriorityQueue<>(new Comparator<Student>() {
@Override
public int compare(Student o1, Student o2) {
return o1.getAge()-o2.getAge();
}
});
}
class Student implements Comparable<Student>{
private String name;
private int age;
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
@Override
public int compareTo(Student o) {
//建小堆
return this.getAge()-o.getAge();
//建大堆
return o.getAge()-this.getAge();
}
}
public static void main(String[] args) {
Student student1 = new Student("拉塞尔",29);
Student student2 = new Student("亚历山大",27);
Student[] students = {
student1,student2};
Arrays.sort(students);
System.out.println(Arrays.toString(students));
}
一组数据中找前k个最大(最小)的数
public PriorityQueue<Integer> topK(int[] array,int k){
PriorityQueue<Integer> maxHeap = new PriorityQueue<>(k, new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return o2-o1;
}
});
for (int i = 0; i < array.length; i++) {
if(maxHeap.size() < k){
maxHeap.offer(array[i]);
}else{
if(maxHeap.peek()>array[i]){
maxHeap.poll();
maxHeap.offer(array[i]);
}
}
}
return maxHeap;
}
https://leetcode-cn.com/problems/find-k-pairs-with-smallest-sums/
public List<List<Integer>> kSmallestPairs(int[] nums1, int[] nums2, int k){
PriorityQueue<List<Integer>> maxHeap = new PriorityQueue<>(k, new Comparator<List<Integer>>() {
@Override
public int compare(List<Integer> o1, List<Integer> o2) {
return (o2.get(0)+o2.get(1)) - (o1.get(0)+o1.get(1));
}
});
for (int i = 0; i < nums1.length; i++) {
for (int j = 0; j < nums2.length; j++) {
if(maxHeap.size() < k){
List<Integer> list = new LinkedList<>();
list.add(nums1[i]);
list.add(nums2[j]);
maxHeap.offer(list);
}else{
List<Integer> list = maxHeap.peek();
int count = list.get(0) + list.get(1);
if(nums1[i] + nums2[j] < count){
List<Integer> list1 = new LinkedList<>();
list1.add(nums1[i]);
list1.add(nums2[j]);
maxHeap.poll();
maxHeap.offer(list1);
}
}
}
}
List<List<Integer>> list = new LinkedList<>();
for (int i = 0; i < k && !maxHeap.isEmpty(); i++) {
list.add(maxHeap.poll());
}
return list;
}
此时堆顶元素就是这个数组第第k小的元素
从小到大排列,此时this.elem是一个大堆了!!!
public void sort(){
int end = this.useSize-1;
while(end>0) {
int temp = this.elem[0];
this.elem[0] = this.elem[end];
this.elem[end] = temp;
adjustDown(this.elem, 0, end);
end--;
}
}
认真生活,就能找到生活藏起来的糖果。