Exemple #1
0
  /**
   * Set up the threads with the help of extreme nodes. A node is "extreme" when it is the
   * leftmost/rightmost in the lowest level.
   *
   * <p>1. work out left and right subtree 2. get extreme nodes from the left and right subtree 3.
   * calculate the offset from parent & set a new thread if required
   *
   * @return the leftmost and the rightmost node on the deepest level of the subtree rooted at this
   *     node
   */
  private NodePair<BSTNode> RTPreposition() {
    NodePair<BSTNode> result = new NodePair<BSTNode>();
    NodePair<BSTNode> fromLeftSubtree = null, fromRightSubtree = null;
    offset = 0;

    // 1. & 2. work out left & right subtree
    if (getLeft() != null) fromLeftSubtree = getLeft().RTPreposition();
    if (getRight() != null) fromRightSubtree = getRight().RTPreposition();
    // 3. examine this node
    if (isLeaf()) {
      if (!isRoot()) {
        offset = isLeft() ? -DataStructure.minsepx / 2 : +DataStructure.minsepx / 2;
      }
      result.left = this;
      result.right = this;
    } else { // This is not a leaf; at least one subtree is non-empty.
      /*
       * If one subtree is empty, it is not necessary to make a new
       * thread. A proper offset must be set.
       */
      if (getLeft() == null) {
        getRight().offset = DataStructure.minsepx / 2;
        result.left = fromRightSubtree.left;
        result.right = fromRightSubtree.right;
        return result;
      }

      if (getRight() == null) {
        getLeft().offset = -DataStructure.minsepx / 2;
        result.left = fromLeftSubtree.left;
        result.right = fromLeftSubtree.right;
        return result;
      }

      // Calculate offsets for the left and the right son.
      int loffset = 0; // offset of this node from the right contour of
      // the left subtree.
      int roffset = 0; // offset of this node from the left contour of the
      // right subtree.
      BSTNode L = getLeft();
      BSTNode R = getRight();
      /*
       * First, left.offset is 0 and only right.offset accumulates. The
       * offsets are corrected afterwards (this way is easier to
       * generalize to m-ary trees). Note that offsets can be negative.
       */
      getLeft().offset = 0;
      getRight().offset = 0;

      // traverse the right contour of the left subtree and the left
      // counour of the right subtree
      while ((L != null) && (R != null)) {
        /*
         * left.offset + loffset is the horizontal distance from L to
         * this node. Similarly, right.offset + roffset is the
         * horizontal distance from R to this node.
         */
        int distance = (loffset + DataStructure.minsepx - roffset);
        if (distance > 0) {
          getRight().offset += distance;
          roffset += distance;
        }
        /*
         * When passes through thread there will be for sure incorrect
         * offset! So Elevator calculate this new offset. In algorithm
         * TR published by Reingold this value is already calculated.
         */
        boolean LwasThread = L.thread, RwasThread = R.thread;
        L = (L.right != null) ? L.right : L.left;
        if (L != null) {
          loffset += L.offset;
        }
        R = (R.left != null) ? R.left : R.right;
        if (R != null) {
          roffset += R.offset;
        }

        BSTNode Elevator = null;
        if (LwasThread) {
          LwasThread = false;
          loffset = 0;
          Elevator = L;
          while (Elevator != this) {
            loffset += Elevator.offset;
            Elevator = Elevator.getParent();
          }
        }
        if (RwasThread) {
          roffset = 0;
          Elevator = R;
          while (Elevator != this) {
            roffset += Elevator.offset;
            Elevator = Elevator.getParent();
          }
        }
      }

      /*
       * Now, distances should be 0 for left and some value for right.. So
       * lets change it
       */

      getRight().offset /= 2;
      getLeft().offset = -getRight().offset;

      /*
       * General switch of making a new thread: we want to make a thread
       * iff one pair of extremes is deeper than others. We assume that
       * threads from subtrees are set properly.
       */

      if ((R != null) && (L == null)) { // the right subtree is deeper
        // than the left subtree
        fromLeftSubtree.left.thread = true;
        fromLeftSubtree.left.right = R;
        result.left = fromRightSubtree.left;
        result.right = fromRightSubtree.right;
      } else if ((L != null) && (R == null)) { // the left subtree is
        // deeper than the right
        // subtree
        fromRightSubtree.right.thread = true;
        fromRightSubtree.right.left = L;
        result.left = fromLeftSubtree.left;
        result.right = fromLeftSubtree.right;
      } else if ((L == null) && (R == null)) { // both subtrees have the
        // same height
        result.left = fromLeftSubtree.left;
        result.right = fromRightSubtree.right;
      }
    }
    return result;
  }