📄 collect.cxx
字号:
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;
}
PAbstractSortedList::Element * PAbstractSortedList::Info ::Predecessor(const Element * 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;
}
PAbstractSortedList::Element * PAbstractSortedList::Info::OrderSelect(Element * 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;
return node->left->subTreeSize;
}
}
return P_MAX_INDEX;
}
void PAbstractSortedList::DeleteSubTrees(Element * node, BOOL deleteObject)
{
if (node->left != &info->nil) {
DeleteSubTrees(node->left, deleteObject);
delete node->left;
node->left = &info->nil;
}
if (node->right != &info->nil) {
DeleteSubTrees(node->right, deleteObject);
delete node->right;
node->right = &info->nil;
}
if (deleteObject) {
delete node->data;
node->data = NULL;
}
}
///////////////////////////////////////////////////////////////////////////////
PObject * POrdinalKey::Clone() const
{
return new POrdinalKey(theKey);
}
PObject::Comparison POrdinalKey::Compare(const PObject & obj) const
{
PAssert(PIsDescendant(&obj, POrdinalKey), PInvalidCast);
const POrdinalKey & other = (const POrdinalKey &)obj;
if (theKey < other.theKey)
return LessThan;
if (theKey > other.theKey)
return GreaterThan;
return EqualTo;
}
PINDEX POrdinalKey::HashFunction() const
{
return PABSINDEX(theKey)%23;
}
void POrdinalKey::PrintOn(ostream & strm) const
{
strm << theKey;
}
///////////////////////////////////////////////////////////////////////////////
void PHashTable::Table::DestroyContents()
{
for (PINDEX i = 0; i < GetSize(); i++) {
Element * list = GetAt(i);
if (list != NULL) {
Element * elmt = list;
do {
Element * nextElmt = elmt->next;
if (elmt->data != NULL && reference->deleteObjects)
delete elmt->data;
if (deleteKeys)
delete elmt->key;
delete elmt;
elmt = nextElmt;
} while (elmt != list);
}
}
PAbstractArray::DestroyContents();
}
PINDEX PHashTable::Table::AppendElement(PObject * key, PObject * data)
{
lastElement = NULL;
PINDEX bucket = PAssertNULL(key)->HashFunction();
Element * list = GetAt(bucket);
Element * element = new Element;
PAssert(element != NULL, POutOfMemory);
element->key = key;
element->data = data;
if (list == NULL) {
element->next = element->prev = element;
SetAt(bucket, element);
}
else if (list == list->prev) {
list->next = list->prev = element;
element->next = element->prev = list;
}
else {
element->next = list;
element->prev = list->prev;
list->prev->next = element;
list->prev = element;
}
lastElement = element;
lastIndex = P_MAX_INDEX;
return bucket;
}
PObject * PHashTable::Table::RemoveElement(const PObject & key)
{
PObject * obj = NULL;
if (GetElementAt(key) != NULL) {
if (lastElement == lastElement->prev)
SetAt(key.HashFunction(), NULL);
else {
lastElement->prev->next = lastElement->next;
lastElement->next->prev = lastElement->prev;
SetAt(key.HashFunction(), lastElement->next);
}
obj = lastElement->data;
if (deleteKeys)
delete lastElement->key;
delete lastElement;
lastElement = NULL;
}
return obj;
}
BOOL PHashTable::Table::SetLastElementAt(PINDEX index)
{
if (index == 0 || lastElement == NULL || lastIndex == P_MAX_INDEX) {
lastIndex = 0;
lastBucket = 0;
while ((lastElement = GetAt(lastBucket)) == NULL) {
if (lastBucket >= GetSize())
return FALSE;
lastBucket++;
}
}
if (lastIndex == index)
return TRUE;
if (lastIndex < index) {
while (lastIndex != index) {
if (lastElement->next != operator[](lastBucket))
lastElement = lastElement->next;
else {
do {
if (++lastBucket >= GetSize())
return FALSE;
} while ((lastElement = operator[](lastBucket)) == NULL);
}
lastIndex++;
}
}
else {
while (lastIndex != index) {
if (lastElement != operator[](lastBucket))
lastElement = lastElement->prev;
else {
do {
if (lastBucket-- == 0)
return FALSE;
} while ((lastElement = operator[](lastBucket)) == NULL);
lastElement = lastElement->prev;
}
lastIndex--;
}
}
return TRUE;
}
PHashTable::Element * PHashTable::Table::GetElementAt(const PObject & key)
{
if (lastElement != NULL && *lastElement->key == key)
return lastElement;
Element * list = GetAt(key.HashFunction());
if (list != NULL) {
Element * element = list;
do {
if (*element->key == key) {
lastElement = element;
lastIndex = P_MAX_INDEX;
return lastElement;
}
element = element->next;
} while (element != list);
}
return NULL;
}
PINDEX PHashTable::Table::GetElementsIndex(
const PObject * obj, BOOL byValue, BOOL keys) const
{
PINDEX index = 0;
for (PINDEX i = 0; i < GetSize(); i++) {
Element * list = operator[](i);
if (list != NULL) {
Element * element = list;
do {
PObject * keydata = keys ? element->key : element->data;
if (byValue ? (*keydata == *obj) : (keydata == obj))
return index;
element = element->next;
index++;
} while (element != list);
}
}
return P_MAX_INDEX;
}
///////////////////////////////////////////////////////////////////////////////
PHashTable::PHashTable()
: hashTable(new PHashTable::Table)
{
PAssert(hashTable != NULL, POutOfMemory);
hashTable->lastElement = NULL;
}
void PHashTable::DestroyContents()
{
if (hashTable != NULL) {
hashTable->reference->deleteObjects = reference->deleteObjects;
delete hashTable;
hashTable = NULL;
}
}
void PHashTable::CopyContents(const PHashTable & hash)
{
hashTable = hash.hashTable;
}
void PHashTable::CloneContents(const PHashTable * hash)
{
PINDEX sz = PAssertNULL(hash)->GetSize();
PHashTable::Table * original = PAssertNULL(hash->hashTable);
hashTable = new PHashTable::Table(original->GetSize());
PAssert(hashTable != NULL, POutOfMemory);
hashTable->lastElement = NULL;
for (PINDEX i = 0; i < sz; i++) {
original->SetLastElementAt(i);
PObject * data = original->lastElement->data;
if (data != NULL)
data = data->Clone();
hashTable->AppendElement(original->lastElement->key->Clone(), data);
}
}
PObject::Comparison PHashTable::Compare(const PObject & obj) const
{
PAssert(PIsDescendant(&obj, PHashTable), PInvalidCast);
return reference != ((const PHashTable &)obj).reference
? GreaterThan : EqualTo;
}
BOOL PHashTable::SetSize(PINDEX)
{
return TRUE;
}
PObject & PHashTable::AbstractGetDataAt(PINDEX index) const
{
PAssert(hashTable->SetLastElementAt(index), PInvalidArrayIndex);
return *hashTable->lastElement->data;
}
const PObject & PHashTable::AbstractGetKeyAt(PINDEX index) const
{
PAssert(hashTable->SetLastElementAt(index), PInvalidArrayIndex);
return *hashTable->lastElement->key;
}
///////////////////////////////////////////////////////////////////////////////
void PAbstractSet::DestroyContents()
{
hashTable->deleteKeys = reference->deleteObjects;
PHashTable::DestroyContents();
}
void PAbstractSet::CopyContents(const PAbstractSet & )
{
}
void PAbstractSet::CloneContents(const PAbstractSet * )
{
}
PINDEX PAbstractSet::Append(PObject * obj)
{
if (AbstractContains(*obj)) {
if (reference->deleteObjects)
delete obj;
return P_MAX_INDEX;
}
reference->size++;
return hashTable->AppendElement(obj, NULL);
}
PINDEX PAbstractSet::Insert(const PObject &, PObject * obj)
{
return Append(obj);
}
PINDEX PAbstractSet::InsertAt(PINDEX, PObject * obj)
{
return Append(obj);
}
BOOL PAbstractSet::Remove(const PObject * obj)
{
if (PAssertNULL(obj) == NULL)
return FALSE;
if (hashTable->GetElementAt(*obj) == NULL)
return FALSE;
hashTable->deleteKeys = hashTable->reference->deleteObjects = reference->deleteObjects;
hashTable->RemoveElement(*obj);
reference->size--;
return TRUE;
}
PObject * PAbstractSet::RemoveAt(PINDEX index)
{
if (!hashTable->SetLastElementAt(index))
return NULL;
PObject * obj = hashTable->lastElement->key;
hashTable->deleteKeys = hashTable->reference->deleteObjects = reference->deleteObjects;
hashTable->RemoveElement(*obj);
reference->size--;
return obj;
}
PINDEX PAbstractSet::GetObjectsIndex(const PObject * obj) const
{
return hashTable->GetElementsIndex(obj, FALSE, TRUE);
}
PINDEX PAbstractSet::GetValuesIndex(const PObject & obj) const
{
return hashTable->GetElementsIndex(&obj, TRUE, TRUE);
}
PObject * PAbstractSet::GetAt(PINDEX index) const
{
return (PObject *)&AbstractGetKeyAt(index);
}
BOOL PAbstractSet::SetAt(PINDEX, PObject * obj)
{
return Append(obj);
}
///////////////////////////////////////////////////////////////////////////////
PINDEX PAbstractDictionary::Append(PObject *)
{
PAssertAlways(PUnimplementedFunction);
return 0;
}
PINDEX PAbstractDictionary::Insert(const PObject & before, PObject * obj)
{
AbstractSetAt(before, obj);
return 0;
}
PINDEX PAbstractDictionary::InsertAt(PINDEX index, PObject * obj)
{
AbstractSetAt(AbstractGetKeyAt(index), obj);
return index;
}
BOOL PAbstractDictionary::Remove(const PObject * obj)
{
PINDEX idx = GetObjectsIndex(obj);
if (idx == P_MAX_INDEX)
return FALSE;
RemoveAt(idx);
return TRUE;
}
PObject * PAbstractDictionary::RemoveAt(PINDEX index)
{
PObject & obj = AbstractGetDataAt(index);
AbstractSetAt(AbstractGetKeyAt(index), NULL);
return &obj;
}
PINDEX PAbstractDictionary::GetObjectsIndex(const PObject * obj) const
{
return hashTable->GetElementsIndex(obj, FALSE, FALSE);
}
PINDEX PAbstractDictionary::GetValuesIndex(const PObject & obj) const
{
return hashTable->GetElementsIndex(&obj, TRUE, FALSE);
}
BOOL PAbstractDictionary::SetAt(PINDEX index, PObject * val)
{
return AbstractSetAt(AbstractGetKeyAt(index), val);
}
PObject * PAbstractDictionary::GetAt(PINDEX index) const
{
PAssert(hashTable->SetLastElementAt(index), PInvalidArrayIndex);
return hashTable->lastElement->data;
}
BOOL PAbstractDictionary::SetDataAt(PINDEX index, PObject * val)
{
return AbstractSetAt(AbstractGetKeyAt(index), val);
}
BOOL PAbstractDictionary::AbstractSetAt(const PObject & key, PObject * obj)
{
if (obj == NULL) {
obj = hashTable->RemoveElement(key);
if (obj != NULL) {
if (reference->deleteObjects)
delete obj;
reference->size--;
}
}
else {
Element * element = hashTable->GetElementAt(key);
if (element == NULL) {
hashTable->AppendElement(key.Clone(), obj);
reference->size++;
}
else {
if ((reference->deleteObjects) && (hashTable->lastElement->data != obj))
delete hashTable->lastElement->data;
hashTable->lastElement->data = obj;
}
}
return TRUE;
}
PObject * PAbstractDictionary::AbstractGetAt(const PObject & key) const
{
Element * element = hashTable->GetElementAt(key);
return element != NULL ? element->data : (PObject *)NULL;
}
PObject & PAbstractDictionary::GetRefAt(const PObject & key) const
{
Element * element = hashTable->GetElementAt(key);
return *PAssertNULL(element)->data;
}
void PAbstractDictionary::PrintOn(ostream &strm) const
{
char separator = strm.fill();
if (separator == ' ')
separator = '\n';
for (PINDEX i = 0; i < GetSize(); i++) {
if (i > 0)
strm << separator;
strm << AbstractGetKeyAt(i) << '=' << AbstractGetDataAt(i);
}
if (separator == '\n')
strm << separator;
}
// End Of File ///////////////////////////////////////////////////////////////
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -