多向归并——索引优先序列
优先序列见:优先序列实现
/**
* 最大索引优先序列,为二叉堆实现的优先序列加上索引,其典型应用是在k个有序数组的多项归并中,维护
* 长度为k的优先序列,每个数组的编号为优先序列的索引,每次取掉的最小值的索引就将编号为该序列的
* 数组的下一位读入,依次进行。之所以使用索引优先序列,是因为没有索引就无法确定下一次读入哪个数组
* @author XY
*
*/
@SuppressWarnings("unchecked")
public class Indexpriority<Key extends Comparable<Key>> {
private final int len_default=10;
private int size;
private int len;
private Key[] key;//元素数组
private int[] pq;//索引数组,该数组存在的作用是根据元素所在位置知道其索引
private int[] qp;//索引的逆数组,保存索引的位置,用来根据索引查找该索引对应的数据位置
public Indexpriority(){
this.len=len_default+1;
this.size=0;
key=(Key[])new Comparable[len];
pq=new int[len];
qp=new int[len];//这里两个数组同样大小,但是这样会限制索引取值范围在0-len-1之间。
for (int i = 0; i < qp.length; i++) {
qp[i]=-1;//索引数组初始值为-1,意味着此索引值不存在
}
}
public Indexpriority(int l){
this.len=l+1;
this.size=0;
key=(Key[])new Comparable[len];
pq=new int[len];
qp=new int[len];
for (int i = 0; i < qp.length; i++) {
qp[i]=-1;
}
}
public void insert(int index,Key item){
if(qp[index]==-1){
key[++size]=item;//同时处理三个数组
pq[size]=index;
qp[index]=size;
swim(size);
}else set(index, item);
}
public void set(int index,Key item){
if(qp[index]==-1) {insert(index, item);}
else{
int temploca=qp[index];
pq[temploca]=index;
key[temploca]=item;
// if(temploca/2>=1 && less(temploca/2, temploca)) swim(temploca);
// else sink(temploca);
swim(temploca);//swim()和sink()中存在边界检查,所以此处不进行重复检查。
sink(temploca);
}
}
public boolean contains(int index){
return qp[index]!=-1;
}
public Key max(){
if(size<1) return null;
return key[1];
}
public int maxIndex(){
if(size<1) return -1;
return pq[1];
}
public int delMax(){
if(size<1) return -1;
exchange(1, size);
int tempindex=pq[size];
key[size]=null;
pq[size--]=-1;
qp[tempindex]=-1;//防止对象游离
sink(1);
return tempindex;
}
public void delete(int index){
int location=qp[index];
if(location==-1) return;
exchange(location, size--);
swim(location);
sink(location);
qp[index]=-1;
key[size+1]=null;
pq[size+1]=-1;
}
public int size(){
return size;
}
public boolean isEmpty(){
return size==0;
}
private void swim(int loca){
if(loca>size) return;
int k=loca;
while(k/2>=1 && less(k/2, k) ){
exchange(k, k/2);
k/=2;
}
}
private void sink(int loca){
if (loca<1) return;
int k=loca;
while(k*2 <=size){
int j=k*2;
if(j+1<=size && less(j, j+1)){j=j+1;}
if (less(k, j)) {exchange(k, j);k=j;}
else break;
}
}
private void exchange(int a,int b){//交换要同时处理三个数组
Key tempkey=key[a];
key[a]=key[b];
key[b]=tempkey;
int tempindex=pq[a];
pq[a]=pq[b];
qp[pq[a]]=a;
pq[b]=tempindex;
qp[pq[b]]=b;
}
private boolean less(int a,int b){
return key[a].compareTo(key[b])<0;
}
public static void main(String[] args) {
Indexpriority<Integer> indexpq=new Indexpriority<Integer>();
Integer[] v={1,2,3,5,9,4,10};
int[] index={2,3,1,7,4,6,5};
for (int i = 0; i < index.length; i++) {
indexpq.insert(index[i], v[i]);
}
System.out.println(indexpq.max());
System.out.println(indexpq.maxIndex());
// indexpq.set(2, 12);
// System.out.println(indexpq.max());
// System.out.println(indexpq.maxIndex());
indexpq.delMax();
System.out.println(indexpq.max());
System.out.println(indexpq.maxIndex());
indexpq.delMax();
System.out.println(indexpq.max());
System.out.println(indexpq.maxIndex());
indexpq.delete(2);
System.out.println(indexpq.max());
System.out.println(indexpq.maxIndex());
System.out.println(indexpq.contains(2));
}
}
最小索引优先序列仅仅是改变swim()和sink()的内容而已,具体实现如下:
public class Indexpriority<Key extends Comparable<Key>> {
private final int len_default=40;
private int size;
private int len;
private Key[] key;//元素数组
private int[] pq;//索引数组,该数组存在的作用是根据元素所在位置知道其索引
private int[] qp;//索引的逆数组,保存索引的位置,用来根据索引查找该索引对应的数据位置
public Indexpriority(){
this.len=len_default+1;
this.size=0;
key=(Key[])new Comparable[len];
pq=new int[len];
qp=new int[len];//这里两个数组同样大小,但是这样会限制索引取值范围在0-len-1之间。
for (int i = 0; i < qp.length; i++) {
qp[i]=-1;//索引数组初始值为-1,意味着此索引值不存在
}
}
public Indexpriority(int l){
this.len=l+1;
this.size=0;
key=(Key[])new Comparable[len];
pq=new int[len];
qp=new int[len];
for (int i = 0; i < qp.length; i++) {
qp[i]=-1;
}
}
public void insert(int index,Key item){
if(qp[index]==-1){
key[++size]=item;//同时处理三个数组
pq[size]=index;
qp[index]=size;
swim(size);
}else set(index, item);
}
public void set(int index,Key item){
if(qp[index]==-1) {insert(index, item);}
else{
int temploca=qp[index];
pq[temploca]=index;
key[temploca]=item;
// if(temploca/2>=1 && less(temploca/2, temploca)) swim(temploca);
// else sink(temploca);
swim(temploca);//swim()和sink()中存在边界检查,所以此处不进行重复检查。
sink(temploca);
}
}
public boolean contains(int index){
return qp[index]!=-1;
}
public Key min(){
if(size<1) return null;
return key[1];
}
public int minIndex(){
if(size<1) return -1;
return pq[1];
}
public int delMin(){//返回最小值
if(size<1) return -1;
exchange(1, size);
int tempindex=pq[size];
key[size]=null;
pq[size--]=-1;
qp[tempindex]=-1;//防止对象游离
sink(1);
return tempindex;
}
public void delete(int index){
int location=qp[index];
if(location==-1) return;
exchange(location, size--);
swim(location);
sink(location);
qp[index]=-1;
key[size+1]=null;
pq[size+1]=-1;
}
public Key get(int index){
int location=qp[index];
if(location==-1) return null;
return key[location];
}
public int size(){
return size;
}
public boolean isEmpty(){
return size==0;
}
private void swim(int loca){
if(loca>size) return;
int k=loca;
while(k/2>=1 && less(k, k/2) ){
exchange(k/2, k);
k/=2;
}
}
private void sink(int loca){
if (loca<1) return;
int k=loca;
while(k*2 <=size){
int j=k*2;
if(j+1<=size && less(j+1, j)){j=j+1;}
if (less(j, k)) {exchange(k, j);k=j;}
else break;
}
}
private void exchange(int a,int b){//交换要同时处理三个数组
Key tempkey=key[a];
key[a]=key[b];
key[b]=tempkey;
int tempindex=pq[a];
pq[a]=pq[b];
qp[pq[a]]=a;
pq[b]=tempindex;
qp[pq[b]]=b;
}
private boolean less(int a,int b){
return key[a].compareTo(key[b])<0;
}
public static void main(String[] args) {
Indexpriority<Integer> indexpq=new Indexpriority<Integer>();
Integer[] v={1,2,3,5,9,4,10};
int[] index={2,3,1,7,4,6,5};
for (int i = 0; i < index.length; i++) {
indexpq.insert(index[i], v[i]);
}
System.out.println(indexpq.min());
System.out.println(indexpq.minIndex());
System.out.println(indexpq.min());
System.out.println(indexpq.minIndex());
indexpq.delMin();
System.out.println(indexpq.min());
System.out.println(indexpq.minIndex());
}
}