⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 _pers_tree.c

📁 数据类型和算法库LEDA 数据类型和算法库LEDA
💻 C
📖 第 1 页 / 共 2 页
字号:
/*******************************************************************************
+
+  LEDA  3.0
+
+
+  _pers_tree.c
+
+
+  Copyright (c) 1992  by  Max-Planck-Institut fuer Informatik
+  Im Stadtwald, 6600 Saarbruecken, FRG     
+  All rights reserved.
+ 
*******************************************************************************/


#include <LEDA/impl/pers_tree.h>


#define LEFT 0
#define RIGHT 1
#define f_isred(p)   ((p)->f_color)
#define c_isred(p)   ((p)->c_color)
#define f_mred(p)    ((p)->f_color=1)
#define c_mred(p)    ((p)->c_color=1)
#define f_mblack(p)  ((p)->f_color=0)
#define c_mblack(p)  ((p)->c_color=0)
#define f_lchild(p)  ((p)->f_link[0])
#define c_lchild(p)  ((p)->c_link[0])
#define f_rchild(p)  ((p)->f_link[1])
#define c_rchild(p)  ((p)->c_link[1])
#define f_parent(p)  ((p)->f_link[2])
#define c_parent(p)  ((p)->c_link[2])
#define f_isleaf(p)  (f_lchild(p)==(p))
#define c_isleaf(p)  (c_lchild(p)==(p))


void pers_rb_tree::f_rbclear(F_pers_tree_node* p)
{ if (!(f_isleaf(p)))
    { f_rbclear(f_lchild(p));
      f_rbclear(f_rchild(p));
     }
  delete p;
 }

void pers_rb_tree::c_rbclear(C_pers_tree_node* p)
{ if (!(c_isleaf(p)))
    { c_rbclear(c_lchild(p));
      c_rbclear(c_rchild(p));
     }
  delete p;
}


F_pers_tree_node* pers_rb_tree::f_rbsearch(F_pers_tree_node* p, version i)
{
  F_pers_tree_node *q;
  
  q = f_rchild(p);
  while (!(f_isleaf(q)))
  {  
    if (i == q->ver_stamp || vless(i, q->ver_stamp))
      q = f_lchild(q);
    else
      q = f_rchild(q);
  }
  return(q);
}

C_pers_tree_node* pers_rb_tree::c_rbsearch(C_pers_tree_node* p, version i)
{
  C_pers_tree_node *q;
  
  q = c_rchild(p);
  while (!(c_isleaf(q)))
  {
    if (i == q->vers_stamp || vless(i, q->vers_stamp))
      q = c_lchild(q);
    else
      q = c_rchild(q);
  }
  return(q);
}

F_pers_tree_node * pers_rb_tree::f_nleaf(pers_tree_node* newvalue, version i)
{
  F_pers_tree_node* result = new F_pers_tree_node;

  f_mblack(result);
  result->ver_stamp = i;
  f_lchild(result) = f_rchild(result) = result;
  result->poin_value = newvalue;
  return(result);
}

C_pers_tree_node * pers_rb_tree::c_nleaf(int newvalue, version i)
{
  C_pers_tree_node* result = new C_pers_tree_node;

  c_mblack(result);
  result->vers_stamp = i;
  c_lchild(result) = c_rchild(result) = result;
  result->col_value = newvalue;
  return(result);
}

F_pers_tree_node * pers_rb_tree::f_nnode(F_pers_tree_node* c1, F_pers_tree_node* c2)
{
  F_pers_tree_node* result = new F_pers_tree_node;

  f_mred(result);
  if (vless(c1->ver_stamp, c2->ver_stamp))
  {
    f_lchild(result) = c1;
    c1->f_right = 0;
    f_rchild(result) = c2;
    c2->f_right = 1;
  }
  else
  {
    f_lchild(result) = c2;
    c2->f_right = 0;
    f_rchild(result) = c1;
    c1->f_right = 1;
  }
  f_parent(c1) = f_parent(c2) = result;
  result->ver_stamp = (f_lchild(result))->ver_stamp;
  result->poin_value = NULL;
  return(result);
}

