📄 collect.cxx
字号:
}
while (lastIndex > index) {
lastElement = lastElement->prev;
--lastIndex;
}
return PTrue;
}
PListElement::PListElement(PObject * theData)
{
next = prev = NULL;
data = theData;
}
///////////////////////////////////////////////////////////////////////////////
PAbstractSortedList::PAbstractSortedList()
{
info = new PSortedListInfo;
PAssert(info != NULL, POutOfMemory);
}
PSortedListInfo::PSortedListInfo()
{
root = &nil;
nil.parent = nil.left = nil.right = &nil;
nil.subTreeSize = 0;
nil.colour = Element::Black;
nil.data = NULL;
}
void PAbstractSortedList::DestroyContents()
{
RemoveAll();
delete info;
info = NULL;
}
void PAbstractSortedList::CopyContents(const PAbstractSortedList & list)
{
info = list.info;
}
void PAbstractSortedList::CloneContents(const PAbstractSortedList * list)
{
PSortedListInfo * otherInfo = list->info;
info = new PSortedListInfo;
PAssert(info != NULL, POutOfMemory);
reference->size = 0;
// Have to do this in this manner rather than just doing a for() loop
// as "this" and "list" may be the same object and we just changed info in
// "this" so we need to use the info in "list" saved previously.
Element * element = otherInfo->OrderSelect(otherInfo->root, 1);
while (element != &otherInfo->nil) {
Append(element->data->Clone());
element = otherInfo->Successor(element);
}
}
PBoolean PAbstractSortedList::SetSize(PINDEX)
{
return PTrue;
}
PObject::Comparison PAbstractSortedList::Compare(const PObject & obj) const
{
PAssert(PIsDescendant(&obj, PAbstractSortedList), PInvalidCast);
Element * elmt1 = info->root;
while (elmt1->left != &info->nil)
elmt1 = elmt1->left;
Element * elmt2 = ((const PAbstractSortedList &)obj).info->root;
while (elmt2->left != &info->nil)
elmt2 = elmt2->left;
while (elmt1 != &info->nil && elmt2 != &info->nil) {
if (elmt1 == &info->nil)
return LessThan;
if (elmt2 == &info->nil)
return GreaterThan;
if (*elmt1->data < *elmt2->data)
return LessThan;
if (*elmt1->data > *elmt2->data)
return GreaterThan;
elmt1 = info->Successor(elmt1);
elmt2 = info->Successor(elmt2);
}
return EqualTo;
}
PINDEX PAbstractSortedList::Append(PObject * obj)
{
if (PAssertNULL(obj) == NULL)
return P_MAX_INDEX;
Element * z = new Element;
z->parent = z->left = z->right = &info->nil;
z->colour = Element::Black;
z->subTreeSize = 1;
z->data = obj;
Element * x = info->root;
Element * y = &info->nil;
while (x != &info->nil) {
x->subTreeSize++;
y = x;
x = *z->data < *x->data ? x->left : x->right;
}
z->parent = y;
if (y == &info->nil)
info->root = z;
else if (*z->data < *y->data)
y->left = z;
else
y->right = z;
PSortedListElement * lastElement = x = z;
PINDEX lastIndex;
x->colour = Element::Red;
while (x != info->root && x->parent->colour == Element::Red) {
if (x->parent == x->parent->parent->left) {
y = x->parent->parent->right;
if (y->colour == Element::Red) {
x->parent->colour = Element::Black;
y->colour = Element::Black;
x->parent->parent->colour = Element::Red;
x = x->parent->parent;
}
else {
if (x == x->parent->right) {
x = x->parent;
LeftRotate(x);
}
x->parent->colour = Element::Black;
x->parent->parent->colour = Element::Red;
RightRotate(x->parent->parent);
}
}
else {
y = x->parent->parent->left;
if (y->colour == Element::Red) {
x->parent->colour = Element::Black;
y->colour = Element::Black;
x->parent->parent->colour = Element::Red;
x = x->parent->parent;
}
else {
if (x == x->parent->left) {
x = x->parent;
RightRotate(x);
}
x->parent->colour = Element::Black;
x->parent->parent->colour = Element::Red;
LeftRotate(x->parent->parent);
}
}
}
info->root->colour = Element::Black;
x = lastElement;
lastIndex = x->left->subTreeSize;
while (x != info->root) {
if (x != x->parent->left)
lastIndex += x->parent->left->subTreeSize+1;
x = x->parent;
}
reference->size++;
return lastIndex;
}
PBoolean PAbstractSortedList::Remove(const PObject * obj)
{
PSortedListElement * lastElement;
if (GetObjectsIndex(obj, lastElement) == P_MAX_INDEX)
return PFalse;
RemoveElement(lastElement);
return PTrue;
}
PObject * PAbstractSortedList::RemoveAt(PINDEX index)
{
Element * node = info->OrderSelect(info->root, index+1);
if (node == &info->nil)
return NULL;
PObject * data = node->data;
RemoveElement(node);
return reference->deleteObjects ? (PObject *)NULL : data;
}
void PAbstractSortedList::RemoveAll()
{
if (info->root != &info->nil) {
DeleteSubTrees(info->root, reference->deleteObjects);
delete info->root;
info->root = &info->nil;
reference->size = 0;
}
}
PINDEX PAbstractSortedList::Insert(const PObject &, PObject * obj)
{
return Append(obj);
}
PINDEX PAbstractSortedList::InsertAt(PINDEX, PObject * obj)
{
return Append(obj);
}
PBoolean PAbstractSortedList::SetAt(PINDEX, PObject *)
{
return PFalse;
}
PObject * PAbstractSortedList::GetAt(PINDEX index) const
{
if (index >= GetSize())
return NULL;
PSortedListElement * lastElement = info->OrderSelect(info->root, index+1);
return PAssertNULL(lastElement)->data;
}
PINDEX PAbstractSortedList::GetObjectsIndex(const PObject * obj) const
{
PSortedListElement * lastElement;
return PAbstractSortedList::GetObjectsIndex(obj, lastElement);
}
PINDEX PAbstractSortedList::GetObjectsIndex(const PObject * obj, PSortedListElement * & lastElement) const
{
Element * elmt = NULL;
PINDEX pos = ValueSelect(info->root, *obj, (const Element **)&elmt);
if (pos == P_MAX_INDEX)
return P_MAX_INDEX;
if (elmt->data != obj) {
PINDEX savePos = pos;
Element * saveElmt = elmt;
while (elmt->data != obj &&
(elmt = info->Predecessor(elmt)) != &info->nil &&
*obj == *elmt->data)
pos--;
if (elmt->data != obj) {
pos = savePos;
elmt = saveElmt;
while (elmt->data != obj &&
(elmt = info->Successor(elmt)) != &info->nil &&
*obj == *elmt->data)
pos++;
if (elmt->data != obj)
return P_MAX_INDEX;
}
}
lastElement = elmt;
return pos;
}
PINDEX PAbstractSortedList::GetValuesIndex(const PObject & obj) const
{
PSortedListElement * lastElement;
PINDEX lastIndex = ValueSelect(info->root, obj, (const Element **)&lastElement);
if (lastIndex == P_MAX_INDEX)
return P_MAX_INDEX;
Element * prev;
while ((prev = info->Predecessor(lastElement)) != &info->nil &&
prev->data->Compare(obj) == EqualTo) {
lastElement = prev;
lastIndex--;
}
return lastIndex;
}
void PAbstractSortedList::RemoveElement(Element * node)
{
// Don't try an remove one of the special leaf nodes!
if (PAssertNULL(node) == &info->nil)
return;
if (node->data != NULL && reference->deleteObjects)
delete node->data;
Element * y = node->left == &info->nil || node->right == &info->nil ? node : info->Successor(node);
Element * t = y;
while (t != &info->nil) {
t->subTreeSize--;
t = t->parent;
}
Element * x = y->left != &info->nil ? y->left : y->right;
x->parent = y->parent;
if (y->parent == &info->nil)
info->root = x;
else if (y == y->parent->left)
y->parent->left = x;
else
y->parent->right = x;
if (y != node)
node->data = y->data;
if (y->colour == Element::Black) {
while (x != info->root && x->colour == Element::Black) {
if (x == x->parent->left) {
Element * w = x->parent->right;
if (w->colour == Element::Red) {
w->colour = Element::Black;
x->parent->colour = Element::Red;
LeftRotate(x->parent);
w = x->parent->right;
}
if (w->left->colour == Element::Black && w->right->colour == Element::Black) {
w->colour = Element::Red;
x = x->parent;
}
else {
if (w->right->colour == Element::Black) {
w->left->colour = Element::Black;
w->colour = Element::Red;
RightRotate(w);
w = x->parent->right;
}
w->colour = x->parent->colour;
x->parent->colour = Element::Black;
w->right->colour = Element::Black;
LeftRotate(x->parent);
x = info->root;
}
}
else {
Element * w = x->parent->left;
if (w->colour == Element::Red) {
w->colour = Element::Black;
x->parent->colour = Element::Red;
RightRotate(x->parent);
w = x->parent->left;
}
if (w->right->colour == Element::Black && w->left->colour == Element::Black) {
w->colour = Element::Red;
x = x->parent;
}
else {
if (w->left->colour == Element::Black) {
w->right->colour = Element::Black;
w->colour = Element::Red;
LeftRotate(w);
w = x->parent->left;
}
w->colour = x->parent->colour;
x->parent->colour = Element::Black;
w->left->colour = Element::Black;
RightRotate(x->parent);
x = info->root;
}
}
}
x->colour = Element::Black;
}
delete y;
reference->size--;
}
void PAbstractSortedList::LeftRotate(Element * node)
{
Element * pivot = PAssertNULL(node)->right;
node->right = pivot->left;
if (pivot->left != &info->nil)
pivot->left->parent = node;
pivot->parent = node->parent;
if (node->parent == &info->nil)
info->root = pivot;
else if (node == node->parent->left)
node->parent->left = pivot;
else
node->parent->right = pivot;
pivot->left = node;
node->parent = pivot;
pivot->subTreeSize = node->subTreeSize;
node->subTreeSize = node->left->subTreeSize + node->right->subTreeSize + 1;
}
void PAbstractSortedList::RightRotate(Element * node)
{
Element * pivot = PAssertNULL(node)->left;
node->left = pivot->right;
if (pivot->right != &info->nil)
pivot->right->parent = node;
pivot->parent = node->parent;
if (node->parent == &info->nil)
info->root = pivot;
else if (node == node->parent->right)
node->parent->right = pivot;
else
node->parent->left = pivot;
pivot->right = node;
node->parent = pivot;
pivot->subTreeSize = node->subTreeSize;
node->subTreeSize = node->left->subTreeSize + node->right->subTreeSize + 1;
}
PSortedListElement * PSortedListInfo::Successor(const PSortedListElement * node) const
{
Element * next;
if (node->right != &nil) {
next = node->right;
while (next->left != &nil)
next = next->left;
}
else {
next = node->parent;
while (next != &nil && node == next->right) {
node = next;
next = node->parent;
}
}
return next;
}
PSortedListElement * PSortedListInfo::Predecessor(const PSortedListElement * node) const
{
Element * pred;
if (node->left != &nil) {
pred = node->left;
while (pred->right != &nil)
pred = pred->right;
}
else {
pred = node->parent;
while (pred != &nil && node == pred->left) {
node = pred;
pred = node->parent;
}
}
return pred;
}
PSortedListElement * PSortedListInfo::OrderSelect(PSortedListElement * node, PINDEX index) const
{
PINDEX r = node->left->subTreeSize+1;
if (index == r)
return node;
if (index < r) {
if (node->left != &nil)
return OrderSelect(node->left, index);
}
else {
if (node->right != &nil)
return OrderSelect(node->right, index - r);
}
PAssertAlways2("PAbstractSortedList::Element", "Order select failed!");
return (Element *)&nil;
}
PINDEX PAbstractSortedList::ValueSelect(const Element * node,
const PObject & obj,
const Element ** lastElement) const
{
if (node != &info->nil) {
switch (node->data->Compare(obj)) {
case PObject::LessThan :
{
PINDEX index = ValueSelect(node->right, obj, lastElement);
if (index != P_MAX_INDEX)
return node->left->subTreeSize + index + 1;
break;
}
case PObject::GreaterThan :
return ValueSelect(node->left, obj, lastElement);
default :
*lastElement = node;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -