/* -*- tab-width: 4 -*- * * Electric(tm) VLSI Design System * * File: PriorityQueue.java * Written by: Christian Julg, Jonas Thedering (Team 1) * * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. * * Electric(tm) 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. * * Electric(tm) 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 Electric(tm); see the file COPYING. If not, write to * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, * Boston, Mass 02111-1307, USA. */ package com.sun.electric.tool.routing.experimentalAStar1; import java.util.Random; /** * This class implements a priority queue by using a splay tree and forming a * doubly linked list for entries with the same key * * this list is ordered (numbers represent add order: * (0, n-1, n-2, ..., 1) * remove order will happen reverse to addition, * i.e. the double linked list works as a LIFO / stack data structure * * Node.children[] is reused: * 0: prev, 1: next * * @author Jonas Thedering * @author Christian Jülg */ public class PriorityQueue { SplayTree tree = new SplayTree(); public void clear() { tree.clear(); } public void add(Node node) { Node equalNode = tree.find(node); if(equalNode == null) { node.children[0] = null; node.children[1] = null; tree.insert(node); } else { node.children[1] = equalNode.children[1]; if(equalNode.children[1] != null) equalNode.children[1].children[0] = node; equalNode.children[1] = node; node.children[0] = equalNode; } } public Node remove() { Node firstNode = tree.findMin(); if(firstNode == null) return null; else if(firstNode.children[1] == null) { tree.remove(firstNode); return firstNode; } else { Node result = firstNode.children[1]; firstNode.children[1] = result.children[1]; if(result.children[1] != null) result.children[1].children[0] = firstNode; return result; } } public boolean isEmpty() { return tree.isEmpty(); } /** Updates the f value for the given node and updates its position in the queue */ public void decreaseKey(Node node, int newKey) { // Unfortunately, there is no decreaseKey method in the splay tree if(node.children[0] != null) { node.children[0].children[1] = node.children[1]; if(node.children[1] != null) node.children[1].children[0] = node.children[0]; } else { tree.remove(node); Node next = node.children[1]; if(next != null) { next.children[0] = null; tree.insert(next); } } node.f = newKey; add(node); } // "Unit test" public static void main(String[] args) throws Exception { PriorityQueue queue = new PriorityQueue(); long seed = System.currentTimeMillis(); //seed= 1275391773870l; System.out.printf("Seed: %d\n", seed); Random r = new Random(seed); int[] testValues = new int[50000]; Node[] testNodes = new Node[testValues.length]; for(int i = 0; i < testValues.length; ++i) testValues[i] = r.nextInt(1000000); for(int i = 0; i < testValues.length; ++i) { Node node = new Node(); node.initialize(1, 2, 3); node.childCount = -1; node.children[0] = node; node.children[1] = node; node.f = testValues[i]; queue.add(node); testNodes[i] = node; } for(int i = 100; i < testValues.length; i += 19) { queue.decreaseKey(testNodes[i], testNodes[i].f - 1); queue.decreaseKey(testNodes[i-1], testNodes[i-1].f - 12345); } int previousValue = Integer.MIN_VALUE; int count = 0; while(!queue.isEmpty()) { ++count; Node node = queue.remove(); //System.out.printf("%d, ", node.f); if(node.f < previousValue) throw new Exception("Wrong order"); previousValue = node.f; } if(count != testValues.length) throw new Exception("Wrong value count: " + count); System.out.println("ok"); } }