C_pers_tree_node* pers_rb_tree::c_nnode(C_pers_tree_node* c1, C_pers_tree_node* c2)
{
  C_pers_tree_node* result = new C_pers_tree_node;

  c_mred(result);
  if (vless(c1->vers_stamp, c2->vers_stamp))
  {
    c_lchild(result) = c1;
    c1->c_right = 0;
    c_rchild(result) = c2;
    c2->c_right = 1;
  }
  else
  {
    c_lchild(result) = c2;
    c2->c_right = 0;
    c_rchild(result) = c1;
    c1->c_right = 1;
  }
  c_parent(c1) = c_parent(c2) = result;
  result->vers_stamp = (c_lchild(result))->vers_stamp;
  result->col_value = 0;  
  return(result);
}

void  pers_rb_tree::f_single_rot(F_pers_tree_node* top_node, int dir)
{
  F_pers_tree_node *temp, *q;

  q = top_node->f_link[1-dir];
  top_node->f_link[1-dir] = temp = q->f_link[dir];
  temp->f_right = 1 - dir;
  f_parent(temp) = top_node;
  q->f_link[dir] = top_node;
  temp = f_parent(top_node);
  f_parent(top_node) = q;
  q->f_right = top_node->f_right;
  temp->f_link[top_node->f_right] = q;
  f_parent(q) = temp;
  top_node->f_right = dir;
  return;
}

void  pers_rb_tree::c_single_rot(C_pers_tree_node* top_node, int dir)
{
  C_pers_tree_node *temp, *q;

  q = top_node->c_link[1-dir];
  top_node->c_link[1-dir] = temp = q->c_link[dir];
  temp->c_right = 1 - dir;
  c_parent(temp) = top_node;
  q->c_link[dir] = top_node;
  temp = c_parent(top_node);
  c_parent(top_node) = q;
  q->c_right = top_node->c_right;
  temp->c_link[top_node->c_right] = q;
  c_parent(q) = temp;
  top_node->c_right = dir;
  return;
}


void  pers_rb_tree::f_double_rot(F_pers_tree_node* top_node, int dir)
{
  F_pers_tree_node *q, *r, *temp;

  q = top_node->f_link[1-dir];
  r = q->f_link[dir];
  top_node->f_link[1-dir] = temp = r->f_link[dir];
  temp->f_right = 1 - dir;
  f_parent(temp) = top_node;
  q->f_link[dir] = (temp = r->f_link[1-dir]);
  temp->f_right = dir;
  f_parent(temp) = q;
  temp = f_parent(top_node);
  r->f_right = top_node->f_right;
  r->f_link[dir] = top_node;
  f_parent(top_node) = r;
  top_node->f_right = dir;
  r->f_link[1-dir] = q;
  f_parent(q) = r;
  temp->f_link[r->f_right] = r;
  f_parent(r) = temp;
  return;
}

void  pers_rb_tree::c_double_rot(C_pers_tree_node* top_node, int dir)
{
  C_pers_tree_node *q, *r, *temp;

  q = top_node->c_link[1-dir];
  r = q->c_link[dir];
  top_node->c_link[1-dir] = temp = r->c_link[dir];
  temp->c_right = 1 - dir;
  c_parent(temp) = top_node;
  q->c_link[dir] = (temp = r->c_link[1-dir]);
  temp->c_right = dir;
  c_parent(temp) = q;
  temp = c_parent(top_node);
  r->c_right = top_node->c_right;
  r->c_link[dir] = top_node;
  c_parent(top_node) = r;
  top_node->c_right = dir;
  r->c_link[1-dir] = q;
  c_parent(q) = r;
  temp->c_link[r->c_right] = r;
  c_parent(r) = temp;
  return;
}


