PriorityQueue.toString wrong element order

ε祈祈猫儿з 提交于 2019-11-26 10:01:46

问题


I am trying to make a priority queue in java with the nodes with the lowest frequency in priority. However, my comparator is not working and the output is very weird. I believe I need to change my comparator but I am not sure how to change it. Here is my code:

public class HuffmanComparator implements Comparator<TreeNodeHuffman> {
    public int compare(TreeNodeHuffman p1, TreeNodeHuffman p2) {
        if (p1.frequency < p2.frequency) return -1;
        if (p1.frequency > p2.frequency) return 1;
        return 0;
    }    
}

public class TreeNodeHuffman {
public static void main(String[] args) {    
    HuffmanComparator compare = new HuffmanComparator();
    TreeNodeHuffman e = new TreeNodeHuffman(\'e\', 12702);
    TreeNodeHuffman t = new TreeNodeHuffman(\'t\', 9056);
    TreeNodeHuffman a = new TreeNodeHuffman(\'a\', 8167);
    TreeNodeHuffman o = new TreeNodeHuffman(\'o\', 7507);
    TreeNodeHuffman i = new TreeNodeHuffman(\'i\', 6966);
    TreeNodeHuffman n = new TreeNodeHuffman(\'a\', 6749);
    TreeNodeHuffman s = new TreeNodeHuffman(\'s\', 6327);
    TreeNodeHuffman h = new TreeNodeHuffman(\'h\', 6094);
    TreeNodeHuffman r = new TreeNodeHuffman(\'r\', 5987);
    TreeNodeHuffman d = new TreeNodeHuffman(\'d\', 4253);
    TreeNodeHuffman l = new TreeNodeHuffman(\'l\', 4025);
    TreeNodeHuffman c = new TreeNodeHuffman(\'c\', 2782);
    TreeNodeHuffman u = new TreeNodeHuffman(\'u\', 2758);
    TreeNodeHuffman m = new TreeNodeHuffman(\'m\', 2406);
    TreeNodeHuffman w = new TreeNodeHuffman(\'w\', 2360);
    TreeNodeHuffman f = new TreeNodeHuffman(\'f\', 2228);
    TreeNodeHuffman g = new TreeNodeHuffman(\'g\', 2015);
    TreeNodeHuffman y = new TreeNodeHuffman(\'y\', 1974);
    TreeNodeHuffman p = new TreeNodeHuffman(\'p\', 1929);
    TreeNodeHuffman b = new TreeNodeHuffman(\'b\', 1492);
    TreeNodeHuffman v = new TreeNodeHuffman(\'v\', 978);
    TreeNodeHuffman k = new TreeNodeHuffman(\'k\', 772);
    TreeNodeHuffman j = new TreeNodeHuffman(\'j\', 153);
    TreeNodeHuffman x = new TreeNodeHuffman(\'x\', 150);
    TreeNodeHuffman q = new TreeNodeHuffman(\'q\', 95);
    TreeNodeHuffman z = new TreeNodeHuffman(\'z\', 74);
    PriorityQueue<TreeNodeHuffman> queue = new PriorityQueue<TreeNodeHuffman>(26, compare);
    queue.add(e);
    queue.add(t);
    queue.add(a);
    queue.add(o);
    queue.add(i);
    queue.add(n);
    queue.add(s);
    queue.add(h);
    queue.add(r);
    queue.add(d);
    queue.add(l);
    queue.add(c);
    queue.add(u);
    queue.add(m);
    queue.add(w);
    queue.add(f);
    queue.add(g);
    queue.add(y);
    queue.add(p);
    queue.add(b);
    queue.add(v);
    queue.add(k);
    queue.add(j);
    queue.add(x);
    queue.add(q);
    queue.add(z);
    System.out.println(queue);
}
}

The output is as follows: [z, k, q, g, v, x, u, d, f, y, b, m, j, i, c, e, s, o, w, a, r, h, p, t, l, a]. However, the output should be [z, q, x, j, k, v, b........]. Thanks in advance!


回答1:


You need to poll the items from the PriorityQueue one by one. toString doesn't do that.

So instead of your System.out.println(queue); do this:

while(!queue.isEmpty()) {
   System.out.println(queue.poll());
}

The reason is that the PriorityQueue is never completely sorted internally, lookup how a heap works for more detail. Polling items from it fixes the heap during the calls, thus it should output the elements in sorted order.




回答2:


The System.out.println(queue) is printing the queue unsorted. If you want to print the queue real order follow the below code which use poll to get the elements from the queue top to bottom:

TreeNodeHuffman tn = null;
    do{
        tn = queue.poll();
        if(tn!=null){
            System.out.print(tn.key+",");
        }
    }while(tn != null);

and you shall see this output as expected:

z,q,x,j,k,v,b,p,y,g,f,w,m,u,c,l,d,r,h,s,a,i,o,a,t,e,




回答3:


You want lower frequency to go higher so :

  public int compare(TreeNodeHuffman p1, TreeNodeHuffman p2) {
          if (p1.frequency < p2.frequency) return 1;
          if (p1.frequency > p2.frequency) return -1;
          return 0;
      }    
   }

If you want to test it, send it to a single threaded pool and see the order of jobs being processed instead of to string or iterator. as doc says at http://docs.oracle.com/javase/7/docs/api/java/util/PriorityQueue.html#iterator%28%29 :

Returns an iterator over the elements in this queue. The iterator does not return the elements in any particular order.

Can see http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Executors.html#newSingleThreadExecutor%28%29 for a quick single threaded pool to test this.




回答4:


@Thomas answer works.

My approach is to produce same result without actually emptying the queue . So, instead I created a wrapper over the PriorityQueue, and implemented next() and hasNext() for it. Also, to exactly simulate the priority queue behavior, extend AbstractQueue and delegate calls to methods like offer, peek, poll and size through PriorityQueue object.

priorityQueueObject.methodName()

Disclaimer: This does cost copying the whole queue into a list and doing the sorting over it.

public class MyPriorityQueue<E extends Comparable<T>, T> extends AbstractQueue<E> {
    Integer arrOfInts[] = { 11, 7, 15, 10, 2, 1, 4, 5, 7, 2, 18, 1, 19};
    PriorityQueue<E> pq = new PriorityQueue<>();

    public static void main(String[] args) {
        MyPriorityQueue mpq = new MyPriorityQueue<>();
        mpq.addAll(Arrays.asList(arrOfInts));

        //Using iterator
        Iterator it = mpq.iterator();
        System.out.println("The internal priority queue:"  + mpq.pq);
        System.out.println("Using Iterator:");
        while(it.hasNext()) {
            System.out.print(it.next() + ", ");
        }

        System.out.println("\nUsing simple system out println:");
        System.out.println(mpq);

        System.out.println("Using foreach: ");
        for(Object o : mpq) {
            System.out.print(o + ", ");
        }
    }

    @Override
    public boolean offer(E arg0) {
        return pq.offer(arg0);
    }

    @Override
    public E peek() {
        return pq.peek();
    }

    @Override
    public E poll() {
        return pq.poll();
    }

    @Override
    public Iterator<E> iterator() {
        ArrayList<E> list = new ArrayList(Arrays.asList(pq.toArray()));
        Collections.sort(list, null);
        return new Iterator<E>() {
            @Override
            public boolean hasNext() {
                return !list.isEmpty();
            }

            @Override
            public E next() {
                assert (hasNext());
                return list.remove(0);
            }
        };
    }

    @Override
    public int size() {
        return pq.size();
    }
}

prints:

The internal priority queue:[1, 2, 1, 7, 5, 2, 4, 11, 7, 10, 18, 15, 19]
Using Iterator:
1, 1, 2, 2, 4, 5, 7, 7, 10, 11, 15, 18, 19, 
Using simple system out println:
[1, 1, 2, 2, 4, 5, 7, 7, 10, 11, 15, 18, 19]
Using foreach: 
1, 1, 2, 2, 4, 5, 7, 7, 10, 11, 15, 18, 19, 


来源:https://stackoverflow.com/questions/27806315/priorityqueue-tostring-wrong-element-order

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!