java二叉堆_为什么二叉堆利用数组存储?
堆
邏輯結構最大的優勢就在于,通過數組,目標index 能推算出 父子指針的定位。
所以在上下heaptify的時候可以直接找到對應位置進行交換等操作。
現有語言里比如Java,C,C+;以java為例:
系統層面API:PriorityQueue ”優先隊列“,底層實現就是堆結構。其實就是堆實現。
但是大部分堆API都沒有提供動態修改已排序對象內部值的方法 Resign();
#舉例 已排序堆數組arr[];其中元素為Object O, 并且O包含N個屬性,比如以age屬性為例
arr[O1,O2,O3...] 這里裝著一堆object同學對象,現在以同學對象的age屬性,給arr排序
/*** 需求是,我給O3的age調整,比如改成20歲,對象要變更內部值。* 要求O3調整完畢后,提供一個方法,保證arr[]依然是排序后的堆結構。* ###動態修改,動態增刪,這種其實現實中很常見的需求。* 關鍵還在于,我們需要時間復雜度。* O(logN) 復雜度*/
- 邏輯過程簡單想一下就知道 插入一個值,然后每次O對象都要從下往上/從上往下進行heaptify這個操作,而且要進行N次
所以大部分都覺得動態修改這個代價太大。
回到正題,如果想實現O(logN)時間復雜度的堆,就需要有一個IndexMap:目的每次記錄修改前的值在堆內的哪個 ”位置“ 。
我個人認為正是由于數組的下標,標記了父子對應關系的可預見性數學方程關系:
[0,1,2,3,4,5]前提以0位置開始
1. left = 2*i + 1;
2. right = 2*i + 2;
3. root = (i - 1)/2;
才方便找到。
鏈表實現對應關系,可能會使用更多數據結構占用。
附帶數組Heap Resign();
package class04;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.PriorityQueue;
public class Heap {
// 堆
public static class MyHeap {
private ArrayList heap;
private HashMap indexMap;
private int heapSize;
private Comparator super T> comparator;
public MyHeap(Comparator super T> com) {
heap = new ArrayList<>();
indexMap = new HashMap<>();
heapSize = 0;
comparator = com;
}
public boolean isEmpty() {
return heapSize == 0;
}
public int size() {
return heapSize;
}
public boolean contains(T key) {
return indexMap.containsKey(key);
}
public void push(T value) {
heap.add(value);
indexMap.put(value, heapSize);
heapInsert(heapSize++);
}
public T pop() {
T ans = heap.get(0);
int end = heapSize - 1;
swap(0, end);
heap.remove(end);
indexMap.remove(ans);
heapify(0, --heapSize);
return ans;
}
public void resign(T value) {
int valueIndex = indexMap.get(value);
heapInsert(valueIndex);
heapify(valueIndex, heapSize);
}
private void heapInsert(int index) {
while (comparator.compare(heap.get(index), heap.get((index - 1) / 2)) < 0) {
swap(index, (index - 1) / 2);
index = (index - 1) / 2;
}
}
private void heapify(int index, int heapSize) {
int left = index * 2 + 1;
while (left < heapSize) {
int largest = left + 1 < heapSize && (comparator.compare(heap.get(left + 1), heap.get(left)) < 0)
? left + 1
: left;
largest = comparator.compare(heap.get(largest), heap.get(index)) < 0 ? largest : index;
if (largest == index) {
break;
}
swap(largest, index);
index = largest;
left = index * 2 + 1;
}
}
private void swap(int i, int j) {
T o1 = heap.get(i);
T o2 = heap.get(j);
heap.set(i, o2);
heap.set(j, o1);
indexMap.put(o1, j);
indexMap.put(o2, i);
}
}
public static class Student {
public int classNo;
public int age;
public int id;
public Student(int c, int a, int i) {
classNo = c;
age = a;
id = i;
}
}
public static class StudentComparator implements Comparator {
@Override
public int compare(Student o1, Student o2) {
return o1.age - o2.age;
}
}
public static void main(String[] args) {
Student s1 = null;
Student s2 = null;
Student s3 = null;
Student s4 = null;
Student s5 = null;
Student s6 = null;
s1 = new Student(2, 50, 11111);
s2 = new Student(1, 60, 22222);
s3 = new Student(6, 10, 33333);
s4 = new Student(3, 20, 44444);
s5 = new Student(7, 72, 55555);
s6 = new Student(1, 14, 66666);
PriorityQueue heap = new PriorityQueue<>(new StudentComparator());
heap.add(s1);
heap.add(s2);
heap.add(s3);
heap.add(s4);
heap.add(s5);
heap.add(s6);
while (!heap.isEmpty()) {
Student cur = heap.poll();
System.out.println(cur.classNo + "," + cur.age + "," + cur.id);
}
System.out.println("===============");
MyHeap myHeap = new MyHeap<>(new StudentComparator());
myHeap.push(s1);
myHeap.push(s2);
myHeap.push(s3);
myHeap.push(s4);
myHeap.push(s5);
myHeap.push(s6);
while (!myHeap.isEmpty()) {
Student cur = myHeap.pop();
System.out.println(cur.classNo + "," + cur.age + "," + cur.id);
}
System.out.println("===============");
s1 = new Student(2, 50, 11111);
s2 = new Student(1, 60, 22222);
s3 = new Student(6, 10, 33333);
s4 = new Student(3, 20, 44444);
s5 = new Student(7, 72, 55555);
s6 = new Student(1, 14, 66666);
heap = new PriorityQueue<>(new StudentComparator());
heap.add(s1);
heap.add(s2);
heap.add(s3);
heap.add(s4);
heap.add(s5);
heap.add(s6);
s2.age = 6;
s4.age = 12;
s5.age = 10;
s6.age = 84;
while (!heap.isEmpty()) {
Student cur = heap.poll();
System.out.println(cur.classNo + "," + cur.age + "," + cur.id);
}
System.out.println("===============");
s1 = new Student(2, 50, 11111);
s2 = new Student(1, 60, 22222);
s3 = new Student(6, 10, 33333);
s4 = new Student(3, 20, 44444);
s5 = new Student(7, 72, 55555);
s6 = new Student(1, 14, 66666);
myHeap = new MyHeap<>(new StudentComparator());
myHeap.push(s1);
myHeap.push(s2);
myHeap.push(s3);
myHeap.push(s4);
myHeap.push(s5);
myHeap.push(s6);
s2.age = 6;
myHeap.resign(s2);
s4.age = 12;
myHeap.resign(s4);
s5.age = 10;
myHeap.resign(s5);
s6.age = 84;
myHeap.resign(s6);
while (!myHeap.isEmpty()) {
Student cur = myHeap.pop();
System.out.println(cur.classNo + "," + cur.age + "," + cur.id);
}
// 對數器
System.out.println("test begin");
int maxValue = 100000;
int pushTime = 1000000;
int resignTime = 100;
MyHeap test = new MyHeap<>(new StudentComparator());
ArrayList list = new ArrayList<>();
for(int i = 0 ; i < pushTime; i++) {
Student cur = new Student(1,(int) (Math.random() * maxValue), 1000);
list.add(cur);
test.push(cur);
}
for(int i = 0 ; i < resignTime; i++) {
int index = (int)(Math.random() * pushTime);
list.get(index).age = (int) (Math.random() * maxValue);
test.resign(list.get(index));
}
int preAge = Integer.MIN_VALUE;
while(test.isEmpty()) {
Student cur = test.pop();
if(cur.age < preAge) {
System.out.println("Oops!");
}
preAge = cur.age;
}
System.out.println("test finish");
}
}
總結
以上是生活随笔為你收集整理的java二叉堆_为什么二叉堆利用数组存储?的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java jdk安装失败 mac_Mac
- 下一篇: 枚举与常量 java_java – 为什