int pers_rb_tree::f_insert(F_pers_tree_node* head, pers_tree_node* newvalue, version i)
{
  int aux_bool;
  F_pers_tree_node *p, *q, *r, *aux_node;

  if (f_rchild(head) == NULL)
  {
    p = f_nleaf(newvalue, i);
    p->f_right = 1;
    f_parent(p) = head;
    f_rchild(head) = p;
    return(0);
  }
  p = f_rbsearch(head, i);
  if (p->ver_stamp == i)
  {
    p->poin_value = newvalue;
    return(1);
  }
  q = f_nleaf(newvalue, i);
  aux_bool = p->f_right;
  aux_node = f_parent(p);
  r = f_nnode(p, q);
  f_parent(r) = aux_node;
  r->f_right = aux_bool;
  aux_node->f_link[aux_bool] = r;
  if (!f_isred(aux_node))
  {
    f_mblack(f_rchild(head));
    return(0);
  }
  q = aux_node;
  p = f_parent(q);
  while ((f_isred(f_lchild(p))) && (f_isred(f_rchild(p))))
  {
    f_mblack(f_lchild(p));
    f_mblack(f_rchild(p));
    f_mred(p);
    r = p;
    q = f_parent(r);
    if (!f_isred(q))
    {
      f_mblack(f_rchild(head));
      return(0);
    }
    p = f_parent(q);
  }
  if (q->f_right == r->f_right)
  {
    f_mred(p);
    f_mblack(q);
    f_single_rot(p, 1-r->f_right);
  }
  else
  {
    f_mblack(r);
    f_mred(p);
    f_double_rot(p, r->f_right);
  }
  f_mblack(f_rchild(head));
  return(0);
}

int pers_rb_tree::c_insert(C_pers_tree_node* head, int newvalue, version i)
{
  int aux_bool;
  C_pers_tree_node *p, *q, *r, *aux_node;

  if (c_rchild(head) == NULL)
  {
    p = c_nleaf(newvalue, i);
    p->c_right = 1;
    c_parent(p) = head;
    c_rchild(head) = p;
    return(0);
  }
  p = c_rbsearch(head, i);
  if (p->vers_stamp == i)
  {
    p->col_value = newvalue;
    return(1);
  }
  q = c_nleaf(newvalue, i);
  aux_bool = p->c_right;
  aux_node = c_parent(p);
  r = c_nnode(p, q);
  c_parent(r) = aux_node;
  r->c_right = aux_bool;
  aux_node->c_link[aux_bool] = r;
  if (!c_isred(aux_node))
  {
    c_mblack(c_rchild(head));
    return(0);
  }
  q = aux_node;
  p = c_parent(q);
  while ((c_isred(c_lchild(p))) && (c_isred(c_rchild(p))))
  {
    c_mblack(c_lchild(p));
    c_mblack(c_rchild(p));
    c_mred(p);
    r = p;
    q = c_parent(r);
    if (!c_isred(q))
    {
      c_mblack(c_rchild(head));
      return(0);
    }
    p = c_parent(q);
  }
  if (q->c_right == r->c_right)
  {
    c_mred(p);
    c_mblack(q);
    c_single_rot(p, 1-r->c_right);
  }
  else
  {
    c_mblack(r);
    c_mred(p);
    c_double_rot(p, r->c_right);
  }
  c_mblack(c_rchild(head));
  return(0);
}



/* insert the new version in the appropriate position and update the 
 * version list
 */

void pers_rb_tree::del_version(version) 
{ if (--v_list->count ==0) del_tree(); }

version pers_rb_tree::copy_version(version i) { return new_version(i); }

version pers_rb_tree::new_version(version i)
{

  version succ = v_list->vl.succ(i);
  
  ver_node p = new VER_pers_tree_node;

  if (succ != nil)
     p->ser_num = (v_list->vl[i]->ser_num + v_list->vl[succ]->ser_num) / 2.0;
  else 
     p->ser_num = v_list->vl[i]->ser_num + 1000;


  p->popul = v_list->vl[i]->popul;
  p->acc_pointer = v_list->vl[i]->acc_pointer;
  v_list->count++;
  return v_list->vl.insert(p,i);
}

/* implementation of the update step (change of left or right child)
 * for a specific persistent node and update operation 
 */
 
