提交 5c1d48b2 编写于 作者: GreyZeng's avatar GreyZeng

update heap code

上级 e3d0e704
package snippet;
import java.util.Comparator;
import java.util.PriorityQueue;
/**
* 什么是完全二叉树
* 如果一个树是满的,它是完全二叉树,即便不是满的,也是从左到右依次变满的
* <p>
* 堆结构
* <p>
* 1)堆结构就是用数组实现的完全二叉树结构
* <p>
* 2)完全二叉树中如果每棵子树的最大值都在顶部就是大根堆
* <p>
* 3)完全二叉树中如果每棵子树的最小值都在顶部就是小根堆
* <p>
* 4)堆结构的heapInsert与heapify操作
* <p>
* 5)堆结构的增大和减少
* <p>
* 6)Java中的PriorityQueue,就是堆结构
* <p>
* 用数组表示堆的两种情况
* <p>
* 如果使用数组0位置,对于i位置来说,它的:
* <p>
* 左孩子 2 * i + 1
* <p>
* 右孩子 2 * i + 2
* <p>
* 父节点 (i - 1)/ 2
* <p>
* 如果不用0位置,对于i位置来说,它的:
* <p>
* 左孩子 2 * i 即:i << 1
* <p>
* 右孩子 2 * i + 1 即:i << 1 | 1
* <p>
* 父节点 i / 2 即:i >> 1
* <p>
* 大根堆:完全二叉树中,每棵树的最大值都是头节点的值
*
* heapify和heapInsert都是logN级别的复杂度,因为N个节点的二叉树高度是logN
*/
public class Code_0026_Heap {
public static class MyMaxHeap {
private int[] heap;
private final int limit;
private int heapSize;
public MyMaxHeap(int limit) {
heap = new int[limit];
this.limit = limit;
heapSize = 0;
}
public boolean isEmpty() {
return heapSize == 0;
}
public boolean isFull() {
return heapSize == limit;
}
public void push(int value) {
if (heapSize == limit) {
throw new RuntimeException("heap is full");
}
heap[heapSize] = value;
// value heapSize
heapInsert(heap, heapSize++);
}
public int pop() {
int ans = heap[0];
swap(heap, 0, --heapSize);
heapify(heap, 0, heapSize);
return ans;
}
private void heapInsert(int[] arr, int index) {
while (arr[index] > arr[(index - 1) / 2]) {
swap(arr, index, (index - 1) / 2);
index = (index - 1) / 2;
}
}
private void heapify(int[] arr, int index, int heapSize) {
int left = index * 2 + 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, largest, index);
index = largest;
left = index * 2 + 1;
}
}
private void swap(int[] arr, int i, int j) {
int tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
}
public static class RightMaxHeap {
private int[] arr;
private final int limit;
private int size;
public RightMaxHeap(int limit) {
arr = new int[limit];
this.limit = limit;
size = 0;
}
public boolean isEmpty() {
return size == 0;
}
public boolean isFull() {
return size == limit;
}
public void push(int value) {
if (size == limit) {
throw new RuntimeException("heap is full");
}
arr[size++] = value;
}
public int pop() {
int maxIndex = 0;
for (int i = 1; i < size; i++) {
if (arr[i] > arr[maxIndex]) {
maxIndex = i;
}
}
int ans = arr[maxIndex];
arr[maxIndex] = arr[--size];
return ans;
}
}
public static class MyComparator implements Comparator<Integer> {
@Override
public int compare(Integer o1, Integer o2) {
return o2 - o1;
}
}
public static void main(String[] args) {
// 小根堆
PriorityQueue<Integer> heap = new PriorityQueue<>(new MyComparator());
heap.add(5);
heap.add(5);
heap.add(5);
heap.add(3);
// 5 , 3
System.out.println(heap.peek());
heap.add(7);
heap.add(0);
heap.add(7);
heap.add(0);
heap.add(7);
heap.add(0);
System.out.println(heap.peek());
while (!heap.isEmpty()) {
System.out.println(heap.poll());
}
int value = 1000;
int limit = 100;
int testTimes = 1000000;
for (int i = 0; i < testTimes; i++) {
int curLimit = (int) (Math.random() * limit) + 1;
MyMaxHeap my = new MyMaxHeap(curLimit);
RightMaxHeap test = new RightMaxHeap(curLimit);
int curOpTimes = (int) (Math.random() * limit);
for (int j = 0; j < curOpTimes; j++) {
if (my.isEmpty() != test.isEmpty()) {
System.out.println("Oops!");
}
if (my.isFull() != test.isFull()) {
System.out.println("Oops!");
}
if (my.isEmpty()) {
int curValue = (int) (Math.random() * value);
my.push(curValue);
test.push(curValue);
} else if (my.isFull()) {
if (my.pop() != test.pop()) {
System.out.println("Oops!");
}
} else {
if (Math.random() < 0.5) {
int curValue = (int) (Math.random() * value);
my.push(curValue);
test.push(curValue);
} else {
if (my.pop() != test.pop()) {
System.out.println("Oops!");
}
}
}
}
}
System.out.println("finish!");
}
}
\ No newline at end of file
......@@ -14,7 +14,7 @@ import java.util.PriorityQueue;
* 加k个数进堆,然后再加入一个,弹出一个,最后堆里面剩下的继续弹出即可
* 时间复杂度:O(N*logK)
*/
public class Code_0028_DistanceLessK {
public class Code_DistanceLessK {
public static void sortedArrDistanceLessK(int[] arr, int k) {
k = Math.min(arr.length - 1, k);
PriorityQueue<Integer> heap = new PriorityQueue<>();
......
package snippet;
import java.util.PriorityQueue;
/**
* 笔记: 什么是完全二叉树 如果一个树是满的,它是完全二叉树,即便不是满的,也是从左到右依次变满的
*
* <p>堆结构
*
* <p>1)堆结构就是用数组实现的完全二叉树结构
*
* <p>2)完全二叉树中如果每棵子树的最大值都在顶部就是大根堆
*
* <p>3)完全二叉树中如果每棵子树的最小值都在顶部就是小根堆
*
* <p>4)堆结构的heapInsert与heapify操作
*
* <p>5)堆结构的增大和减少
*
* <p>6)Java中的PriorityQueue,就是堆结构
*
* <p>用数组表示堆的两种情况
*
* <p>如果使用数组0位置,对于i位置来说,它的:
*
* <p>左孩子 2 * i + 1
*
* <p>右孩子 2 * i + 2
*
* <p>父节点 (i - 1)/ 2
*
* <p>如果不用0位置,对于i位置来说,它的:
*
* <p>左孩子 2 * i 即:i << 1
*
* <p>右孩子 2 * i + 1 即:i << 1 | 1
*
* <p>父节点 i / 2 即:i >> 1
*
* <p>大根堆:完全二叉树中,每棵树的最大值都是头节点的值
*
* <p>heapify和heapInsert都是logN级别的复杂度,因为N个节点的二叉树高度是logN
*/
public class Code_Heap {
public static class MyMaxHeap {
private int[] heap;
private final int limit;
private int heapSize;
public MyMaxHeap(int limit) {
heap = new int[limit];
this.limit = limit;
heapSize = 0;
}
public boolean isEmpty() {
return heapSize == 0;
}
public boolean isFull() {
return heapSize == limit;
}
public void push(int value) {
if (heapSize == limit) {
throw new RuntimeException("heap is full");
}
heap[heapSize] = value;
// value heapSize
heapInsert(heap, heapSize++);
}
public int pop() {
int ans = heap[0];
swap(heap, 0, --heapSize);
heapify(heap, 0, heapSize);
return ans;
}
private void heapInsert(int[] arr, int index) {
while (arr[index] > arr[(index - 1) / 2]) {
swap(arr, index, (index - 1) / 2);
index = (index - 1) / 2;
}
}
private void heapify(int[] arr, int index, int heapSize) {
int left = index * 2 + 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, largest, index);
index = largest;
left = index * 2 + 1;
}
}
private void swap(int[] arr, int i, int j) {
int tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
}
public static class RightMaxHeap {
private int[] arr;
private final int limit;
private int size;
public RightMaxHeap(int limit) {
arr = new int[limit];
this.limit = limit;
size = 0;
}
public boolean isEmpty() {
return size == 0;
}
public boolean isFull() {
return size == limit;
}
public void push(int value) {
if (size == limit) {
throw new RuntimeException("heap is full");
}
arr[size++] = value;
}
public int pop() {
int maxIndex = 0;
for (int i = 1; i < size; i++) {
if (arr[i] > arr[maxIndex]) {
maxIndex = i;
}
}
int ans = arr[maxIndex];
arr[maxIndex] = arr[--size];
return ans;
}
}
public static void main(String[] args) {
// 小根堆
PriorityQueue<Integer> heap = new PriorityQueue<>((o1, o2) -> o2 - o1);
heap.add(5);
heap.add(5);
heap.add(5);
heap.add(3);
// 5 , 3
System.out.println(heap.peek());
heap.add(7);
heap.add(0);
heap.add(7);
heap.add(0);
heap.add(7);
heap.add(0);
System.out.println(heap.peek());
while (!heap.isEmpty()) {
System.out.println(heap.poll());
}
int value = 1000;
int limit = 100;
int testTimes = 1000000;
for (int i = 0; i < testTimes; i++) {
int curLimit = (int) (Math.random() * limit) + 1;
MyMaxHeap my = new MyMaxHeap(curLimit);
RightMaxHeap test = new RightMaxHeap(curLimit);
int curOpTimes = (int) (Math.random() * limit);
for (int j = 0; j < curOpTimes; j++) {
if (my.isEmpty() != test.isEmpty()) {
System.out.println("Oops!");
}
if (my.isFull() != test.isFull()) {
System.out.println("Oops!");
}
if (my.isEmpty()) {
int curValue = (int) (Math.random() * value);
my.push(curValue);
test.push(curValue);
} else if (my.isFull()) {
if (my.pop() != test.pop()) {
System.out.println("Oops!");
}
} else {
if (Math.random() < 0.5) {
int curValue = (int) (Math.random() * value);
my.push(curValue);
test.push(curValue);
} else {
if (my.pop() != test.pop()) {
System.out.println("Oops!");
}
}
}
}
}
System.out.println("finish!");
}
}
......@@ -8,7 +8,7 @@ import java.util.PriorityQueue;
// b. 从下到上的方法,时间复杂度为O(N)
// 2. 把堆的最大值和堆末尾的值交换, 然后减少堆的大小之后,再去调整堆, 一直周而复始,时间复杂度为O(N*logN) 【扩两倍估算复杂度法】
// 3. 把堆的大小减小成0之后,排序完成
public class Code_0075_HeapSort {// 堆排序额外空间复杂度O(1)
public class Code_HeapSort {// 堆排序额外空间复杂度O(1)
public static void heapSort(int[] arr) {
if (arr == null || arr.length < 2) {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册