java数据结构和算法(IndexMaxPQ2)

package cn.xyc.sort.maxPQ;

import java.util.Iterator;
import java.util.NoSuchElementException;

/**
 * 
 * 描述:索引优先队列
 * 
 * <pre>
 * HISTORY
 * ****************************************************************************
 *  ID   DATE             PERSON          REASON
 *  1    2016年10月10日           蒙奇·D·许                     Create
 * ****************************************************************************
 * </pre>
 * 
 * @author 蒙奇·D·许
 * @since 1.0
 */
public class IndexMaxPQ2<Key extends Comparable<Key>> {
	/** 优先队列中索引的位置:queue_index ;queue代表队列中的下标位,index代表索引 */
	private int queue_index[];// 存储索引i信息queue_index[n]=i;队列中只存储索引的位置
	/** 索引在优先队列中的位置: index_queue[i]=n ;queue代表队列中的下标位,index代表索引 */
	private int index_queue[];// 索引存储对应的n index_queue[i]=n;方便根据索引查询
	/** 索引对应的数据:keys[index]=key */
	private Key keys[];// 存储索引对应的具体的数据keys[index]=key;
	private int n;// 队列中元素的个数
	private int maxN;// 队列的最大长度

	/**
	 * 初始化长度为maxN的数组
	 * 
	 * @param MaxN
	 */
	@SuppressWarnings("unchecked")
	public IndexMaxPQ2(int maxN) {
		this.maxN = maxN;
		this.n = 0;
		this.queue_index = new int[maxN + 1];
		this.index_queue = new int[maxN + 1];
		keys = (Key[]) new Comparable[maxN + 1];
		for (int i = 0; i <= maxN; i++)
			index_queue[i] = -1;
	}

	/**
	 * 是否包含索引i
	 * 
	 * @param i
	 * @return
	 */
	public boolean isContain(int i) {
		return index_queue[i] != -1;
	}

	/**
	 * 判断是队列是否为空
	 * 
	 * @return
	 */
	public boolean isEmpty() {
		return this.n == 0;
	}

	/**
	 * 判断是否已经满了
	 * 
	 * @return
	 */
	public boolean isFull() {
		return this.n == this.maxN;
	}

	/**
	 * 返回队列的长度
	 * 
	 * @return
	 */
	public int getSize() {
		return this.n;
	}

	/**
	 * 得到最优的数据对应的索引
	 * 
	 * @return
	 */
	public int getMaxOfIndex() {
		if (n == 0)
			throw new NoSuchElementException("Priority queue underflow");
		return queue_index[1];
	}

	/**
	 * 得到索引优先队列中最大的Key
	 * 
	 * @return
	 */
	public Key getMaxKey() {
		if (n == 0)
			throw new NoSuchElementException("Priority queue underflow");
		return keys[queue_index[1]];
	}

	/**
	 * 判断i是否小于j
	 * 
	 * @param i
	 * @param j
	 * @return
	 */
	private boolean less(int i, int j) {
		return keys[queue_index[i]].compareTo(keys[queue_index[j]]) < 0;
	}

	/**
	 * 交换两个元素的位置
	 * 
	 * @param i
	 * @param j
	 */
	private void exch(int i, int j) {
		int swap = queue_index[i];
		queue_index[i] = queue_index[j];
		queue_index[j] = swap;
		index_queue[queue_index[i]] = i;
		index_queue[queue_index[j]] = j;
	}

	/**
	 * 当新插入、删除或者数据发生变大时,上浮
	 * 
	 * @param k
	 */
	private void swim(int k) {
		// 根据pq[k]找到索引,k>1等价于k/2>=1
		while (k > 1 && less(k / 2, k)) {
			exch(k / 2, k);
			k = k / 2;
		}
	}

	/**
	 * 当数据变小时,下沉
	 * 
	 * @param k
	 */
	private void sink(int k) {

		// 判断2*k和2*k+1的大小,选出其中较大者与k比较
		while (2 * k <= n) {
			int j = 2 * k;
			if (j < n && less(j, j + 1))
				j++;
			if (!less(k, j))
				break;
			exch(k, j);
			k = j;
		}
	}

