赞
踩
二叉堆(满足一些特殊性质的二叉树)
18
/ \
15 30
/ \ / \
40 50 100 40
18
/ \
15 30
/ \ / \
40 50 100 40
/ \ /
8 7 9
62
/ \
41 30
/ \ / \
28 16 22 13
/ \ /
19 17 15
按照二叉树的 结构存储数组 插入新数组的时候只要计算 他的父节点
(父节点计算公式为 i/2 i为当前数组索引 ) 如果插入元素比父节点小 则 成功 如果父节点 较小 则互相调换值 然后 在判断 当前位置的父节点 是否 比新插入的元素小 如果小交换 反复重复这个过程直到 插入元素 比 父节点小
如果从堆中 取出最大值 62 后需要把堆中最后一个元素取出 替代 取出的位置 然后为了满足 二叉堆的性质 需要从子节点中选择最大的节点 替换直到满足 父节点小于子节点的性质。
将任意数组整理成堆的形状
从最后一个 节点计算 找到父亲节点(n-1/2) 如果父节点小于子节点 执行交换 重复这个操作直到父节点大于子节点。
Array.java
public class Array<E> { private E[] data; private int size; /** * * @param capacity 构造函数,传入数组的容量capacity 构造Array */ public Array(int capacity){ data =(E[])new Object[capacity]; size = 0; } public int getSize(){ return size; } public int getCapacity(){ return data.length; } //无参数构造函数,默认数组的容量 capacity =10 public void addLast(E e){ add(size,e); } public void addFirst(E e){ add(0,e); } public Array(){ this(10); } public void add(int index,E e){ if(size > (int)(data.length) * 2/3) //System.out.println(2 * data.length); resize((int)(data.length) * 4/3); if(index < 0 || index>size) throw new IllegalArgumentException("Addlast failed.index must over zero and index must small than size"); for (int i = size;i >= index;i--) data[i + 1]= data[i]; data[index] = e; size ++; } /** * * @param index 要删除的索引 * @return 返回删除的值 */ public E remove(int index){ if(index >size || index<0 ) throw new IllegalArgumentException("Delval failed.index must big than zeor and index not over than size"); E ret =data[index]; for(int i=index ;i<size;i++){ data[i] =data[i+1]; } data[size] = null; //loitering objects != memory leak size--; if(size <= (int)data.length/3 && data.length/3 != 0) resize((int)data.length * 2/3); return ret; } /** * * @return 删除以一个值返回删除的元素 */ public E removeFirst(){ E ret ; ret = this.remove(0); return ret; } /** * * @return 删除最后一个值返回删除的元素 */ public E removeLast(){ E ret ; ret = this.remove(size); return ret; } /** * * @return 删除元素 */ public void removeElement(E e){ int find =find(e); if(find != -1){ remove(find); } } public boolean isEmpty(){ if(data.length == 0) return true; else return false; } public E getFirst(){ return get(0); } public E getLast(){ return get(size - 1); } /** * * @param index 传入一个不超过当前数组size的索引 * @return 返回索引相对应的值 */ E get(int index){ if(index < 0 || index >= size) throw new IllegalArgumentException("Get failed ,index is Illegal"); return data[index] ; } /** * * @param index 传入一个不超过数组size的索引 * @param e 传入值 */ void set(int index,E e){ if(index >size || index < 0) throw new IllegalArgumentException("Set failed ,index is overflow"); data[index] =e; } /** * * @param e 传入元素的值查找 * @return 找到返回真 */ public boolean contains(E e){ for(int i = 0 ;i<size;i++){ if(data[i] == e){ return true; } } return false; } /** * * @param e 要查找的参数 * @return 查找参数找到返回1 没找到返回-1 */ public int find(E e){ for (int i =0 ;i<size;i++){ if(data[i] .equals(e)) return i; } return -1; } @Override public String toString() { StringBuilder res = new StringBuilder(); res.append(String.format("Array :size= %d ,capacity =%d\n ", size, data.length )); res.append('['); for (int i = 0; i < size; i++) { res.append(data[i]); if (i != size - 1) { res.append(","); }else { res.append(']'); } } return res.toString(); } public void resize(int newCapacity){ E[] newE = (E[]) new Object[newCapacity]; for(int i =0;i<size;i++){ newE[i] =data[i]; } data =newE; } }
MaxHeap.java
public class MaxHeap<E extends Comparable<E>> { private Array<E> data; public MaxHeap(int capacity){ data = new Array<>(capacity); } public MaxHeap(){ data = new Array<>(); } public MaxHeap(E[] arr){ data = new Array<>(arr); for(int i =parent(arr.length-1);i>=0;i--) siftDown(i); } //返回堆中的元素个数 public int size(){ return data.getSize(); } //返回一个布尔值,表示堆中是否为空 public boolean isEmpty(){ return data.isEmpty(); } //返回完全二叉树组中,一个缩影表示的元素的父节点的索引。 private int parent(int index){ if(index == 0) throw new IllegalArgumentException("index zero has no parent"); return(index -1)/2; } //返回完全二叉树的数组表示中,一个索引所表示的元素的有孩子节点的索引 private int rightChild(int index){ return index * 2 + 2; } private int leftChild(int index){ return index * 2 + 1; } //对堆中添加元素 public void add(E e){ data.addLast(e); siftUp(data.getSize() -1); } //交换最大值 private void siftUp(int i) { //和父节点比大小 如果父节点小就交换 while(i > 0 && data.get(parent(i)).compareTo(data.get(i))<0){ //交换父节点和子节点 data.swap(i,parent(i)); //重新获得交换后插入值的索引 i = parent(i); } } public E findMax(){ if(data.getSize() == 0) throw new IllegalArgumentException("cannot find Max When Heap is empty"); return data.get(0); } //取出堆中最大元素 public E extractMax(){ E ret =findMax(); data.swap(0,data.getSize() -1); data.removeLast(); siftDown(0); return ret; } private void siftDown(int i) { while (leftChild(i) <data.getSize()){ int j = leftChild(i); if(j+1 <data.getSize() && data.get(j+1).compareTo(data.get(j))>0) j ++ ; if(data.get(i).compareTo(data.get(j))>=0) break; data.swap(i,j); i=j; } } //替换节点 public E replace(E e){ E ret =findMax(); data.set(0,e); siftDown(0); return ret; } } Queue.java ```java public interface Queue<E> { int getSize(); boolean isEmpty(); void enqueue(E e); E dequeue(); E getFront(); }
优先队列
PriorityQueue.java
public class PriorityQueue <E extends Comparable<E>> implements Queue<E> { private MaxHeap<E> maxHeap; public PriorityQueue(){ maxHeap =new MaxHeap<>(); } @Override public int getSize() { return maxHeap.size(); } @Override public boolean isEmpty() { return maxHeap.isEmpty(); } @Override public void enqueue(E e) { maxHeap.add(e); } @Override public E dequeue() { return maxHeap.findMax(); } @Override public E getFront() { return maxHeap.extractMax(); } }
add | Heapify | |
---|---|---|
算法复杂度 | O(n) | On(logn) |
使用Heapify 将直接生成的数组 传入 算法复杂度为 On(logn)
使用add 一个个添加元素 算法复杂度为O(n)
import java.util.Random; public class Main { private static double testHeap(Integer[] testData, boolean isHeapify){ long startTime = System.nanoTime(); MaxHeap<Integer> maxHeap; if(isHeapify) maxHeap = new MaxHeap<>(testData); else{ maxHeap = new MaxHeap<>(); for(int num: testData) maxHeap.add(num); } int[] arr = new int[testData.length]; for(int i = 0 ; i < testData.length ; i ++) arr[i] = maxHeap.extractMax(); for(int i = 1 ; i < testData.length ; i ++) if(arr[i-1] < arr[i]) throw new IllegalArgumentException("Error"); System.out.println("Test MaxHeap completed."); long endTime = System.nanoTime(); return (endTime - startTime) / 1000000000.0; } public static void main(String[] args) { int n = 1000000; Random random = new Random(); Integer[] testData = new Integer[n]; for(int i = 0 ; i < n ; i ++) testData[i] = random.nextInt(Integer.MAX_VALUE); double time1 = testHeap(testData, false); System.out.println("Without heapify: " + time1 + " s"); double time2 = testHeap(testData, true); System.out.println("With heapify: " + time2 + " s"); } }
插入100万 随机数 性能 如上。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。