Exemplo n.º 1
0
static void
print_node (avl_key_printer_fun_type key_printer,
        avl_node * node,
        link_node * link)
{
  char buffer[256];
  unsigned int width;
  width = key_printer (buffer, node->key);

  if (node->right) {
      link_node here;
      here.parent = link;
      here.direction = 1;
      here.width = width + 11;
    print_node (key_printer, node->right, &here);
  }
  print_connectors (link);
  fprintf (stdout, "+-[%c %s %03d]",
       balance_chars[AVL_GET_BALANCE(node)+1],
       buffer,
       (int)AVL_GET_RANK(node));
  if (node->left || node->right) {
    fprintf (stdout, "-|\n");
  } else {
    fprintf (stdout, "\n");
  }
  if (node->left) {
      link_node here;
      here.parent = link;
      here.direction = -1;
      here.width = width + 11;
      print_node (key_printer, node->left, &here);
  } 
}  
Exemplo n.º 2
0
int
avl_get_by_index (avl_tree * tree,
           unsigned long index,
           void ** value_address)
{
  avl_node * p = tree->root->right;
  unsigned long m = index + 1;
  while (1) {
    if (!p) {
      return -1;
    }
    if (m < AVL_GET_RANK(p)) {
      p = p->left;
    } else if (m > AVL_GET_RANK(p)) {
      m = m - AVL_GET_RANK(p);
      p = p->right;
    } else {
      *value_address = p->key;
      return 0;
    }
  }
}
Exemplo n.º 3
0
static 
avl_node *
avl_get_index_by_key (avl_tree * tree,
                      void * key,
                      unsigned long * index)
{
  avl_node * x = tree->root->right;
  unsigned long m;

  if (!x) {
    return NULL;
  }
  m = AVL_GET_RANK (x);

  while (1) {
    int compare_result = tree->compare_fun (tree->compare_arg, key, x->key);
    if (compare_result < 0) {
      if (x->left) {
        m = m - AVL_GET_RANK(x);
        x = x->left;
        m = m + AVL_GET_RANK(x);
      } else {
        *index = m - 2;
        return NULL;
      }
    } else if (compare_result > 0) {
      if (x->right) {
        x = x->right;
        m = m + AVL_GET_RANK(x);
      } else {
        *index = m - 1;
        return NULL;
      }
    } else {
      *index = m - 1;
      return x;
    }
  }
}
Exemplo n.º 4
0
int
avl_iterate_index_range (avl_tree * tree,
             avl_iter_index_fun_type iter_fun,
             unsigned long low,
             unsigned long high,
             void * iter_arg)
{
  unsigned long m;
  unsigned long num_left;
  avl_node * node;

  if (high > tree->length) {
    return -1;
  }
  num_left = (high - low);
  /* find the <high-1>th node */
  m = high;
  node = tree->root->right;
  while (1) {
    if (m < AVL_GET_RANK (node)) {
      node = node->left;
    } else if (m > AVL_GET_RANK (node)) {
      m = m - AVL_GET_RANK (node);
      node = node->right;
    } else {
      break;
    }
  }
  /* call <iter_fun> on <node>, <get_pred(node)>, ... */
  while (num_left) {
    num_left = num_left - 1;
    if (iter_fun (num_left, node->key, iter_arg) != 0) {
      return -1;
    }
    node = avl_get_prev (node);
  }
  return 0;
}
Exemplo n.º 5
0
static long
avl_verify_rank (avl_node * node)
{
  if (!node) {
    return 0;
  } else {
    unsigned long num_left=0, num_right=0;
    if (node->left) {
      num_left = avl_verify_rank (node->left);
    }
    if (node->right) {
      num_right = avl_verify_rank (node->right);
    }
    if (AVL_GET_RANK (node) != num_left + 1) {
      fprintf (stderr, "invalid rank at node %ld\n", (long) node->key);
      exit (1);
    }
    return (num_left + num_right + 1);
  }
}
Exemplo n.º 6
0
int avl_delete(avl_tree *tree, void *key, avl_free_key_fun_type free_key_fun)
{
  avl_node *x, *y, *p, *q, *r, *top, *x_child;
  int shortened_side, shorter;
  
  x = tree->root->right;
  if (!x) {
    return -1;
  }
  while (1) {
    int compare_result = tree->compare_fun (tree->compare_arg, key, x->key);
    if (compare_result < 0) {
      /* move left
       * We will be deleting from the left, adjust this node's
       * rank accordingly
       */
      AVL_SET_RANK (x, (AVL_GET_RANK(x) - 1));
      if (x->left) {
    x = x->left;
      } else {
    /* Oops! now we have to undo the rank changes
     * all the way up the tree
     */
    AVL_SET_RANK(x, (AVL_GET_RANK (x) + 1));
    while (x != tree->root->right) {
      if (x->parent->left == x) {
        AVL_SET_RANK(x->parent, (AVL_GET_RANK (x->parent) + 1));
      }
      x = x->parent;
    }
    return -1;        /* key not in tree */
      }
    } else if (compare_result > 0) {
      /* move right */
      if (x->right) {
    x = x->right;
      } else {
    AVL_SET_RANK(x, (AVL_GET_RANK (x) + 1));
    while (x != tree->root->right) {
      if (x->parent->left == x) {
        AVL_SET_RANK(x->parent, (AVL_GET_RANK (x->parent) + 1));
      }
      x = x->parent;
    }
    return -1;        /* key not in tree */
      }
    } else {
      break;
    }
  }

  if (x->left && x->right) {
    void * temp_key;

    /* The complicated case.
     * reduce this to the simple case where we are deleting
     * a node with at most one child.
     */
    
    /* find the immediate predecessor <y> */
    y = x->left;
    while (y->right) {
      y = y->right;
    }
    /* swap <x> with <y> */
    temp_key = x->key;
    x->key = y->key;
    y->key = temp_key;
    /* we know <x>'s left subtree lost a node because that's
     * where we took it from
     */
    AVL_SET_RANK (x, (AVL_GET_RANK (x) - 1));
    x = y;
  }
  /* now <x> has at most one child
   * scoot this child into the place of <x>
   */
  if (x->left) {
    x_child = x->left;
    x_child->parent = x->parent;
  } else if (x->right) {
    x_child = x->right;
    x_child->parent = x->parent;
  } else {
    x_child = NULL;
  }

  /* now tell <x>'s parent that a grandchild became a child */
  if (x == x->parent->left) {
    x->parent->left = x_child;
    shortened_side = -1;
  } else {
    x->parent->right = x_child;
    shortened_side = +1;
  }

  /*
   * the height of the subtree <x>
   * has now been shortened.  climb back up
   * the tree, rotating when necessary to adjust
   * for the change.
   */
  shorter = 1;
  p = x->parent;
  
  /* return the key and node to storage */
  if (free_key_fun)
      free_key_fun (x->key);
#ifdef HAVE_AVL_NODE_LOCK
  thread_rwlock_destroy (&x->rwlock);
#endif
  free (x);

  while (shorter && p->parent) {
    
    /* case 1: height unchanged */
    if (AVL_GET_BALANCE(p) == 0) {
      if (shortened_side == -1) {
    /* we removed a left child, the tree is now heavier
     * on the right
     */
    AVL_SET_BALANCE (p, +1);
      } else {
    /* we removed a right child, the tree is now heavier
     * on the left
     */
    AVL_SET_BALANCE (p, -1);
      }
      shorter = 0;
      
    } else if (AVL_GET_BALANCE (p) == shortened_side) {
      /* case 2: taller subtree shortened, height reduced */
      AVL_SET_BALANCE (p, 0);
    } else {
      /* case 3: shorter subtree shortened */
      top = p->parent;
      /* set <q> to the taller of the two subtrees of <p> */
      if (shortened_side == 1) {
    q = p->left;
      } else {
    q = p->right;
      }
      if (AVL_GET_BALANCE (q) == 0) {
    /* case 3a: height unchanged */
    if (shortened_side == -1) {
      /* single rotate left */
      q->parent = p->parent;
      p->right = q->left;
      if (q->left) {
        q->left->parent = p;
      }
      q->left = p;
      p->parent = q;
      AVL_SET_RANK (q, (AVL_GET_RANK (q) + AVL_GET_RANK (p)));
    } else {
      /* single rotate right */
      q->parent = p->parent;
      p->left = q->right;
      if (q->right) {
        q->right->parent = p;
      }
      q->right = p;
      p->parent = q;
      AVL_SET_RANK (p, (AVL_GET_RANK (p) - AVL_GET_RANK (q)));
    }
    shorter = 0;
    AVL_SET_BALANCE (q, shortened_side);
    AVL_SET_BALANCE (p, (- shortened_side));
      } else if (AVL_GET_BALANCE (q) == AVL_GET_BALANCE (p)) {
    /* case 3b: height reduced */
    if (shortened_side == -1) {
      /* single rotate left */
      q->parent = p->parent;
      p->right = q->left;
      if (q->left) {
        q->left->parent = p;
      }
      q->left = p;
      p->parent = q;
      AVL_SET_RANK (q, (AVL_GET_RANK (q) + AVL_GET_RANK (p)));
    } else {
      /* single rotate right */
      q->parent = p->parent;
      p->left = q->right;
      if (q->right) {
        q->right->parent = p;
      }
      q->right = p;
      p->parent = q;
      AVL_SET_RANK (p, (AVL_GET_RANK (p) - AVL_GET_RANK (q)));
    }
    shorter = 1;
    AVL_SET_BALANCE (q, 0);
    AVL_SET_BALANCE (p, 0);
      } else {
    /* case 3c: height reduced, balance factors opposite */
    if (shortened_side == 1) {
      /* double rotate right */
      /* first, a left rotation around q */
      r = q->right;
      r->parent = p->parent;
      q->right = r->left;
      if (r->left) {
        r->left->parent = q;
      }
      r->left = q;
      q->parent = r;
      /* now, a right rotation around p */
      p->left = r->right;
      if (r->right) {
        r->right->parent = p;
      }
      r->right = p;
      p->parent = r;
      AVL_SET_RANK (r, (AVL_GET_RANK (r) + AVL_GET_RANK (q)));
      AVL_SET_RANK (p, (AVL_GET_RANK (p) - AVL_GET_RANK (r)));
    } else {
      /* double rotate left */
      /* first, a right rotation around q */
      r = q->left;
      r->parent = p->parent;
      q->left = r->right;
      if (r->right) {
        r->right->parent = q;
      }
      r->right = q;
      q->parent = r;
      /* now a left rotation around p */
      p->right = r->left;
      if (r->left) {
        r->left->parent = p;
      }
      r->left = p;
      p->parent = r;
      AVL_SET_RANK (q, (AVL_GET_RANK (q) - AVL_GET_RANK (r)));
      AVL_SET_RANK (r, (AVL_GET_RANK (r) + AVL_GET_RANK (p)));        
    }
    if (AVL_GET_BALANCE (r) == shortened_side) {
      AVL_SET_BALANCE (q, (- shortened_side));
      AVL_SET_BALANCE (p, 0);
    } else if (AVL_GET_BALANCE (r) == (- shortened_side)) {
      AVL_SET_BALANCE (q, 0);
      AVL_SET_BALANCE (p, shortened_side);
    } else {
      AVL_SET_BALANCE (q, 0);
      AVL_SET_BALANCE (p, 0);
    }
    AVL_SET_BALANCE (r, 0);
    q = r;
      }
      /* a rotation has caused <q> (or <r> in case 3c) to become
       * the root.  let <p>'s former parent know this.
       */
      if (top->left == p) {
    top->left = q;
      } else {
    top->right = q;
      }
      /* end case 3 */
      p = q;
    }
    x = p;
    p = x->parent;
    /* shortened_side tells us which side we came up from */
    if (x == p->left) {
      shortened_side = -1;
    } else {
      shortened_side = +1;
    }
  } /* end while(shorter) */
  /* when we're all done, we're one shorter */
  tree->length = tree->length - 1;
  return (0);
}
Exemplo n.º 7
0
int
avl_insert (avl_tree * ob,
           void * key)
{
  if (!(ob->root->right)) {
    avl_node * node = avl_node_new (key, ob->root);
    if (!node) {
      return -1;
    } else {
      ob->root->right = node;
      ob->length = ob->length + 1;
      return 0;
    }
  } else { /* not self.right == None */
    avl_node *t, *p, *s, *q, *r;
    int a;

    t = ob->root;
    s = p = t->right;

    while (1) {
      if (ob->compare_fun (ob->compare_arg, key, p->key) < 1) {
    /* move left */
    AVL_SET_RANK (p, (AVL_GET_RANK (p) + 1));
    q = p->left;
    if (!q) {
      /* insert */
      avl_node * q_node = avl_node_new (key, p);
      if (!q_node) {
        return (-1);
      } else {
        q = q_node;
        p->left = q;
        break;
      }
    } else if (AVL_GET_BALANCE(q)) {
      t = p;
      s = q;
    }
    p = q;
      } else {
    /* move right */
    q = p->right;
    if (!q) {
      /* insert */
      avl_node * q_node = avl_node_new (key, p);
      if (!q_node) {
        return -1;
      } else {
        q = q_node;
        p->right = q;
        break;
      }
    } else if (AVL_GET_BALANCE(q)) {
      t = p;
      s = q;
    }
    p = q;
      }
    }
    
    ob->length = ob->length + 1;
    
    /* adjust balance factors */
    if (ob->compare_fun (ob->compare_arg, key, s->key) < 1) {
      r = p = s->left;
    } else {
      r = p = s->right;
    }
    while (p != q) {
      if (ob->compare_fun (ob->compare_arg, key, p->key) < 1) {
    AVL_SET_BALANCE (p, -1);
    p = p->left;
      } else {
    AVL_SET_BALANCE (p, +1);
    p = p->right;
      }
    }
    
    /* balancing act */
    
    if (ob->compare_fun (ob->compare_arg, key, s->key) < 1) {
      a = -1;
    } else {
      a = +1;
    }
    
    if (AVL_GET_BALANCE (s) == 0) {
      AVL_SET_BALANCE (s, a);
      ob->height = ob->height + 1;
      return 0;
    } else if (AVL_GET_BALANCE (s) == -a) {
      AVL_SET_BALANCE (s, 0);
      return 0;
    } else if (AVL_GET_BALANCE(s) == a) {
      if (AVL_GET_BALANCE (r) == a) {
    /* single rotation */
    p = r;
    if (a == -1) {
      s->left = r->right;
      if (r->right) {
        r->right->parent = s;
      }
      r->right = s;
      s->parent = r;
      AVL_SET_RANK (s, (AVL_GET_RANK (s) - AVL_GET_RANK (r)));
    } else {
      s->right = r->left;
      if (r->left) {
        r->left->parent = s;
      }
      r->left = s;
      s->parent = r;
      AVL_SET_RANK (r, (AVL_GET_RANK (r) + AVL_GET_RANK (s)));
    }
    AVL_SET_BALANCE (s, 0);
    AVL_SET_BALANCE (r, 0);
      } else if (AVL_GET_BALANCE (r) == -a) {
    /* double rotation */
    if (a == -1) {
      p = r->right;
      r->right = p->left;
      if (p->left) {
        p->left->parent = r;
      }
      p->left = r;
      r->parent = p;
      s->left = p->right;
      if (p->right) {
        p->right->parent = s;
      }
      p->right = s;
      s->parent = p;
      AVL_SET_RANK (p, (AVL_GET_RANK (p) + AVL_GET_RANK (r)));
      AVL_SET_RANK (s, (AVL_GET_RANK (s) - AVL_GET_RANK (p)));
    } else {
      p = r->left;
      r->left = p->right;
      if (p->right) {
        p->right->parent = r;
      }
      p->right = r;
      r->parent = p;
      s->right = p->left;
      if (p->left) {
        p->left->parent = s;
      }
      p->left = s;
      s->parent = p;
      AVL_SET_RANK (r, (AVL_GET_RANK (r) - AVL_GET_RANK (p)));
      AVL_SET_RANK (p, (AVL_GET_RANK (p) + AVL_GET_RANK (s)));
    }
    if (AVL_GET_BALANCE (p) == a) {
      AVL_SET_BALANCE (s, -a);
      AVL_SET_BALANCE (r, 0);
    } else if (AVL_GET_BALANCE (p) == -a) {
      AVL_SET_BALANCE (s, 0);
      AVL_SET_BALANCE (r, a);
    } else {
      AVL_SET_BALANCE (s, 0);
      AVL_SET_BALANCE (r, 0);
    }
    AVL_SET_BALANCE (p, 0);
      }
      /* finishing touch */
      if (s == t->right) {
    t->right = p;
      } else {
    t->left = p;
      }
      p->parent = t;
    }
  }
  return 0;
}