📄 ttree.cxx
字号:
//-< TTREE.CXX >-----------------------------------------------------*--------*
// POST++ Version 1.0 (c) 1998 GARRET * ? *
// (Persistent Object Storage) * /\| *
// * / \ *
// Created: 23-Jan-99 K.A. Knizhnik * / [] \ *
// Last update: 23-Jan-99 K.A. Knizhnik * GARRET *
//-------------------------------------------------------------------*--------*
// T-tree class implementation
//-------------------------------------------------------------------*--------*
#include "ttree.h"
REGISTER(dbTtree);
REGISTER(dbTtreeNode);
int dbTtree::find(dbSearchContext& sc)
{
sc.lastMatch = NULL;
sc.nMatches = 0;
if (sc.buffer != NULL) {
sc.buffer->set_size(0);
}
if (root != NULL) {
root->find(sc);
}
return sc.nMatches;
}
void dbTtree::insert(object* obj, dbRelation& relation)
{
if (root == NULL) {
root = new_in(*get_storage(), dbTtreeNode)(obj);
} else {
root->insert(root, obj, relation);
}
}
void dbTtree::remove(object* obj, dbRelation& relation)
{
int h = root->remove(root, obj, relation);
assert(h >= 0);
}
void dbTtree::purge()
{
if (root != NULL) {
delete root;
root = NULL;
}
}
bool dbTtreeNode::find(dbSearchContext& sc)
{
int l, r, m, n = nItems;
if (sc.firstKey != NULL) {
if (sc.compare(sc.firstKey, item[0]) >= sc.firstKeyInclusion) {
if (sc.compare(sc.firstKey, item[n-1]) >= sc.firstKeyInclusion) {
if (right != 0) {
return right->find(sc);
}
return true;
}
for (l = 0, r = n; l < r;) {
m = (l + r) >> 1;
if (sc.compare(sc.firstKey, item[m]) >= sc.firstKeyInclusion) {
l = m+1;
} else {
r = m;
}
}
while (r < n) {
if (sc.lastKey != NULL
&& -sc.compare(sc.lastKey, item[r]) >= sc.lastKeyInclusion)
{
return false;
}
if (sc.predicate(item[r])) {
sc.lastMatch = item[r];
if (sc.buffer != NULL) {
sc.buffer->push(item[r]);
}
if (++sc.nMatches == sc.selectionLimit) {
return false;
}
}
r += 1;
}
if (right != 0) {
return right->find(sc);
}
return true;
}
}
if (left != 0) {
if (!left->find(sc)) {
return false;
}
}
for (l = 0; l < n; l++) {
if (sc.lastKey != NULL
&& -sc.compare(sc.lastKey, item[l]) >= sc.lastKeyInclusion)
{
return false;
}
if (sc.predicate(item[l])) {
sc.lastMatch = item[l];
if (sc.buffer != NULL) {
sc.buffer->push(item[l]);
}
if (++sc.nMatches == sc.selectionLimit) {
return false;
}
}
}
if (right != 0) {
return right->find(sc);
}
return true;
}
bool dbTtreeNode::insert(dbTtreeNode* &p, object* obj, dbRelation& relation)
{
int n = nItems;
int diff = relation.compare(obj, item[0]);
if (diff <= 0) {
if ((left == NULL || diff == 0) && n != pageSize) {
for (int i = n; i > 0; i--) item[i] = item[i-1];
item[0] = obj;
nItems += 1;
return false;
}
if (left == NULL) {
left = new_in(*get_storage(), dbTtreeNode)(obj);
} else {
if (!left->insert(left, obj, relation)) {
return false;
}
}
if (balance > 0) {
balance = 0;
return false;
} else if (balance == 0) {
balance = -1;
return true;
} else {
dbTtreeNode* lp = left;
if (lp->balance < 0) { // single LL turn
left = lp->right;
lp->right = this;
balance = 0;
lp->balance = 0;
p = lp;
} else { // double LR turn
dbTtreeNode* rp = lp->right;
lp->right = rp->left;
rp->left = lp;
left = rp->right;
rp->right = this;
balance = (rp->balance < 0) ? 1 : 0;
lp->balance = (rp->balance > 0) ? -1 : 0;
rp->balance = 0;
p = rp;
}
return false;
}
}
diff = relation.compare(obj, item[n-1]);
if (diff >= 0) {
if ((right == NULL || diff == 0) && n != pageSize) {
item[n] = obj;
nItems += 1;
return false;
}
if (right == NULL) {
right = new_in(*get_storage(), dbTtreeNode)(obj);
} else {
if (!right->insert(right, obj, relation)) {
return false;
}
}
if (balance < 0) {
balance = 0;
return false;
} else if (balance == 0) {
balance = 1;
return true;
} else {
dbTtreeNode* rp = right;
if (rp->balance > 0) { // single RR turn
right = rp->left;
rp->left = this;
balance = 0;
rp->balance = 0;
p = rp;
} else { // double RL turn
dbTtreeNode* lp = rp->left;
rp->left = lp->right;
lp->right = rp;
right = lp->left;
lp->left = this;
balance = (lp->balance > 0) ? -1 : 0;
rp->balance = (lp->balance < 0) ? 1 : 0;
lp->balance = 0;
p = lp;
}
return false;
}
}
int l = 1, r = n-1;
while (l < r) {
int i = (l+r) >> 1;
diff = relation.compare(obj, item[i]);
if (diff > 0) {
l = i + 1;
} else {
r = i;
if (diff == 0) {
break;
}
}
}
// Insert before item[r]
if (n != pageSize) {
for (int i = n; i > r; i--) item[i] = item[i-1];
item[r] = obj;
nItems += 1;
return false;
} else {
object* reinsert;
if (balance >= 0) {
reinsert = item[0];
for (int i = 1; i < r; i++) item[i-1] = item[i];
item[r-1] = obj;
} else {
reinsert = item[n-1];
for (int i = n-1; i > r; i--) item[i] = item[i-1];
item[r] = obj;
}
return insert(p, reinsert, relation);
}
}
inline int dbTtreeNode::balanceLeftBranch(dbTtreeNode* &p)
{
if (balance < 0) {
balance = 0;
return 1;
} else if (balance == 0) {
balance = 1;
return 0;
} else {
dbTtreeNode* rp = right;
if (rp->balance >= 0) { // single RR turn
right = rp->left;
rp->left = this;
if (rp->balance == 0) {
balance = 1;
rp->balance = -1;
p = rp;
return 0;
} else {
balance = 0;
rp->balance = 0;
p = rp;
return 1;
}
} else { // double RL turn
dbTtreeNode* lp = rp->left;
rp->left = lp->right;
lp->right = rp;
right = lp->left;
lp->left = this;
balance = lp->balance > 0 ? -1 : 0;
rp->balance = lp->balance < 0 ? 1 : 0;
lp->balance = 0;
p = lp;
return 1;
}
}
}
inline int dbTtreeNode::balanceRightBranch(dbTtreeNode* &p)
{
if (balance > 0) {
balance = 0;
return 1;
} else if (balance == 0) {
balance = -1;
return 0;
} else {
dbTtreeNode* lp = left;
if (lp->balance <= 0) { // single LL turn
left = lp->right;
lp->right = this;
if (lp->balance == 0) {
balance = -1;
lp->balance = 1;
p = lp;
return 0;
} else {
balance = 0;
lp->balance = 0;
p = lp;
return 1;
}
} else { // double LR turn
dbTtreeNode* rp = lp->right;
lp->right = rp->left;
rp->left = lp;
left = rp->right;
rp->right = this;
balance = rp->balance < 0 ? 1 : 0;
lp->balance = rp->balance > 0 ? -1 : 0;
rp->balance = 0;
p = rp;
return 1;
}
}
}
int dbTtreeNode::remove(dbTtreeNode* &p, object* obj, dbRelation& relation)
{
int n = nItems;
int diff = relation.compare(obj, item[0]);
if (diff <= 0) {
if (left != NULL) {
int h = left->remove(left, obj, relation);
if (h > 0) {
return balanceLeftBranch(p);
} else if (h == 0) {
return 0;
}
}
assert (diff == 0);
}
diff = relation.compare(obj, item[n-1]);
if (diff <= 0) {
for (int i = 0; i < n; i++) {
if (item[i] == obj) {
if (n == 1) {
if (right == NULL) {
p = left;
left = NULL;
delete this;
return 1;
} else if (left == NULL) {
p = right;
right = NULL;
delete this;
return 1;
}
}
if (n <= minItems) {
if (left != NULL && balance <= 0) {
dbTtreeNode* lp = left;
while (lp->right != 0) {
lp = lp->right;
}
while (--i >= 0) {
item[i+1] = item[i];
}
item[0] = lp->item[lp->nItems-1];
int h = left->remove(left, item[0], relation);
if (h > 0) {
h = balanceLeftBranch(p);
}
return h;
} else if (right != NULL) {
dbTtreeNode* rp = right;
while (rp->left != 0) {
rp = rp->left;
}
while (++i < n) {
item[i-1] = item[i];
}
item[n-1] = rp->item[0];
int h = right->remove(right, item[n-1], relation);
if (h > 0) {
h = balanceRightBranch(p);
}
return h;
}
}
while (++i < n) {
item[i-1] = item[i];
}
nItems -= 1;
return 0;
}
}
}
if (right != NULL) {
int h = right->remove(right, obj, relation);
if (h > 0) {
return balanceRightBranch(p);
} else {
return h;
}
}
return -1;
}
dbTtreeNode::~dbTtreeNode()
{
delete left;
delete right;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -