📄 mw_matching0.t
字号:
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 + -