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

📄 mw_matching0.t

📁 A Library of Efficient Data Types and Algorithms,封装了常用的ADT及其相关算法的软件包
💻 T
📖 第 1 页 / 共 5 页
字号:
  f->children += 1;

  // recursively split f
  if (f->children > b) return split_node(f);
  else return f;
}



void conc_pq_tree::add_leaves(conc_pq_node *p, int leaves) {
  // traverses the path from p up to the root and sets
  // for each node cur on that path:
  // cur.leaves += leaves

  conc_pq_node* cur = p;

  while (cur) {
    cur->leaves += leaves;
    cur = cur->parent;
  }
}



conc_pq_node* conc_pq_tree::conc(conc_pq_node* r1, conc_pq_node* r2) {
  // concatenates the two trees rooted at r1 and r2 and 
  // returns the root of the concatenated trees.
  // minptr and list of leaves are NOT maintained here

  if (r1 == nil) return r2;
  if (r2 == nil) return r1;

  int h1 = r1->height;
  int h2 = r2->height;

  conc_pq_node *cur, *f;

  if (h1 >= h2) {
    // seek rightmost node cur in tree rooted at r1 
    // with height h2 and let f be the father of cur
    cur = r1;
    while (cur->height != h2) cur = cur->child->left;
    f = cur->parent;

    // create new root f with key cur->key in case h1 == h2
    if (f == nil) {      
      GenPtr new_key = cur->key;
      copy_key(new_key);
      f = new_conc_pq_node(new_key, nil);
      f->child = cur;
      f->height = cur->height + 1;	
      f->leaves = cur->leaves;
      f->children = 1;
      cur->parent = f;
    }

    // INVARIANT: f is the parent of cur
    f->child->left = r2;
    r2->right = f->child;
    r2->left  = cur;
    cur->right = r2;
    r2->parent = f;
    
    add_leaves(f, r2->leaves);
    f->children += 1;
    
    if (cmp(f->key, r2->key) > 0)
      decrease_prio(f, r2->key);

    if (f->children > b) f = split_node(f);

    return (f->height > r1->height ? f : r1);
  }
  else { 
    // seek leftmost node cur in tree rooted at r2 
    // with height h1 and let f be the father of cur
    cur = r2;
    // next line mod. 12/01, was before: 
    // while (cur->height != h1) cur = cur->child->left;
    while (cur->height != h1) cur = cur->child;
    f = cur->parent;
    
    // INVARIANT: f is the parent of cur
    r1->left = f->child->left;
    r1->right  = cur;
    r1->parent = f;
    f->child->left->right = r1;
    f->child = r1;
    cur->left = r1;

    add_leaves(f, r1->leaves);
    f->children += 1;

    if (cmp(f->key, r1->key) > 0)
      decrease_prio(f, r1->key);

    if (f->children > b) f = split_node(f);

    return (f->height > r2->height ? f : r2);
  }
}



void conc_pq_tree::conc(conc_pq_tree &pq, int dir) {

  if (a != pq.a || b != pq.b) 
    error_handler(1, "void conc_pq_tree::conc(...): incompatible tree types");
  if (&pq == this) 
    error_handler(1, "void conc_pq_tree::conc(...): argument is identical with object"); 

  conc_pq_tree *T1 = (dir == leda::after ? this : &pq );
  conc_pq_tree *T2 = (dir == leda::after ? &pq  : this);

  // set root
  root = conc(T1->root, T2->root);
  root->tree = this;

  // determine new minptr
  if (T1->minptr == nil)
    minptr = T2->minptr;
  else if (T2->minptr == nil)
    minptr = T1->minptr;
  else {
    conc_pq_node* aux = T2->minptr;
    // CAREFUL: minptr might overwrite T2->minptr in the
    // next step, but using aux. variable is save
    minptr = T1->minptr;
    if (cmp(minptr->key, aux->key) > 0)
      minptr = aux;
  }

  // concatenate leave lists (with special cases
  // T1 or T2 empty)

  if (T1->tail_leaf == nil)
    T1->head_leaf = T2->head_leaf;
  else if (T2->tail_leaf == nil)
    T2->tail_leaf = T1->tail_leaf;
  else {
    T1->tail_leaf->succ = T2->head_leaf;
    T2->head_leaf->pred = T1->tail_leaf;
  }

  head_leaf = T1->head_leaf;
  tail_leaf = T2->tail_leaf;

  // destroy object different form *this
  if (T1 != this) {
    T1->head_leaf = T1->tail_leaf = nil;
    T1->root = T1->minptr = nil;
  }
  if (T2 != this) {
    T2->head_leaf = T2->tail_leaf = nil;
    T2->root = T2->minptr = nil;
  }
}



void conc_pq_tree::delete_node(conc_pq_node *p) {
  // deletes the node p
  
  clear_key(p->key);
  clear_inf(p->inf);  

  // GSchange
  // std_memory.deallocate_bytes(p, sizeof(conc_pq_node));
  delete p;
}


void conc_pq_tree::print_tree(conc_pq_node *cur, int blancs) const { 

  if (cur == 0) { 
    for(int j = 1; j <= blancs; j++) 
      cout << " ";
    cout << "NIL" << endl;
    return;
  }  
  if (cur->height == 0) { 
    for(int j = 1; j <= blancs; j++) 
      cout << " ";
    if (cmp(cur->key, infinity) == 0) 
      cout << "infty";
    else 
      print_key(cur->key); 
    cout << endl;
  }
  else {         
    conc_pq_node *it = cur->child;

    print_tree(it, blancs + 10);
    it = it->right;
    while (it != cur->child) {
      print_tree(it, blancs + 10);
      it = it->right;
    }
    for(int j = 1; j <= blancs; j++) 
      cout << " ";
    if (cmp(cur->key, infinity) == 0) 
      cout << "infty";
    else 
      print_key(cur->key); 
    cout << endl;
  }
}


void conc_pq_tree::split_at_item(conc_pq_node *p, conc_pq_tree &pq1, conc_pq_tree &pq2) {
  // splits *this at p into pq1 and pq2. pq1 contains thereafter all elements
  // of *this that preceede p (inclusive).
  // NOTICE: relevant for the split operation is the linear precedence relation
  // on the leaves and NOT the key of the elements  
  // case p == nil:         pq1 gets empty and pq2 equals *this
  // case p == last_item(): pq2 gets empty and pq1 equals *this

  if (root == nil) 
    error_handler(1, "void conc_pq_tree::split(...): pq is empty.");
  if (&pq1 == &pq2)
    error_handler(1, "void conc_pq_tree::split(...): identical arguments.");
  if (a != pq1.a || a != pq2.a || b != pq1.b || b != pq2.b) 
    error_handler(1, "void conc_pq_tree::split(...): incompatible priority queues."); 
  
  if (&pq1 != this) pq1.clear();
  if (&pq2 != this) pq2.clear();

  if (p == nil || p == last_item()) {
    // make either pq1 or pq2 a copy of *this
    conc_pq_tree *pq = (p == nil ? &pq2 : &pq1);

    // make pq equal to *this
    pq->head_leaf = head_leaf;
    pq->tail_leaf = tail_leaf;
    pq->root = root;
    // mod. 05/01
    pq->root->tree = pq;

    pq->minptr = minptr;
    
    // destroy *this
    if (pq != this) {
      head_leaf = tail_leaf = nil;
      root = minptr = nil;
    }
    return;
  }

  // store pointers to roots of left/right forest in array
  conc_pq_node **left_trees  = new conc_pq_node*[root->leaves];  
  conc_pq_node **right_trees = new conc_pq_node*[root->leaves]; 

  int left_cnt  = 0;  
  int right_cnt = 0;

  conc_pq_node *cur = p, *f, *l, *r;
  conc_pq_node *l_stop, *r_stop;

  while (cur->parent) {
    f = cur->parent;
    l = cur->left;  l_stop = f->child->left; 
    r = cur->right; r_stop = f->child;
     
    // take cur to the left forest, when cur == p (leaf) 
    if (p == cur) left_trees[left_cnt++] = cur;
    
    // collect trees to the left of cur
    while (l != l_stop) {
      left_trees[left_cnt++] = l;
      l = l->left;
    }

    // collect trees to the right of cur
    while (r != r_stop) {
      right_trees[right_cnt++] = r;
      r = r->right;
    }

    if (cur != p) delete_node(cur);
    cur = f;    
  }

  // delete root
  if (cur != p) delete_node(cur);
  
  // destroy *this
  root = nil;

  // concatenate all trees from the left forest
  // -- mod. 12/09/00: for (int i = left_cnt-1 ; i >= 0; i--) 
  int i;
  for (i = 0; i < left_cnt; i++) {
    conc_pq_node *cur = left_trees[i];
    cur->parent = nil;
    cur->left = cur->right = cur;
    // -- mod. 12/09/00: pq1.root = conc(pq1.root, cur);
    pq1.root = conc(cur, pq1.root);
  }

  // concatenate all trees from the right forest
  for (i = 0 ; i < right_cnt; i++) {
    conc_pq_node *cur = right_trees[i];
    cur->parent = nil;
    cur->left = cur->right = cur;
    pq2.root = conc(pq2.root, cur);
  }

  // determine new min: determine the min of the smaller group.
  // if this is equal to the current minptr (hard luck) the 
  // min of the larger group must be determined as well; otherwise,
  // we're done

  conc_pq_node *aux = minptr;
  
  conc_pq_tree *small_pq = (pq1.root->leaves > pq2.root->leaves ? &pq2 : &pq1);
  conc_pq_tree *large_pq = (pq1.root->leaves > pq2.root->leaves ? &pq1 : &pq2);
  
  small_pq->minptr = locate_min(small_pq->root);

  // mod. 13/01
  // CAREFULL: aux might point to an element different from the minptr of small_pq,
  // _although_ the priority of aux->key and minptr->key are equal. 
  // Eg:  this = (pq1 = 2 1 3 4 | pq2 = 7 8 2 0 0)    (pq1 large, pq2 small)
  //                                            ^aux
  // locate_min in small pq (pq2) yields:     ^
  // Hence, next line does not work
  // -- if (small_pq->minptr == aux) 
  if (cmp(small_pq->minptr->key, aux->key) == 0)
    large_pq->minptr = locate_min(large_pq->root);
  else
    large_pq->minptr = aux;

  // split leaf list
  pq1.head_leaf = head_leaf;
  pq2.tail_leaf = tail_leaf;
  pq1.tail_leaf = p;
  pq2.head_leaf = p->succ;
  pq1.tail_leaf->succ = nil;
  pq2.head_leaf->pred = nil;

  // adjust the tree pointers of the root nodes
  pq1.root->tree = &pq1;
  pq2.root->tree = &pq2;

  // destroy *this
  if ((&pq1 != this) && (&pq2 != this)) {
    minptr    = nil; 
    head_leaf = tail_leaf = nil;
  }

  delete[] left_trees;
  delete[] right_trees;
}




conc_pq_node* conc_pq_tree::locate_min(conc_pq_node *p) const {
  // determines the minimal leaf in tree rooted at p

#define _LOCATE_MIN_MACRO(ktype)\
ktype cur_key, it_key;\
while(cur->child) {\
  it = cur->child;\
  cur_key = LEDA_ACCESS(ktype, cur->key);\
  it_key  = LEDA_ACCESS(ktype, it->key);\
  while (it_key != cur_key) {\
    it = it->right;\
    it_key = LEDA_ACCESS(ktype, it->key);\
  }\
  cur = it;\
}

  conc_pq_node *cur = p, *it = nil;

  switch( key_type_id() ) {

  case CHAR_TYPE_ID:   { _LOCATE_MIN_MACRO(char);   } break;
  case INT_TYPE_ID:    { _LOCATE_MIN_MACRO(int);    } break;
  case LONG_TYPE_ID:   { _LOCATE_MIN_MACRO(long);   } break;
  case FLOAT_TYPE_ID:  { _LOCATE_MIN_MACRO(float);  } break;
  case DOUBLE_TYPE_ID: { _LOCATE_MIN_MACRO(double); } break;

  default: {
    while (cur->child) {
      it = cur->child;
      while (cmp(it->key, cur->key) != 0)
	it = it->right;
      cur = it;
    }
  } 
  break;
  }

  return cur;
}



