You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
341 lines
8.4 KiB
341 lines
8.4 KiB
package leo.class04_06;
|
|
|
|
import java.util.PriorityQueue;
|
|
|
|
/**
|
|
* @author Leo
|
|
* @ClassName MyMaxHeap
|
|
* @DATE 2020/11/27 11:01 上午
|
|
* @Description 堆结构
|
|
* 堆结构比堆排序重要
|
|
* 优先级队列[PriorityQueue,默认是小根堆]结构就是堆结构.
|
|
* 完全二叉树:如果一个树是满的就是完全二叉树,如果一棵树不满,也是最后一层,也在变满的路上,如果一个树是从左到右变满的就是完全二叉树.
|
|
* 堆结构:用数组实现的完全二叉树结构,
|
|
* 大根堆:在完全二叉树中,每棵子树的最大值都在顶部
|
|
* 小根堆:在完全二叉树中,每棵子树的最小值都在顶部
|
|
* 堆结构操作:
|
|
* heapInsert 向上调整
|
|
* heapify 向下调整
|
|
* i 左子节点的位置:2*i+1
|
|
* i 右子节点的位置:2*i+2
|
|
* i 父节点的位置:(i-1)/2
|
|
*
|
|
*
|
|
|
|
*/
|
|
public class MyMaxHeap {
|
|
private final int limit;
|
|
private int heapSize;
|
|
private int[] arr;
|
|
|
|
public MyMaxHeap(int limit) {
|
|
this.limit = limit;
|
|
this.heapSize = 0;
|
|
this.arr = new int[limit];
|
|
}
|
|
|
|
public void push(int value) {
|
|
if (this.heapSize >= this.limit) {
|
|
throw new RuntimeException("heap is full");
|
|
}
|
|
this.arr[this.heapSize] = value;
|
|
heapInsert(arr, this.heapSize++);
|
|
}
|
|
|
|
public int pop() {
|
|
if (heapSize == 0) {
|
|
throw new RuntimeException("heap is empty");
|
|
}
|
|
int value = this.arr[0];
|
|
this.swap(arr, 0, --heapSize);
|
|
heapify(arr, 0, heapSize);
|
|
return value;
|
|
}
|
|
|
|
public boolean isEmpty() {
|
|
return heapSize == 0;
|
|
}
|
|
|
|
|
|
/**
|
|
* 将index向上调整
|
|
*/
|
|
private void heapInsert(int[] arr, int index) {
|
|
|
|
while (arr[index] > arr[(index - 1) / 2]) {
|
|
this.swap(arr, index, (index - 1) / 2);
|
|
index = (index - 1) / 2;
|
|
}
|
|
}
|
|
|
|
private void heapify(int[] arr, int index, int heapSize) {
|
|
int left = index << 1 | 1;
|
|
while (left < heapSize) {
|
|
//选择左右哪个子节点,哪个大选择那个
|
|
int largest = left + 1 < heapSize && arr[left + 1] > arr[left] ? left + 1 : left;
|
|
largest = arr[largest] > arr[index] ? largest : index;
|
|
if (largest == index) {
|
|
break;
|
|
}
|
|
swap(arr, index, largest);
|
|
index = largest;
|
|
left = index << 1 | 1;
|
|
}
|
|
}
|
|
|
|
|
|
private void swap(int[] arr, int i, int j) {
|
|
if (i == j || arr[i] == arr[j]) {
|
|
return;
|
|
}
|
|
arr[i] = arr[i] ^ arr[j];
|
|
arr[j] = arr[i] ^ arr[j];
|
|
arr[i] = arr[i] ^ arr[j];
|
|
}
|
|
|
|
}
|
|
|
|
class MyMaxHeap1 {
|
|
|
|
private int size;
|
|
private final int limit;
|
|
private int[] arr;
|
|
|
|
|
|
MyMaxHeap1(int limit) {
|
|
this.limit = limit;
|
|
this.arr = new int[limit];
|
|
this.size = 0;
|
|
}
|
|
|
|
public boolean isEmpty() {
|
|
return size == 0;
|
|
}
|
|
|
|
public void push(int value) {
|
|
if (size == limit) {
|
|
throw new RuntimeException("heap is full");
|
|
}
|
|
arr[size] = value;
|
|
heapInsert(arr, size++);
|
|
}
|
|
|
|
public int pop() {
|
|
if (size == 0) {
|
|
throw new RuntimeException("heap is empty!");
|
|
}
|
|
int value = this.arr[0];
|
|
this.swap(arr, 0, --size);
|
|
heapify(arr, 0, size);
|
|
return value;
|
|
}
|
|
|
|
private void heapify(int[] arr, int i, int size) {
|
|
int left = i << 1 | 1;
|
|
while (left < size) {
|
|
int largest = left + 1 < size && arr[left + 1] > arr[left] ? left + 1 : left;
|
|
largest = arr[i] >= arr[largest] ? i : largest;
|
|
if (largest == i) {
|
|
break;
|
|
}
|
|
swap(arr, largest, i);
|
|
i = largest;
|
|
left = i << 1 | 1;
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
private void heapInsert(int[] arr, int i) {
|
|
while (arr[i] > arr[(i - 1) / 2]) {
|
|
swap(arr, i, (i - 1) / 2);
|
|
i = (i - 1) / 2;
|
|
}
|
|
|
|
}
|
|
|
|
private void swap(int[] arr, int i, int j) {
|
|
if (i == j || arr[i] == arr[j]) {
|
|
return;
|
|
}
|
|
arr[i] = arr[i] ^ arr[j];
|
|
arr[j] = arr[i] ^ arr[j];
|
|
arr[i] = arr[i] ^ arr[j];
|
|
}
|
|
}
|
|
|
|
class MyMaxHeap2{
|
|
|
|
private int size;
|
|
private int[] arr;
|
|
private final int limit;
|
|
|
|
MyMaxHeap2(int limit) {
|
|
this.limit = limit;
|
|
this.size = 0;
|
|
this.arr = new int[limit];
|
|
}
|
|
|
|
|
|
public boolean isEmpty() {
|
|
return size == 0;
|
|
}
|
|
|
|
public void push(int value) {
|
|
if (size == limit) {
|
|
throw new RuntimeException("heap is full");
|
|
}
|
|
this.arr[size] = value;
|
|
this.heapInsert(arr, size++);
|
|
}
|
|
|
|
public int pop() {
|
|
int value = this.arr[0];
|
|
swap(this.arr, 0, --this.size);
|
|
heapify(arr, 0, this.size);
|
|
return value;
|
|
}
|
|
|
|
private void heapify(int[] arr, int i, int size) {
|
|
int left = i << 1 | 1;
|
|
while (left < size) {
|
|
int largest = left + 1 < size && arr[left + 1] > arr[left] ? left + 1 : left;
|
|
largest = arr[largest] > arr[i] ? largest : i;
|
|
if (largest == i) {
|
|
break;
|
|
}
|
|
swap(arr, largest, i);
|
|
i = largest;
|
|
left = i << 1 | 1;
|
|
}
|
|
}
|
|
|
|
private void heapInsert(int[] arr, int i) {
|
|
while (arr[i] > arr[(i - 1) / 2]) {
|
|
swap(arr, i, (i - 1) / 2);
|
|
i = (i - 1) / 2;
|
|
}
|
|
}
|
|
|
|
|
|
private void swap(int[] arr, int i, int j) {
|
|
if (i == j || arr[i] == arr[j]) {
|
|
return;
|
|
}
|
|
arr[i] = arr[i] ^ arr[j];
|
|
arr[j] = arr[i] ^ arr[j];
|
|
arr[i] = arr[i] ^ arr[j];
|
|
}
|
|
}
|
|
|
|
class MyMaxHeap3 {
|
|
private int size;
|
|
private int[] arr;
|
|
private final int limit;
|
|
|
|
public MyMaxHeap3(int limit) {
|
|
this.limit = limit;
|
|
this.size = 0;
|
|
this.arr = new int[limit];
|
|
}
|
|
|
|
public void push(int value) {
|
|
if (size == limit) {
|
|
throw new RuntimeException("heap is full");
|
|
}
|
|
arr[size] = value;
|
|
heapInsert(arr, size++);
|
|
|
|
}
|
|
|
|
public int pop() {
|
|
if (size == 0) {
|
|
throw new RuntimeException("heap is empty");
|
|
}
|
|
int value = arr[0];
|
|
swap(arr, 0, --size);
|
|
heapify(arr, 0, size);
|
|
return value;
|
|
}
|
|
|
|
private void heapify(int[] arr, int i, int heapSize) {
|
|
int left = i << 1 | 1;
|
|
while (left < heapSize) {
|
|
int largest = left + 1 < heapSize && arr[left + 1] > arr[left] ? left + 1 : left;
|
|
largest = arr[largest] > arr[i] ? largest : i;
|
|
if (largest == i) {
|
|
break;
|
|
}
|
|
this.swap(arr, largest, i);
|
|
i = largest;
|
|
left = i << 1 | 1;
|
|
}
|
|
}
|
|
|
|
private void heapInsert(int[] arr, int index) {
|
|
while (arr[index] > arr[(index - 1) / 2]) {
|
|
swap(arr, index, (index - 1) / 2);
|
|
index = (index - 1) / 2;
|
|
}
|
|
}
|
|
|
|
public boolean isEmpty() {
|
|
return size == 0;
|
|
}
|
|
|
|
public void swap(int[] arr, int i, int j) {
|
|
if (i == j || arr[i] == arr[j]) {
|
|
return;
|
|
}
|
|
arr[i] = arr[i] ^ arr[j];
|
|
arr[j] = arr[i] ^ arr[j];
|
|
arr[i] = arr[i] ^ arr[j];
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
class Main{
|
|
|
|
public static void main(String[] args){
|
|
|
|
int testTimes = 1000;
|
|
int range = 50;
|
|
System.out.println("start!");
|
|
PriorityQueue<Integer> queue = new PriorityQueue<>((a,b)-> {return b-a;});
|
|
MyMaxHeap3 heap = new MyMaxHeap3(testTimes);
|
|
for (int i = 0; i < testTimes; i++) {
|
|
if (heap.isEmpty()) {
|
|
int num = (int) ((range * Math.random() + 1) - (range * Math.random() + 1));
|
|
queue.add(num);
|
|
heap.push(num);
|
|
}else {
|
|
if (Math.random() < 0.5) {
|
|
int num = (int) ((range * Math.random() + 1) - (range * Math.random() + 1));
|
|
queue.add(num);
|
|
heap.push(num);
|
|
}else{
|
|
Integer poll = queue.poll();
|
|
int pop = heap.pop();
|
|
if (poll != pop) {
|
|
System.out.println(poll);
|
|
System.out.println(pop);
|
|
System.out.println("fuck!");
|
|
return;
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|
|
System.out.println("end!");
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|