<!DOCTYPE html>
<!--
Copyright (c) 2012 The Chromium Authors. All rights reserved.
Use of this source code is governed by a BSD-style license that can be
found in the LICENSE file.
-->
<link rel="import" href="/base/base.html">
<script>
'use strict';

/**
 * @fileoverview Splay tree used by CodeMap.
 */
tr.exportTo('tr.e.importer.v8', function() {
  /**
   * Constructs a Splay tree.  A splay tree is a self-balancing binary
   * search tree with the additional property that recently accessed
   * elements are quick to access again. It performs basic operations
   * such as insertion, look-up and removal in O(log(n)) amortized time.
   *
   * @constructor
   */
  function SplayTree() { };

  /**
   * Pointer to the root node of the tree.
   *
   * @type {SplayTree.Node}
   * @private
   */
  SplayTree.prototype.root_ = null;

  /**
   * @return {boolean} Whether the tree is empty.
   */
  SplayTree.prototype.isEmpty = function() {
    return !this.root_;
  };

  /**
   * Inserts a node into the tree with the specified key and value if
   * the tree does not already contain a node with the specified key. If
   * the value is inserted, it becomes the root of the tree.
   *
   * @param {number} key Key to insert into the tree.
   * @param {*} value Value to insert into the tree.
   */
  SplayTree.prototype.insert = function(key, value) {
    if (this.isEmpty()) {
      this.root_ = new SplayTree.Node(key, value);
      return;
    }
    // Splay on the key to move the last node on the search path for
    // the key to the root of the tree.
    this.splay_(key);
    if (this.root_.key == key) {
      return;
    }
    var node = new SplayTree.Node(key, value);
    if (key > this.root_.key) {
      node.left = this.root_;
      node.right = this.root_.right;
      this.root_.right = null;
    } else {
      node.right = this.root_;
      node.left = this.root_.left;
      this.root_.left = null;
    }
    this.root_ = node;
  };


  /**
   * Removes a node with the specified key from the tree if the tree
   * contains a node with this key. The removed node is returned. If the
   * key is not found, an exception is thrown.
   *
   * @param {number} key Key to find and remove from the tree.
   * @return {SplayTree.Node} The removed node.
   */
  SplayTree.prototype.remove = function(key) {
    if (this.isEmpty()) {
      throw Error('Key not found: ' + key);
    }
    this.splay_(key);
    if (this.root_.key != key) {
      throw Error('Key not found: ' + key);
    }
    var removed = this.root_;
    if (!this.root_.left) {
      this.root_ = this.root_.right;
    } else {
      var right = this.root_.right;
      this.root_ = this.root_.left;
      // Splay to make sure that the new root has an empty right child.
      this.splay_(key);
      // Insert the original right child as the right child of the new
      // root.
      this.root_.right = right;
    }
    return removed;
  };


  /**
   * Returns the node having the specified key or null if the tree doesn't
   * contain a node with the specified key.
   *
   *
   * @param {number} key Key to find in the tree.
   * @return {SplayTree.Node} Node having the specified key.
   */
  SplayTree.prototype.find = function(key) {
    if (this.isEmpty()) {
      return null;
    }
    this.splay_(key);
    return this.root_.key == key ? this.root_ : null;
  };

  /**
   * @return {SplayTree.Node} Node having the minimum key value.
   */
  SplayTree.prototype.findMin = function() {
    if (this.isEmpty()) {
      return null;
    }
    var current = this.root_;
    while (current.left) {
      current = current.left;
    }
    return current;
  };

  /**
   * @return {SplayTree.Node} Node having the maximum key value.
   */
  SplayTree.prototype.findMax = function(opt_startNode) {
    if (this.isEmpty()) {
      return null;
    }
    var current = opt_startNode || this.root_;
    while (current.right) {
      current = current.right;
    }
    return current;
  };

  /**
   * @return {SplayTree.Node} Node having the maximum key value that
   *     is less or equal to the specified key value.
   */
  SplayTree.prototype.findGreatestLessThan = function(key) {
    if (this.isEmpty()) {
      return null;
    }
    // Splay on the key to move the node with the given key or the last
    // node on the search path to the top of the tree.
    this.splay_(key);
    // Now the result is either the root node or the greatest node in
    // the left subtree.
    if (this.root_.key <= key) {
      return this.root_;
    } else if (this.root_.left) {
      return this.findMax(this.root_.left);
    } else {
      return null;
    }
  };

  /**
   * @return {Array<*>} An array containing all the values of tree's nodes
   * paired with keys.
   *
   */
  SplayTree.prototype.exportKeysAndValues = function() {
    var result = [];
    this.traverse_(function(node) { result.push([node.key, node.value]); });
    return result;
  };

  /**
   * @return {Array<*>} An array containing all the values of tree's nodes.
   */
  SplayTree.prototype.exportValues = function() {
    var result = [];
    this.traverse_(function(node) { result.push(node.value); });
    return result;
  };

  /**
   * Perform the splay operation for the given key. Moves the node with
   * the given key to the top of the tree.  If no node has the given
   * key, the last node on the search path is moved to the top of the
   * tree. This is the simplified top-down splaying algorithm from:
   * "Self-adjusting Binary Search Trees" by Sleator and Tarjan
   *
   * @param {number} key Key to splay the tree on.
   * @private
   */
  SplayTree.prototype.splay_ = function(key) {
    if (this.isEmpty()) {
      return;
    }
    // Create a dummy node.  The use of the dummy node is a bit
    // counter-intuitive: The right child of the dummy node will hold
    // the L tree of the algorithm.  The left child of the dummy node
    // will hold the R tree of the algorithm.  Using a dummy node, left
    // and right will always be nodes and we avoid special cases.
    var dummy, left, right;
    dummy = left = right = new SplayTree.Node(null, null);
    var current = this.root_;
    while (true) {
      if (key < current.key) {
        if (!current.left) {
          break;
        }
        if (key < current.left.key) {
          // Rotate right.
          var tmp = current.left;
          current.left = tmp.right;
          tmp.right = current;
          current = tmp;
          if (!current.left) {
            break;
          }
        }
        // Link right.
        right.left = current;
        right = current;
        current = current.left;
      } else if (key > current.key) {
        if (!current.right) {
          break;
        }
        if (key > current.right.key) {
          // Rotate left.
          var tmp = current.right;
          current.right = tmp.left;
          tmp.left = current;
          current = tmp;
          if (!current.right) {
            break;
          }
        }
        // Link left.
        left.right = current;
        left = current;
        current = current.right;
      } else {
        break;
      }
    }
    // Assemble.
    left.right = current.left;
    right.left = current.right;
    current.left = dummy.right;
    current.right = dummy.left;
    this.root_ = current;
  };

  /**
   * Performs a preorder traversal of the tree.
   *
   * @param {function(SplayTree.Node)} f Visitor function.
   * @private
   */
  SplayTree.prototype.traverse_ = function(f) {
    var nodesToVisit = [this.root_];
    while (nodesToVisit.length > 0) {
      var node = nodesToVisit.shift();
      if (node == null) {
        continue;
      }
      f(node);
      nodesToVisit.push(node.left);
      nodesToVisit.push(node.right);
    }
  };

  /**
   * Constructs a Splay tree node.
   *
   * @param {number} key Key.
   * @param {*} value Value.
   */
  SplayTree.Node = function(key, value) {
    this.key = key;
    this.value = value;
  };

  /**
   * @type {SplayTree.Node}
   */
  SplayTree.Node.prototype.left = null;

  /**
   * @type {SplayTree.Node}
   */
  SplayTree.Node.prototype.right = null;

  return {
    SplayTree: SplayTree
  };
});
</script>