void conc_pq_tree::decrease_prio(conc_pq_node *p, GenPtr k) {
  // starts at p and follows the path to the root of p.
  // at each node: if current key is larger than k
  // replace with k, and exit otherwise.

  conc_pq_node *cur = p;
  
  while (cur && (cmp(cur->key, k) > 0)) {
    copy_key(k);
    cur->key = k;
    cur = cur->parent;
  }         
}



conc_pq_node* conc_pq_tree::increase_prio(conc_pq_node *p, GenPtr k) {
  // starts at p and follows the path to the root of p.
  // at each node: if current key is not the min. of all children
  // replace, otherwise exit.
  // the function returns a conc_pq_node* to the node having minimal 
  // key that has been inspected during the search

#define _INCREASE_PRIO_MACRO(ktype) \
ktype old_key; \
ktype cur_key = LEDA_ACCESS(ktype, cur->key); \
ktype min_key = LEDA_ACCESS(ktype, k); \
while (cur && (cur_key != min_key)) { \
  old_key = cur_key; \
  cur->key = leda_cast(min_key); \
  if (cur->parent && (LEDA_ACCESS(ktype, cur->parent->key) == old_key)) { \
    cur_stop = cur; \
    cur = cur->right; \
    while(cur != cur_stop) { \
      cur_key = LEDA_ACCESS(ktype, cur->key); \
      if (min_key > cur_key) { min = cur; min_key = cur_key; } \
      cur = cur->right; \
    } \
    cur = cur->parent; \
  } \
  if (cur) cur_key = LEDA_ACCESS(ktype, cur->key); \
}

  conc_pq_node *cur = p, *cur_stop;
  conc_pq_node *min = cur;

  switch( key_type_id() ) {

  case CHAR_TYPE_ID:   { _INCREASE_PRIO_MACRO(char);   } break;
  case INT_TYPE_ID:    { _INCREASE_PRIO_MACRO(int);    } break;
  case LONG_TYPE_ID:   { _INCREASE_PRIO_MACRO(long);   } break;
  case FLOAT_TYPE_ID:  { _INCREASE_PRIO_MACRO(float);  } break;
  case DOUBLE_TYPE_ID: { _INCREASE_PRIO_MACRO(double); } break;

  default: {
    GenPtr old_key;
    GenPtr min_key = k;

    while (cur && (cmp(cur->key, min_key) != 0)) {
      old_key = cur->key;
      copy_key(min_key);
      cur->key = min_key;      
      if (cur->parent && (cmp(cur->parent->key, old_key) == 0)) {
	cur_stop = cur;
	cur = cur->right;	
	while(cur != cur_stop) {
	  if (cmp(min_key, cur->key) > 0) { 
	    min = cur; 
	    min_key = cur->key; 
	  }
	  cur = cur->right;
	}
        cur = cur->parent;
      }      
    }
  }
  break;
  }

  return min;

}


void conc_pq_tree::del_item(conc_pq_node *p) {
  // we do not really delete an item, but instead set the
  // key to infinity

⌨️ 快捷键说明

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