优先队列(堆)
来源:互联网 发布:独立域名 编辑:程序博客网 时间:2024/05/21 16:32
优先队列(priority model)模型
insert:等价enqueue(入队)操作
deleteMin:它的工作是找出、返回并删除优先队列中最小的元素,等价dequeue(出队)操作
优先队列基本模型:
优先队列可以用外部排序。在贪婪算法(greedy algorithm)的实现方面优先队列也是很重要的,该算法通过反复求出最小元来进行操作。
一些简单的实现
1)使用一个简单链表在表头以O(1)执行插入操作,并变量该链表以删除最小元,这需要O(N)时间。
2)始终让链表保持排序状态,这使得插入代价高昂(O(N))而deleteMin花费低廉(O(1))。方法1比方法2好。
3)使用二叉查找树,它对这两种操作(插入、删除)的平均运行时间都是O(logN)。尽管插入是随机的,而删除则不是,但这个结论还是成立的。
二叉堆(binary heap)
就是平时所说的堆(heap)。性质:结构性和堆序性。堆的操作必须到堆的所有性质都被满足时才能终止。
结构性质
堆是一颗被完全填满的二叉树,有可能的例外是在底层,底层上的元素从左到右填入。这样的树称为完全二叉树(complete binary tree)。
一颗高为h的完全二叉树有2h到2h+1-1个节点。这意味着完全二叉树的高是小于等于logN的整数值,显然它是O(logN)。
完全二叉树的数组实现:
一个堆结构将由一个(Comparable对象的)数组和一个代表当前堆大小的整数组成。类架构如下:
public class BinaryHeap<AnyType extends Comparable<? super AnyType>> {public BinaryHeap(){}public BinaryHeap(int capacity){}public BinaryHeap(AnyType[] items){}public BinaryHeap(AnyType x){}public AnyType findmin(){}public AnyType deleteMin(){}public boolean isEmpty(){}public void makeEmpty(){}private static final int DEFAULT_CAPACITY = 10;private int currentSize; //堆中元素数量private AnyType[] array; //堆数组private void percolateDown(int hole){}private void buildHeap(){}private void enlargeArray(int newSize){}}
堆序性质(heap-order property)
让操作快速执行的性质是堆序性质。在一个堆中,对于每一个节点X,X的父亲中的关键字小于(或等于)X中的关键字,根节点除外(它没有父亲)。
基本的堆操作
insert(插入)
为将一个元素X插入到堆中,我们在下一个可用位置创建一个空穴,否则该堆将不是完全树。如果X可以放在该空穴中而并不破坏堆的序,那么插入完成。否则,我们把空穴的父节点上的元素移入该空穴中,这样,空穴就朝着根的方向上冒一步。继续该过程直到X能被放入空穴中为止。这种策略叫做上滤(precolate up)。
插入到一个二叉堆的过程:
/** * Insert into the priority queue,maintaining heap order. * Duplicates are allowed * @param x the item to insert */ public void insert(AnyType x){ if(currentSize==array.length-1){ enlargeArray(array.length*2+1); } //Percolate up int hole = ++currentSize; for(;hole>1 && x.compareTo(array[hole/2])<0;hole/=2){ array[hole] = array[hole/2]; } array[hole] = x; }
deleteMin(删除最小元)
当删除一个最小元时,要在根节点建立一个空穴。由于现在堆少了一个元素,因此堆中最后一个元素X必须移动到该堆的某个地方。如果X可以被放到空穴中,那么deleteMin完成。不过这一般不太可能,因此我们将空穴的两个儿子中较小者移入空穴,这样就把空穴向下推了一层。重复该步骤直到X可以被放入空穴中。因此,我们的做法是将X置入沿着从根开始包含最小儿子的一条路径上一个正确的位置。这种策略叫做下滤(percolate down)。
在二叉堆中执行deleteMin的方法:
/** * Remove the smallest item from the priority queue * @return the smallest item,or throw UnderflowException,if empty */ public AnyType deleteMin(){ if(isEmpty()){ throw new UnderflowException(); } AnyType minItem = findMin(); array[1] = array[currentSize--]; percolateDown(1); return minItem; } /** * Internal method to percolate down in the heap * @param hole the index at which the perolate begins */ private void percolateDown(itn hole){ int child; AnyType tmp = array[hole]; for(;hole*2<=currentSize;hole=child){ child = hole*2; if(child!=currentSize&&array[child+1].compareTo(array[child])<0){ child++; } if(array[child].compareTo(tmp)<0){ array[hole] = array[child]; }else{ break; } } array[hole] =tmp; }
decreaseKey(降低关键字的值)
decreaseKey(p,)操作降低在位置p处的项的值,降值的幅度为正的量。由于这可能破坏堆序性质,因此必须通过上滤对堆进行调整。
increaseKey(增加关键字的值)
increateKey(p,)操作增加在位置p处的项的值,增值的幅度为正的量。这可以用下滤来完成。
delete(删除)
delete(p)操作删除堆中位置p上的节点。该操作通过首先执行decreaseKey(p,无穷)然后再执行deleteMin()来完成。当一个进程被用户中止(而不是正常终止)时,它必须从优先队列中除去。
buildHeap(构建堆)
/** * Construct the binary heap given an array of items */ public BinaryHeap(AnyType[] items){ currentSize = items.length; array = (AnyType[])new Comparable[(currentSize+2)*11/10]; int i = 1; for(AnyType item:items){ array[i++] = item; } buildHeap(); } /** * Establish heap order property from an arbitrary * arrangment of items. Runs in linear time */ private void buildHeap(){ for(int i=currentSize/2;i>0;i--){ percolateDown(i); } }
包含2h+1 - 1 个节点,高为h的理想二叉树(perfect binary tree)的节点的高度的和为2h+1 - 1 - (h+1)。
- 优先队列(堆)
- 优先队列(堆)
- 优先队列(堆)
- 优先队列(堆)
- 优先队列(堆)
- 优先队列(堆)
- 优先队列(堆)
- 优先队列(堆)
- 优先队列(堆)
- 二叉堆(优先队列)
- 二叉堆(优先队列)
- 数据结构---->优先队列(堆)
- 优先队列(堆)目录
- 优先队列(堆)浅谈
- 优先队列(最小堆)
- 二叉堆(优先队列)
- [数据结构].堆(优先队列)
- 堆排序(优先队列)
- 门描述符
- android-topeka学习笔记(一)-----一些不知道的属性
- ios弹出框
- 差分约束系统
- 初步封装OkHttp
- 优先队列(堆)
- BroadcastReceiver 广播接收者
- OpenGl红皮书第六版阅读笔记p107页实例
- 数的计数
- C语言学习-指针(仅如初见)
- 5. Longest Palindromic Substring
- web访问基础
- Python基础--运算符
- 笔记本电脑配置要什么样的才算好