代码改变世界

【转载】索引优先队列

2018-07-10 15:32  Lyp_02  阅读(114)  评论(0)    收藏  举报

来自 https://www.cnblogs.com/nullzx/p/6624731.html
同时参考算法 第4版的算法如下

/******************************************************************************

  • Compilation: javac IndexMinPQ.java
  • Execution: java IndexMinPQ
  • Dependencies: StdOut.java
  • Minimum-oriented indexed PQ implementation using a binary heap.

******************************************************************************/

package edu.princeton.cs.algs4;

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

/**

  • The {@code IndexMinPQ} class represents an indexed priority queue of generic keys.

  • It supports the usual insert and delete-the-minimum

  • operations, along with delete and change-the-key

  • methods. In order to let the client refer to keys on the priority queue,

  • an integer between {@code 0} and

  • is associated with each key—the client uses this integer to specify

  • which key to delete or change.

  • It also supports methods for peeking at the minimum key,

  • testing if the priority queue is empty, and iterating through

  • the keys.

  • This implementation uses a binary heap along with an array to associate

  • keys with integers in the given range.

  • The insert, delete-the-minimum, delete,

  • change-key, decrease-key, and increase-key

  • operations take logarithmic time.

  • The is-empty, size, min-index, min-key,

  • and key-of operations take constant time.

  • Construction takes time proportional to the specified capacity.

  • For additional documentation, see Section 2.4 of

  • Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.

  • @author Robert Sedgewick

  • @author Kevin Wayne

  • @param the generic type of key on this priority queue
    */
    public class IndexMinPQ<Key extends Comparable> implements Iterable {
    private int maxN; // maximum number of elements on PQ
    private int n; // number of elements on PQ
    private int[] pq; // binary heap using 1-based indexing
    private int[] qp; // inverse of pq - qp[pq[i]] = pq[qp[i]] = i
    private Key[] keys; // keys[i] = priority of i

    /**

    • Initializes an empty indexed priority queue with indices between
    • and {@code maxN - 1}.
    • @param maxN the keys on this priority queue are index from
    • @throws IllegalArgumentException if {@code maxN < 0}
      */
      public IndexMinPQ(int maxN) {
      if (maxN < 0) throw new IllegalArgumentException();
      this.maxN = maxN;
      n = 0;
      keys = (Key[]) new Comparable[maxN + 1]; // make this of length maxN??
      pq = new int[maxN + 1];
      qp = new int[maxN + 1]; // make this of length maxN??
      for (int i = 0; i <= maxN; i++)
      qp[i] = -1;
      }

    /**

    • Returns true if this priority queue is empty.
    • @return {@code true} if this priority queue is empty;
    • {@code false} otherwise
      */
      public boolean isEmpty() {
      return n == 0;
      }

    /**

    • Is {@code i} an index on this priority queue?
    • @param i an index
    • @return {@code true} if {@code i} is an index on this priority queue;
    • {@code false} otherwise
    • @throws IllegalArgumentException unless {@code 0 <= i < maxN}
      */
      public boolean contains(int i) {
      if (i < 0 || i >= maxN) throw new IllegalArgumentException();
      return qp[i] != -1;
      }

    /**

    • Returns the number of keys on this priority queue.
    • @return the number of keys on this priority queue
      */
      public int size() {
      return n;
      }

    /**

    • Associates key with index {@code i}.
    • @param i an index
    • @param key the key to associate with index
    • @throws IllegalArgumentException unless
    • @throws IllegalArgumentException if there already is an item associated
    • with index {@code i}
      */
      public void insert(int i, Key key) {
      if (i < 0 || i >= maxN) throw new IllegalArgumentException();
      if (contains(i)) throw new IllegalArgumentException("index is already in the priority queue");
      n++;
      qp[i] = n;
      pq[n] = i;
      keys[i] = key;
      swim(n);
      }

    /**

    • Returns an index associated with a minimum key.
    • @return an index associated with a minimum key
    • @throws NoSuchElementException if this priority queue is empty
      */
      public int minIndex() {
      if (n == 0) throw new NoSuchElementException("Priority queue underflow");
      return pq[1];
      }

    /**

    • Returns a minimum key.
    • @return a minimum key
    • @throws NoSuchElementException if this priority queue is empty
      */
      public Key minKey() {
      if (n == 0) throw new NoSuchElementException("Priority queue underflow");
      return keys[pq[1]];
      }

    /**

    • Removes a minimum key and returns its associated index.
    • @return an index associated with a minimum key
    • @throws NoSuchElementException if this priority queue is empty
      */
      public int delMin() {
      if (n == 0) throw new NoSuchElementException("Priority queue underflow");
      int min = pq[1];
      exch(1, n--);
      sink(1);
      assert min == pq[n+1];
      qp[min] = -1; // delete
      keys[min] = null; // to help with garbage collection
      pq[n+1] = -1; // not needed
      return min;
      }

    /**

    • Returns the key associated with index {@code i}.
    • @param i the index of the key to return
    • @return the key associated with index
    • @throws IllegalArgumentException unless
    • @throws NoSuchElementException no key is associated with index {@code i}
      */
      public Key keyOf(int i) {
      if (i < 0 || i >= maxN) throw new IllegalArgumentException();
      if (!contains(i)) throw new NoSuchElementException("index is not in the priority queue");
      else return keys[i];
      }

    /**

    • Change the key associated with index {@code i} to the specified value.
    • @param i the index of the key to change
    • @param key change the key associated with index {@code i} to this key
    • @throws IllegalArgumentException unless
    • @throws NoSuchElementException no key is associated with index {@code i}
      */
      public void changeKey(int i, Key key) {
      if (i < 0 || i >= maxN) throw new IllegalArgumentException();
      if (!contains(i)) throw new NoSuchElementException("index is not in the priority queue");
      keys[i] = key;
      swim(qp[i]);
      sink(qp[i]);
      }

    /**

    • Change the key associated with index {@code i} to the specified value.
    • @param i the index of the key to change
    • @param key change the key associated with index {@code i} to this key
    • @throws IllegalArgumentException unless
    • @deprecated Replaced by {@code changeKey(int, Key)}.
      */
      @Deprecated
      public void change(int i, Key key) {
      changeKey(i, key);
      }

    /**

    • Decrease the key associated with index {@code i} to the specified value.
    • @param i the index of the key to decrease
    • @param key decrease the key associated with index {@code i} to this key
    • @throws IllegalArgumentException unless
    • @throws IllegalArgumentException if
    • @throws NoSuchElementException no key is associated with index {@code i}
      */
      public void decreaseKey(int i, Key key) {
      if (i < 0 || i >= maxN) throw new IllegalArgumentException();
      if (!contains(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;
      swim(qp[i]);
      }

    /**

    • Increase the key associated with index {@code i} to the specified value.
    • @param i the index of the key to increase
    • @param key increase the key associated with index {@code i} to this key
    • @throws IllegalArgumentException unless
    • @throws IllegalArgumentException if
    • @throws NoSuchElementException no key is associated with index {@code i}
      */
      public void increaseKey(int i, Key key) {
      if (i < 0 || i >= maxN) throw new IllegalArgumentException();
      if (!contains(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;
      sink(qp[i]);
      }

    /**

    • Remove the key associated with index {@code i}.
    • @param i the index of the key to remove
    • @throws IllegalArgumentException unless
    • @throws NoSuchElementException no key is associated with index {@code i}
      */
      public void delete(int i) {
      if (i < 0 || i >= maxN) throw new IllegalArgumentException();
      if (!contains(i)) throw new NoSuchElementException("index is not in the priority queue");
      int index = qp[i];
      exch(index, n--);
      swim(index);
      sink(index);
      keys[i] = null;
      qp[i] = -1;
      }

/***************************************************************************
* General helper functions.
***************************************************************************/
private boolean greater(int i, int j) {
return keys[pq[i]].compareTo(keys[pq[j]]) > 0;
}

private void exch(int i, int j) {
int swap = pq[i];
pq[i] = pq[j];
pq[j] = swap;
qp[pq[i]] = i;
qp[pq[j]] = j;
}

/***************************************************************************
* Heap helper functions.
***************************************************************************/
private void swim(int k) {
while (k > 1 && greater(k/2, k)) {
exch(k, k/2);
k = k/2;
}
}

private void sink(int k) {
while (2k <= n) {
int j = 2
k;
if (j < n && greater(j, j+1)) j++;
if (!greater(k, j)) break;
exch(k, j);
k = j;
}
}

/***************************************************************************
* Iterators.
***************************************************************************/

/**
* Returns an iterator that iterates over the keys on the
* priority queue in ascending order.
* The iterator doesn't implement {@code remove()} since it's optional.
*
* @return an iterator that iterates over the keys in ascending order
*/
public Iterator iterator() { return new HeapIterator(); }

private class HeapIterator implements Iterator {
// create a new pq
private IndexMinPQ copy;

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

public boolean hasNext() { return !copy.isEmpty(); }
public void remove() { throw new UnsupportedOperationException(); }

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

/**
* Unit tests the {@code IndexMinPQ} data type.
*
* @param args the command-line arguments
*/
public static void main(String[] args) {
// insert a bunch of strings
String[] strings = { "it", "was", "the", "best", "of", "times", "it", "was", "the", "worst" };

IndexMinPQ pq = new IndexMinPQ(strings.length);
for (int i = 0; i < strings.length; i++) {
pq.insert(i, strings[i]);
}

// delete and print each key
while (!pq.isEmpty()) {
int i = pq.delMin();
StdOut.println(i + " " + strings[i]);
}
StdOut.println();

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

// print each key using the iterator
for (int i : pq) {
StdOut.println(i + " " + strings[i]);
}
while (!pq.isEmpty()) {
pq.delMin();
}

}
}

/******************************************************************************

  • Copyright 2002-2018, Robert Sedgewick and Kevin Wayne.
  • This file is part of algs4.jar, which accompanies the textbook
  • Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
  • Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
  • http://algs4.cs.princeton.edu
  • algs4.jar is free software: you can redistribute it and/or modify
  • it under the terms of the GNU General Public License as published by
  • the Free Software Foundation, either version 3 of the License, or
  • (at your option) any later version.
  • algs4.jar is distributed in the hope that it will be useful,
  • but WITHOUT ANY WARRANTY; without even the implied warranty of
  • MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  • GNU General Public License for more details.
  • You should have received a copy of the GNU General Public License
  • along with algs4.jar. If not, see http://www.gnu.org/licenses.
    ******************************************************************************/