AlgorithmsI PA2: Randomized Queues and Deques RandomizedQueue

RandomizedQueue 有几个关键点:

1. 选择合适的数据结构,因为需要任意位置删除元素,Linked list 做不到,必须使用resizing arrays.

2. resizing 的技巧。

    Q. How to grow array?
    A. If array is full, create a new array of twice the size, and copy items. 

    Q. How to shrink array? 
    A: halve size of array when array is one-quarter full 
3. 正确使用StdRandom.shuffle. 要能实现并行使用Iterator,洗牌不是洗array 本身,而是生成一个乱序的index. 

Java code:
//RandomizedQueue - should be implemented using resizing arrays
import edu.princeton.cs.algs4.StdIn; 
import edu.princeton.cs.algs4.StdOut; 
import edu.princeton.cs.algs4.StdRandom;
import java.util.Iterator;
import java.util.NoSuchElementException;

public class RandomizedQueue<Item> implements Iterable<Item> {
    private Item[] q;         // array of items
    private int N;            // number of elements 
    
    // construct an empty randomized queue
    public RandomizedQueue()  {               
        q = (Item[]) new Object[1];
        N = 0;
    }
    
    // is the queue empty?
    public boolean isEmpty()  {               
         return N == 0;
    }
    
    // return the number of items on the queue
    public int size()  {                     
        return N;
    }
    
    // resize the underlying array holding the elements
    private void resize(int capacity) {
        assert capacity >= N;
        Item[] temp = (Item[]) new Object[capacity];
        for (int i = 0; i < N; i++) {
            temp[i] = q[i];
        }
        q = temp;
    }
    
    // add the item
    //Throw a java.lang.NullPointerException if the client attempts to add a null item
    public void enqueue(Item item)  {     
        if(item == null) {
            throw new NullPointerException("add a null item");
        }
        if(N == q.length) {
             resize(2 * q.length);   // double size of array if necessary
        }
        q[N++] = item;              // add item
    }
    
    /*when deleting random element you can just simply switch it with the last element in array 
     * and decrease the array size counter. So deletion will take constant time.
     *throw a java.util.NoSuchElementException if the client attempts to sample or dequeue an item 
     *from an empty randomized queue;
    */
    // remove and return a random item
    public Item dequeue()  {                  
        if (isEmpty()) {
            throw new NoSuchElementException("No element");
        }
        int x = StdRandom.uniform(N);
        Item item = q[x];
        q[x] = q[--N];
        q[N] = null;
        
        if (N == q.length / 4 && N > 0) {
            resize(q.length / 2);
        }
        return item;
    }
    
    // return (but do not remove) a random item
    public Item sample()  {                  
        if(isEmpty()) {
            throw new NoSuchElementException("No element");
        }
         int x = StdRandom.uniform(N);
         return q[x];        
    }
    
    // return an independent iterator over items in random order
    public Iterator<Item> iterator()  {   
         return new ArrayIterator();
    }
    
    private class ArrayIterator implements Iterator<Item> {
         private int i;
         private int[] indexSequence;
         
         public ArrayIterator() {
             i = 0;
             indexSequence = new int[N];
             for (int j = 0; j < N; j++) {
                 indexSequence[j] = j;
             }
             StdRandom.shuffle(indexSequence);
         }
    
         public boolean hasNext()  { 
             return i < N ;      
         }
         public void remove() { 
             throw new UnsupportedOperationException();  
         }
         
         public Item next() {
             if (!hasNext()) { 
                 throw new NoSuchElementException();
             }
            return q[indexSequence[i++]];
         }
    }
    
    public static void main(String[] args) {   // unit testing
    
    }
}
原文地址:https://www.cnblogs.com/anne-vista/p/4843187.html