代码改变世界

【转载】索引优先队列

2018-07-10 15:32  Lyp_02  阅读(100)  评论(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
    •     {@code maxN - 1}
      
    • @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 (2*k <= 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<Integer> iterator() { return new HeapIterator(); }

private class HeapIterator implements Iterator<Integer> {
    // create a new pq
    private IndexMinPQ<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 IndexMinPQ<Key>(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<String> pq = new IndexMinPQ<String>(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.
    ******************************************************************************/