/* -*- tab-width: 4 -*- * * Electric(tm) VLSI Design System * * File: SplayTree.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; /** * Implements a top-down splay tree. * Available at http://www.link.cs.cmu.edu/splay/ * ftp://ftp.cs.cmu.edu/usr/ftp/usr/sleator/splaying/SplayTree.java * Original author: Danny Sleator <sleator@cs.cmu.edu> * Original notice: This code is in the public domain. * * Adapted specially for our nodes to avoid allocations * * Node.children[] is reused: * 2: left, 3: right * * @author Jonas Thedering * @author Christian Jülg */ public class SplayTree { private Node root; private Node header = new Node(); // For splay public SplayTree() { clear(); } public void clear() { root = null; header.children[2] = null; header.children[3] = null; } /** * Insert into the tree. * @param x the item to insert. * @throws DuplicateItemException if x is already present. */ public void insert(Node key) { Node n; int c; key.children[2] = null; key.children[3] = null; if (root == null) { root = key; return; } splay(key); if ((c = key.f - root.f) == 0) { assert false : "Duplicate item to be inserted into splay tree"; return; } n = key; if (c < 0) { n.children[2] = root.children[2]; n.children[3] = root; root.children[2] = null; } else { n.children[3] = root.children[3]; n.children[2] = root; root.children[3] = null; } root = n; } /** * Remove from the tree. * @param x the item to remove. * @throws ItemNotFoundException if x is not found. */ public void remove(Node key) { splay(key); if (key.f != root.f) { assert false : "Item not found in splay tree"; return; } // Now delete the root if (root.children[2] == null) { root = root.children[3]; } else { Node x = root.children[3]; root = root.children[2]; splay(key); root.children[3] = x; } } /** * Find the smallest item in the tree. */ public Node findMin() { Node x = root; if(root == null) return null; while(x.children[2] != null) x = x.children[2]; splay(x); return x; } /** * Find an item in the tree. */ public Node find(Node key) { if (root == null) return null; splay(key); if(root.f != key.f) return null; return root; } /** * Test if the tree is logically empty. * @return true if empty, false otherwise. */ public boolean isEmpty() { return root == null; } /** * Internal method to perform a top-down splay. * * splay(key) does the splay operation on the given key. * If key is in the tree, then the BinaryNode containing * that key becomes the root. If key is not in the tree, * then after the splay, key.root is either the greatest key * < key in the tree, or the lest key > key in the tree. * * This means, among other things, that if you splay with * a key that's larger than any in the tree, the rightmost * node of the tree becomes the root. This property is used * in the delete() method. */ private void splay(Node key) { Node l, r, t, y; l = r = header; t = root; header.children[2] = header.children[3] = null; for (;;) { if (key.f < t.f) { if (t.children[2] == null) break; if (key.f < t.children[2].f) { y = t.children[2]; /* rotate right */ t.children[2] = y.children[3]; y.children[3] = t; t = y; if (t.children[2] == null) break; } r.children[2] = t; /* link right */ r = t; t = t.children[2]; } else if (key.f > t.f) { if (t.children[3] == null) break; if (key.f > t.children[3].f) { y = t.children[3]; /* rotate left */ t.children[3] = y.children[2]; y.children[2] = t; t = y; if (t.children[3] == null) break; } l.children[3] = t; /* link left */ l = t; t = t.children[3]; } else { break; } } l.children[3] = t.children[2]; /* assemble */ r.children[2] = t.children[3]; t.children[2] = header.children[3]; t.children[3] = header.children[2]; root = t; } }