void pers_rb_tree::update(F_pers_tree_node* p, pers_tree_node* newvalue, version i)
{ 
  F_pers_tree_node *p1, *i1, *i2;

  version ip = v_list->vl.succ(i);

  if (f_insert(p, newvalue, i) == 1) return;

  if (ip == nil || vless(ip,p->ver_stamp)) return;

  p1 = f_rbsearch(p, i);
  if (p1->f_right)
  {
    i1 = f_lchild(f_parent(p1));
    if (f_isleaf(i1))
      goto la;
    else
      i1 = f_rchild(i1);
la: while (p1 != f_rchild(p) && p1->f_right)
      p1 = f_parent(p1);
    if (p1 == f_rchild(p))
      i2 = NULL;
    else
    {
      i2 = f_rchild(f_parent(p1));
      while (!f_isleaf(i2))
        i2 = f_lchild(i2);
    }
  }
  else
  {
    i2 = f_rchild(f_parent(p1));
    if (f_isleaf(i2))
      goto m;
    else
      i2 = f_lchild(i2);
 m: while (p1->f_right == 0)
      p1 = f_parent(p1);
    i1 = f_lchild(f_parent(p1));
    while (!f_isleaf(i1))
      i1 = f_rchild(i1);
  }
  if (i2 == NULL || vless(ip, i2->ver_stamp))
     f_insert(p, i1->poin_value, ip);
}
   

/* implementation of the update step (change of color) for a specific
 * persistent node and update operation 
 */
 
void pers_rb_tree::up_col(C_pers_tree_node* p, int newvalue, version i)
{ 
  C_pers_tree_node *p1, *i1, *i2;
  
  version ip = v_list->vl.succ(i);

  if (c_insert(p, newvalue, i) == 1) return;

  if (ip ==nil  || vless(ip,p->vers_stamp)) return;

  p1 = c_rbsearch(p, i);
  if (p1->c_right)
  {
    i1 = c_lchild(c_parent(p1));
    if (c_isleaf(i1))
      goto lb;
    else
      i1 = c_rchild(i1);
lb: while (p1 != c_rchild(p) && p1->c_right)
      p1 = c_parent(p1);
    if (p1 == c_rchild(p))
      i2 = NULL;
    else
    {
      i2 = c_rchild(c_parent(p1));
      while (!c_isleaf(i2))
        i2 = c_lchild(i2);
    }
  }
  else
  {
    i2 = c_rchild(c_parent(p1));
    if (c_isleaf(i2))
      goto ma;
    else
      i2 = c_lchild(i2);
ma: while (p1->c_right == 0)
      p1 = c_parent(p1);
    i1 = c_lchild(c_parent(p1));
    while (!c_isleaf(i1))
      i1 = c_rchild(i1);
  }
  if (i2 == NULL || vless(ip, i2->vers_stamp))
     c_insert(p, i1->col_value, ip);
}
   

/* implementation of the access step for a specific persistent node 
 * and version 
 */

pers_tree_node * pers_rb_tree::acc_step(F_pers_tree_node *head, version i)
{
  F_pers_tree_node *q, *i1;
 
  q = f_rbsearch(head, i);
  if (q->ver_stamp == i)
    return(q->poin_value);
  if (vless(q->ver_stamp, i))
    return(q->poin_value);
  if (q->f_right)
  {
     i1 = f_lchild(f_parent(q));
     if (f_isleaf(i1))
       goto t;
     else
       i1 = f_rchild(i1);
  }
  else
  {
    while (q->f_right == 0)
      q = f_parent(q);
    i1 = f_lchild(f_parent(q));
    while (!f_isleaf(i1))
      i1 = f_rchild(i1);
  }
t:return(i1->poin_value);
}
  


/* find out whether a given persistent node is red or not in a 
 * specific version 
 */

int pers_rb_tree::isred(pers_tree_node* p, version i)
{
  C_pers_tree_node *head, *q, *i1;
  
  if (isleaf(p))
    return(0);
  head = p->red;
  q = c_rbsearch(head, i);
  if (q->vers_stamp == i)
    return(q->col_value);
  if (vless(q->vers_stamp, i))
    return(q->col_value);
  if (q->c_right)
  {  
     i1 = c_lchild(c_parent(q));
     if (c_isleaf(i1))
       goto s;
     else
       i1 = c_rchild(i1);
  }
  else
  {
    while (q->c_right == 0)
      q = c_parent(q);
    i1 = c_lchild(c_parent(q));
    while (!c_isleaf(i1))
      i1 = c_rchild(i1);
  }
s:return(i1->col_value);
}

 
/* create a new leaf and initialize the fields with the appropriate values */
 
pers_tree_node* pers_rb_tree::newleaf(void* val, void* inf, pers_tree_node* pred, pers_tree_node* succ, version i)
{
  pers_tree_node *result;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -