1.优先队列(堆):堆是一种完全二叉树(完全二叉树insert ,delete时候,这种数据结构能够直接进行自我的调整),二叉堆也叫完全二叉树,使用完全二叉树实现最方便的。
但是完全二叉树并不是堆,这种完全二叉树不得不满足有序性的原理,因此与AVL树一样,对堆(完全二叉树)操作必须让堆满足所有的性质为止 因此高度H的完全二叉树有 2^h个节点高度[logN],算法复杂度o(logN)
最小堆 性质:满足任意一个节点比其子孙后代小,不同于二叉查找树,不采用二叉查找树的特性在于,如果采用查找树删除最小元素,反复去除左子树节点,让右子树变的偏重
使用完全二叉树的结构最大特点 可以使用数组表示不需要使用链表的方式
更加注重的删除操作;堆两个特性及:结构性和有序性
log有序性:从根节点到任一节点的路径上结点保持明显的有序性。
如果采用数组实现的话:
堆性质中数组实现左儿子在2*i位置上 右儿子在2*i+1位置上
适用范围:海量数据中求最大的前N位数据,必须重新理解优先队列的删除元素和插入元素
2.性质: 采用完全二叉树实现,不需要进行比较,只需要保证 树的结构性和有序性不同平衡二叉树(需要对数据进行比较处理),这里保证根节点是最小元
插入过程(insert) 采用上滤的策略:插入新位置同其父结点进行比较 找到其堆中正确位置
删除过程():1.FindMin函数找到数组中最小值,删除只够
1 package Heap; 2 3 import org.omg.CORBA.portable.UnknownException; 4 5 public class BinaryHeap <AnyType extends Comparable <? super AnyType>> { 6 7 /*java 语言 编写最小堆得实现*/ 8 9 /*堆 私有性质:堆得容量 ,数组的类型AnyType代替*/ 10 private int currentSize; 11 private AnyType [] array; //the heap array 12 13 private static final int DEFAULT_CAPACITY=10; 14 public void makeEmpty() 15 { 16 currentSize=0; 17 for(int i=0;i<array.length;i++) 18 array[i]=null; 19 } 20 21 public boolean isEmpty() 22 { 23 if (currentSize>0) 24 return false; 25 else 26 return true; 27 28 } 29 /*构造函数初始化:1.默认10 2.根据输入量开辟数组 30 * 3 二叉堆是一些项的初始集合构造合成 因此对其进行调整让其符合堆得性质*/ 31 public BinaryHeap() 32 { 33 this(DEFAULT_CAPACITY); 34 } 35 36 @SuppressWarnings("unchecked") 37 public BinaryHeap(int capacity) 38 { 39 40 currentSize=0; 41 array=(AnyType[]) new Comparable[capacity+1]; 42 } 43 44 /*将无序的二叉树调整形成堆*/ 45 @SuppressWarnings("unchecked") 46 public BinaryHeap(AnyType [] item) 47 { 48 currentSize=item.length; 49 array=(AnyType []) new Comparable[((currentSize+2)*11/10)]; 50 array[0]=null; 51 52 for(int i=0 ;i<item.length;i++) 53 array[i+1]=item[i]; 54 55 56 buildheap();//采用下过滤将无序二叉树进行调整 57 58 } 59 60 public void buildheap() 61 { 62 for(int i=currentSize/2;i>0;i--) 63 precolateDown(i); 64 } 65 @SuppressWarnings("unchecked") 66 public void insert(AnyType x) 67 { 68 if(currentSize==array.length-1) 69 { 70 enlargeArray(array.length*2+1); 71 } 72 73 /*采用上滤策略进行插入,对于插入元素与其父结点比较,从底层到顶层 74 * array[0]位置存放当前插入元素,当做咲兵*/ 75 int hole=++currentSize; 76 77 for(array[0]=x; x.compareTo(array [hole/2])<0;hole/=2) 78 array[hole]=array[hole/2]; 79 80 array[hole]=x; 81 } 82 83 @SuppressWarnings("unchecked") 84 public void enlargeArray(int newSize) 85 { 86 AnyType []old=array; 87 88 array=(AnyType[]) new Comparable[newSize+1]; 89 90 for(int i=0;i<old.length;i++) 91 array[i]=old[i]; 92 93 } 94 95 public AnyType FindMin() 96 { 97 if(isEmpty()) 98 return null; 99 return array[1]; 100 } 101 102 public AnyType deletMin() 103 { 104 /*从堆中进行弹出,将最后一个元素提到最首位置上采用下过滤策略进行堆得调整 105 * 采用下过滤方法;相反从顶层向底层依次调整顺序*/ 106 if(isEmpty()) 107 throw new UnknownException(null); 108 AnyType minItem=FindMin(); 109 110 array[1]=array[currentSize--]; 111 precolateDown(1); 112 113 return minItem; 114 } 115 116 @SuppressWarnings({ "unchecked", "rawtypes" }) 117 public void precolateDown(int hole) 118 { 119 int child; 120 AnyType tmp=array[hole]; 121 122 for(;hole*2<=currentSize;hole=child) 123 { 124 child=hole*2; 125 /*前部分保证有左右两子节点 ;挑选出子节点最小元素*/ 126 if(child!=currentSize && array[child+1].compareTo(array[child]) <0) 127 child++;/*指向子节点中较小值*/ 128 if( array[child].compareTo(tmp)<0) 129 array[hole]=array[child]; 130 else 131 break; 132 133 } 134 array[hole]=tmp; 135 } 136 137 public void Println() 138 { 139 for (int i=0;i<array.length;i++) 140 System.out.println(i+1 + "位置上: " + array[i]); 141 } 142 public static void main( String [ ] args ) 143 { 144 int itemnum=15; 145 Integer [] item=new Integer [itemnum]; 146 147 item[0]=150;item[1]=80;item[2]=40;item[3]=30;item[4]=10;item[5]=70; 148 item[6]=110;item[7]=100;item[8]=20;item[9]=90;item[10]=60;item[11]=50; 149 item[12]=120;item[13]=140;item[14]=130; 150 151 for(int i=0;i<item.length;i++) 152 System.out.println(item[i]); 153 BinaryHeap <Integer> H =new BinaryHeap<Integer>(item); 154 H.Println(); 155 } 156 }
/*测试:原有的无序集合进行堆得建立,直接采用下过滤方式进行处理*/
150 80 40 30 10 70 110 100 20 90 60 50 120 140 130 1位置上: null 2位置上: 10 3位置上: 20 4位置上: 40 5位置上: 30 6位置上: 60 7位置上: 50 8位置上: 110 9位置上: 100 10位置上: 150 11位置上: 90 12位置上: 80 13位置上: 70 14位置上: 120 15位置上: 140 16位置上: 130 17位置上: null 18位置上: null
二.二叉堆的推广----d堆(所有节点有d个儿子,树变浅 但是insert算法变成 logd(N),删除时候找出d个儿子最小值) 4-堆比二叉堆运行速度更快
堆实现过程中:最明显缺点将两个堆合成(merge)成一个堆,堆得merge
1.左式堆:支持有效的合并使用链式数据结构,不同于二叉堆,趋向于非常不平衡。性质:左儿子零路径长>=右儿子零路径长,偏向向左增加深度,为了合并
零路径长:从X到不具有两个儿子节点的最短路径,npx(null)=-1,只有一个节点或者零个节点的npx=0;
堆左式堆合并过程理解:http://www.07net01.com/program/33962.html
合并过程中: 1.遵守最小堆原则,任意结点比子结点的值小
2. 原则:根值大的堆与根植小的堆右子堆进行合并 ,合并完成之后不符合左子堆条件必须要交互子树
3.H1只有一个节点 H1没有右子堆 H1有右子堆
4. 编程过程记录合并堆得零路径长
1 package Heap; 2 3 import java.util.LinkedList; 4 5 import org.omg.CORBA.portable.UnknownException; 6 7 public class LeftistHeap <AnyType extends Comparable <? super AnyType>>{ 8 /*运用链式数据结构,树结构不用数组存储数据*/ 9 10 private static class Node<AnyType> 11 { 12 AnyType element;/*the data in the node*/ 13 Node<AnyType> right;Node<AnyType> left; 14 int npl;/*null path length*/ 15 16 Node(AnyType theelement) 17 { 18 this(theelement,null,null); 19 } 20 21 Node(AnyType theelement,Node<AnyType> lt,Node<AnyType> rt) 22 { 23 element=theelement; 24 left=lt;right=rt;npl=0; 25 } 26 } 27 28 29 private Node<AnyType> root; 30 31 public LeftistHeap() 32 { 33 root=null; 34 } 35 36 public boolean isEmpty() 37 { 38 return root==null; 39 } 40 public void makeEmpty() 41 { 42 root=null; 43 } 44 45 public void insert( AnyType x) 46 { 47 /*将x与 新的链表结点合并在一起*/ 48 root=merge(new Node<> (x),root); 49 50 } 51 public void merge(LeftistHeap<AnyType> rhs) 52 { 53 /*将其他不同左式堆与现有左式堆进行合并*/ 54 if(this==rhs) 55 return ; 56 root=merge(root,rhs.root); 57 rhs.root=null; 58 } 59 60 private Node<AnyType> merge(Node<AnyType> h1,Node<AnyType> h2) 61 { 62 /*分为三种情况*/ 63 if(h1==null) 64 return h2; 65 if(h2==null) 66 return h1; 67 /*原则:根植大的堆与根植小的堆得右子堆进行合并*/ 68 if(h1.element.compareTo(h2.element)<0) 69 return meger1(h1,h2); 70 else 71 return meger1(h2,h1); 72 73 74 } 75 76 private Node<AnyType> meger1(Node<AnyType>h1,Node<AnyType>h2) 77 { 78 if(h1.left==null) 79 h1.left=h2; 80 else 81 { 82 h1.right=merge(h1.right,h2); 83 if(h1.left.npl < h1.right.npl) 84 swapChildren(h1); 85 86 h1.npl=h1.right.npl+1; 87 88 } 89 return h1; 90 } 91 92 private void swapChildren(Node<AnyType > t) 93 { 94 Node<AnyType> tmp=t.left; 95 t.left=t.right; 96 t.right=tmp; 97 98 } 99 public AnyType findMin() 100 { 101 if( isEmpty( ) ) 102 throw new UnknownException(null ); 103 return root.element; 104 } 105 public AnyType deletMin() 106 { 107 if( isEmpty( ) ) 108 throw new UnknownException(null ); 109 AnyType minItem=root.element; 110 111 root=merge(root.left,root.right); 112 113 return minItem; 114 } 115 116 117 public void levelOrder(Node<AnyType> P) 118 { 119 /*层次遍历过程要用队列*/ 120 LinkedList <Node<AnyType>> queue=new LinkedList<>(); 121 queue.add((Node<AnyType>) P); 122 123 while(P!=null &&(!queue.isEmpty())) 124 { 125 P=(Node<AnyType>) queue.element(); 126 System.out.println("["+P.element+"]"); 127 128 if(P.left!=null) queue.add((Node<AnyType>) P.left); 129 if(P.right!=null) queue.add((Node<AnyType>) P.right); 130 queue.remove(); 131 } 132 133 134 } 135 public static void main(String[] args) { 136 // TODO Auto-generated method stub 137 LeftistHeap <Integer > h=new LeftistHeap<>(); 138 LeftistHeap <Integer > H1=new LeftistHeap<>(); 139 140 Integer array []=new Integer[8]; 141 array[0]=3;array[1]=10;array[2]=8;array[3]=21;array[4]=14;array[5]=17;array[6]=23;array[7]=26; 142 143 for(int i=0;i<8;i++) 144 H1.insert(array[i]); 145 146 H1.levelOrder(H1.root); 147 //h.levelOrder(h.root); 148 149 } 150 151 }
结果显示:
[3] [8] [10] [21] [14] [17] [23] [26]
结构如下显示:符合左式堆条件:左子树零路径长大于等于右子树零路径长;