java資料結構基礎-利用Heap(堆)實現PriorityQueue(優先佇列)
首先做一個優先佇列的介面:
import java.util.List;
public interface PriorityQueue {
void add(Object o);
void addAll(List elements);
Object remove();
boolean isEmpty();
int size();
}
接下來,用java寫一個heap結構,實現priority queue介面:
heap是一種二叉樹,所遵守的唯一規律為:所有的子節點都要大於(小於)父節點。
增加一個節點,直接加在最後,然後用upheap排序
刪除一個節點,則把要刪除的節點與跟節點交換,然後刪除交換後的根節點(既最後一個點),然後用downheap重新排序
heap的add方法很簡單,關鍵是addall,根據是空heap或非空,,應有不同的演算法以保證效率,空heap用bottom-up排序應該是最快的,至於非空的heap,則比較有挑戰性,以下是我自己寫的一段程式,僅供參考:
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Arrays;
public class Heap implements PriorityQueue {
protected Comparator comparator;
final static int ROOT_INDEX = 0;
final static int PRE_ROOT_INDEX = ROOT_INDEX - 1;
List heap;
public Heap() {
heap = new ArrayList();
}
public Heap(Comparator c) {
heap = new ArrayList();
comparator = c;
}
/* (non-Javadoc)
* @see PriorityQueue#add(java.lang.Object)
*/
public void add(Object o) {
heap.add(o);
int index = heap.size() - 1;
while (index > ROOT_INDEX) {
index = stepUpHeap(index);
}
}
/**
* Enforce ordering for heap element and its parent.
* Indices start from ROOT_INDEX (inclusive).
* @param index valid non-root heap position
* @return index of parent in heap, if swap occurs, otherwise ROOT_INDEX
*/
protected int stepUpHeap(int index) {
int parentIndex = parent(index);
Object element = heap.get(index);
Object parent = heap.get(parentIndex);
if (compare(parent, element) > 0) { // heap is out of order here
heap.set(parentIndex, element);
heap.set(index, parent);
return parentIndex; // jump to parent of index
} else // heap is OK
return ROOT_INDEX; // so jump to root
}
/**
* Compare elements using comparator if it exists.
* Otherwise assume elements are Comparable
* @param element
* @param other
* @return result of comparing element with other
*/
protected int compare(Object element, Object other) {
if (comparator == null) {
Comparable e = (Comparable) element;
Comparable o = (Comparable) other;
return e.compareTo(o);
} else
return comparator.compare(element, other);
}
/**
* Index of parent in heap.
* @param index to find parent of
* @return index of parent
*/
protected int parent(int index) {
return (index - PRE_ROOT_INDEX) / 2 + PRE_ROOT_INDEX;
}
public String toString() {
return heap.toString();
}
/* (non-Javadoc)
* @see PriorityQueue#isEmpty()
*/
public boolean isEmpty() {
return heap.isEmpty();
}
/* (non-Javadoc)
* @see PriorityQueue#size()
*/
public int size() {
return heap.size();
}
/* (non-Javadoc)
* @see PriorityQueue#remove()
*/
public Object remove() throws RuntimeException{
if (isEmpty())
throw new RuntimeException();
int index = heap.size() - 1;
Object least;
if(index==0){
least = heap.get(index);
heap.remove(index);
}
else{
Object element = heap.get(index);
least = heap.get(ROOT_INDEX);
heap.set(ROOT_INDEX, element);
heap.set(index, least);
heap.remove(index);
stepDownHeap(ROOT_INDEX);
}
return least;
}
/* (non-Javadoc)
* @see PriorityQueue#addAll(java.util.List)
*/
public void addAll(List elements) {
int numbers = elements.size();
for(int i=0;i
int n=1,rows=0;
for(rows=0;n<= heap.size();rows++){
n = n*2;
}
for(int i=rows-1;i>=1;i--){
for(int j=(int)(Math.pow(2,i-1)-1);j<=(int)(Math.pow(2,i)-2);j++){
stepDownHeap(j);
}
}
}
public static void sort(Comparable[] data) {
Heap cpr = new Heap();
List middle = Arrays.asList(data);
cpr.addAll(middle);
for(int i=data.length-1;i>=0;i--)
data[i] = (Comparable)(cpr.remove());
}
public static void sort(Object[] data, Comparator c) {
Heap cpr = new Heap(c);
List middle = Arrays.asList(data);
cpr.addAll(middle);
for(int i=data.length-1;i>=0;i--)
data[i] = cpr.remove();
}
public void stepDownHeap(int index){
int p = index;
int c = 2*p + 1;
Object temp = heap.get(p);
while(c
if(compare(temp,heap.get(c))<=0)
break;
else {
heap.set(p,heap.get(c));
p = c;
c = 2*p + 1;
}
}
heap.set(p,temp);
}
}
最後是一段測試程式:
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Random;
public class PQTest {
///////////////////////////////////////////////////////
//
// static declarations
//
///////////////////////////////////////////////////////
public static void main(String[] args) {
PQTest test = new PQTest();
test.constructor();
test.add();
test.remove();
test.addAll();
test.sort();
}
static int nextIndex;
final static long SEED = 88888L;
final static Random random = new Random(SEED);
static Integer[] arrayData; // backing store for data
static List data;
static void makeData(int n) {
random.setSeed(SEED);
arrayData = new Integer[n];
for (int i = 0; i < n; ++i) {
arrayData[i] = (new Integer(i));
}
data = Arrays.asList(arrayData);
Collections.shuffle(data, random);
}
static void testAssert(boolean b, String s) {
if (!b) throw new RuntimeException(s);
}
static Comparator comparableComparator() {
return new Comparator() {
public int compare(Object x, Object y) {
return ((Comparable) x).compareTo(y);
}
};
}
static Comparator reverseComparator(Comparator c) {
return new ReverseComparator(c);
}
static class ReverseComparator implements Comparator {
Comparator c;
ReverseComparator(Comparator c) {
this.c = c;
}
public int compare(Object x, Object y) {
return - c.compare(x,y);
}
}
static CountComparator countComparator(Comparator c) {
return new CountComparator(c);
}
static class CountComparator implements Comparator {
Comparator c;
CountComparator(Comparator c) {
this.c = c;
}
int count = 0;
public int getCount() {
return count;
}
public void clearCount() {
count = 0;
}
public int compare(Object x, Object y) {
++count;
return c.compare(x,y);
}
}
///////////////////////////////////////////////////////
//
// instance specific declarations
//
///////////////////////////////////////////////////////
// instance variable
PriorityQueue pq; // priority queue to be tested
Comparator c;
// instance methods for testing priority queue operation
void constructor() {
System.out.println("new Heap()");
pq = new Heap();
checkPQ(true, 0);
System.out.println();
}
void add() {
makeData(16);
for (int i = 0; i < 16; ++i) {
Object o = data.get(i);
System.out.println("add(" + o + ") ...");
pq.add(o);
checkPQ(false, i+1);
}
System.out.println();
}
void remove() {
for (int i = pq.size(); i > 0; --i) {
checkPQ(false, i);
System.out.print("remove() = ");
Object o = pq.remove();
System.out.println(o);
}
checkPQ(true, 0);
System.out.println();
}
void addAll() {
c = countComparator(comparableComparator());
pq = new Heap(c);
makeData(99);
addN(0,16);
addN(16,16);
addN(16,17);
addN(17,19);
addN(19,27);
addN(27,43);
addN(43,48);
addN(48,99);
System.out.println();
}
void addN(int from, int to) {
int size = pq.size();
List dataN = data.subList(from,to);
int n = to - from;
System.out.println("addAll(" + dataN + ") ... " + n + " items ...");
pq.addAll(dataN);
checkPQ(false, size+n);
System.out.println("Comparison count = " + ((CountComparator) c).getCount());
((CountComparator) c).clearCount();
}
void sort() {
Comparator c = null;
System.out.println("Testing sort() with natural ordering");
sortWithComparator(c);
System.out.println();
System.out.println("Testing sort() with reverse natural ordering");
c = reverseComparator(comparableComparator());
sortWithComparator(c);
System.out.println();
System.out.println("Testing sort() with natural ordering and comparison count");
c = countComparator(comparableComparator());
sortWithComparator(c);
System.out.println("Comparison count = " + ((CountComparator) c).getCount());
System.out.println();
System.out.println("Testing sort() with reverse natural ordering and comparison count");
c = countComparator(reverseComparator(comparableComparator()));
sortWithComparator(c);
System.out.println("Comparison count = " + ((CountComparator) c).getCount());
System.out.println();
}
void sortWithComparator(Comparator c) {
makeData(64);
System.out.println("Unsorted: " + data);
Heap.sort(arrayData, c);
System.out.println("Sorted: " + data);
System.out.println();
}
// helper methods
void checkPQ(boolean isEmpty, int size) {
System.out.println("PriorityQueue: " + pq);
testAssert(pq.isEmpty() == isEmpty, "isEmpty()");
testAssert(pq.size() == size, "size()");
}
}
對於非空的heap,應該有更快的演算法(但是效率都是o(nlogn)),只是結果可能會有所不同,但是仍然是按照heap的排序規則排列。
[@more@]來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/208722/viewspace-788541/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- java使用PriorityQueue即優先佇列實現大根堆和小根堆Java佇列
- .NET 6 優先佇列 PriorityQueue 實現分析佇列
- 資料結構之PHP(最大堆)實現優先佇列資料結構PHP佇列
- 二叉堆實現優先佇列佇列
- MaxHeap 最大堆 MinHeap 最小堆 PriorityQueue 優先佇列實現佇列
- 『演算法與資料結構』優先佇列 二叉堆演算法資料結構佇列
- 資料結構&堆&heap&priority_queue&實現資料結構
- 資料結構 - 堆(Heap)資料結構
- 堆與優先佇列佇列
- 資料結構之堆(Heap)資料結構
- 實戰PHP資料結構基礎之佇列PHP資料結構佇列
- 三、資料結構演算法-棧、佇列、優先佇列、雙端佇列資料結構演算法佇列
- 原始碼解析C#中PriorityQueue(優先順序佇列)的實現原始碼C#佇列
- 【資料結構】佇列(順序佇列、鏈佇列)的JAVA程式碼實現資料結構佇列Java
- 關於樹的資料結構(二分搜尋樹,堆和優先佇列)資料結構佇列
- 資料結構-詳解優先佇列的二叉堆(最大堆)原理、實現和應用-C和Python資料結構佇列Python
- js實現資料結構--佇列JS資料結構佇列
- Java版-資料結構-佇列(陣列佇列)Java資料結構佇列陣列
- 資料結構之php實現佇列資料結構PHP佇列
- Java版-資料結構-佇列(迴圈佇列)Java資料結構佇列
- 演算法與資料結構番外(1):優先佇列演算法資料結構佇列
- java實現單連結串列、棧、佇列三種資料結構Java佇列資料結構
- 手擼優先佇列——二叉堆佇列
- 資料結構-js實現棧和佇列資料結構JS佇列
- 資料結構-迴圈佇列(Python實現)資料結構佇列Python
- 【php實現資料結構】鏈式佇列PHP資料結構佇列
- 資料結構基礎學習之(棧和佇列)資料結構佇列
- 佇列 優先順序佇列 python 程式碼實現佇列Python
- php實現基本資料結構之棧、佇列PHP資料結構佇列
- 【堆】【優先佇列】[NOIP2004]合併果子佇列
- 最詳細版圖解優先佇列(堆)圖解佇列
- 堆、堆排序和優先佇列的那些事排序佇列
- 【資料結構基礎】佇列簡介(使用ES6)資料結構佇列
- 【資料結構】佇列的基礎知識(無程式碼)資料結構佇列
- [Java基礎]PriorityQueueJava
- 資料結構 - 佇列資料結構佇列
- 資料結構-佇列資料結構佇列
- 【資料結構-----佇列】資料結構佇列
- 【資料結構】迴圈佇列 C語言實現資料結構佇列C語言