	public void insert(int i, Key key) {
		if (isContain(i))
			throw new IllegalArgumentException(
					"index is already in the priority queue");
		n++;
		index_queue[i] = n;
		queue_index[n] = i;
		keys[i] = key;
		swim(n);
	}

	/**
	 * 删除
	 * 
	 * @return
	 */
	public int delMax() {
		if (n == 0)
			throw new NoSuchElementException("Priority queue underflow");
		int min = queue_index[1];
		exch(1, n--);// 交换最后一个元素的位置,并将n减一
		sink(1);

		assert queue_index[n + 1] == min;
		index_queue[min] = -1; // delete
		keys[min] = null; // to help with garbage collection
		queue_index[n + 1] = -1; // not needed
		return min;
	}

	/**
	 * 根据索引拿到数据
	 * 
	 * @param i
	 * @return
	 */
	public Key keyOf(int i) {
		if (!isContain(i))
			throw new NoSuchElementException(
					"index is not in the priority queue");
		else
			return keys[i];
	}

	/**
	 * 改变索引的值
	 * 
	 * @param i
	 * @param key
	 */
	public void changeKey(int i, Key key) {
		if (!isContain(i))
			throw new NoSuchElementException(
					"index is not in the priority queue");
		keys[i] = key;
		swim(index_queue[i]);
		sink(index_queue[i]);
	}

	public void increaseKey(int i, Key key) {
		if (!isContain(i))
			throw new NoSuchElementException(
					"index is not in the priority queue");
		if (keys[i].compareTo(key) >= 0)
			throw new IllegalArgumentException(
					"Calling increaseKey() with given argument would not strictly increase the key");

		keys[i] = key;
		swim(index_queue[i]);
	}

	public void decreaseKey(int i, Key key) {
		if (!isContain(i))
			throw new NoSuchElementException(
					"index is not in the priority queue");
		if (keys[i].compareTo(key) <= 0)
			throw new IllegalArgumentException(
					"Calling decreaseKey() with given argument would not strictly decrease the key");

		keys[i] = key;
		sink(index_queue[i]);
	}

	@SuppressWarnings("unused")
	private class HeapIterator implements Iterator<Integer> {
		// create a new pq
		private IndexMaxPQ<Key> copy;

		// add all elements to copy of heap
		// takes linear time since already in heap order so no keys move
		public HeapIterator() {
			copy = new IndexMaxPQ<Key>(queue_index.length - 1);
			for (int i = 1; i <= n; i++)
				copy.insert(queue_index[i], keys[queue_index[i]]);
		}

		public boolean hasNext() {
			return !copy.isEmpty();
		}

		public void remove() {
			throw new UnsupportedOperationException();
		}

		public Integer next() {
			if (!hasNext())
				throw new NoSuchElementException();
			return copy.delMax();
		}
	}

	public static void main(String[] args) {
		// insert a bunch of strings
		String[] strings = { "it", "was", "the", "best", "of", "times", "it",
				"was", "the", "worst" };

		IndexMaxPQ<String> queue_index = new IndexMaxPQ<String>(strings.length);
		for (int i = 0; i < strings.length; i++) {
			queue_index.insert(i, strings[i]);
		}

		// print each key using the iterator
		for (int i : queue_index) {
			System.out.println(i + " " + strings[i]);
		}

		System.out.println();

		// // increase or decrease the key
		// for (int i = 0; i < strings.length; i++) {
		// if (StdRandom.uniform() < 0.5)
		// pq.increaseKey(i, strings[i] + strings[i]);
		// else
		// pq.decreaseKey(i, strings[i].substring(0, 1));
		// }

		// delete and print each key
		while (!queue_index.isEmpty()) {
			String key = queue_index.maxKey();
			int i = queue_index.delMax();
			System.out.println(i + " " + key);
		}
		System.out.println();

		// reinsert the same strings
		for (int i = 0; i < strings.length; i++) {
			queue_index.insert(i, strings[i]);
		}

		// delete them in random order
		int[] perm = new int[strings.length];
		for (int i = 0; i < strings.length; i++)
			perm[i] = i;
		// StdRandom.shuffle(perm);
		for (int i = 0; i < perm.length; i++) {
			String key = queue_index.keyOf(perm[i]);
			queue_index.delete(perm[i]);
			System.out.println(perm[i] + " " + key);
		}

	}
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值