这是我根据 Cormen 实现的不相交集(算法简介 - 第 2 版第 21 章)。
删除对象(“~DisjointSet”析构函数)时出现问题。
这是因为“std::vector sets;”的寄存器。可能指向相同的“MetaSet*”。
#include <vector>
#include <string>
#include <iostream>
#include <sstream>
#define WEIGHTED_UNION_HEURISTIC
class DisjointSetLinkedList
{
class LinkedListSet
{
int pos;
LinkedListSet * parent;
LinkedListSet * next;
public:
LinkedListSet(int pos) :
pos(pos),
parent(this),
next(NULL)
{
}
LinkedListSet * getParent()
{
return parent;
}
void setParent(LinkedListSet * node)
{
this->parent = (LinkedListSet *)node;
}
LinkedListSet * getNext()
{
return next;
}
void setNext(LinkedListSet * node)
{
this->next = (LinkedListSet *)node;
}
int getPos()
{
return pos;
}
};
class MetaSet
{
#ifdef WEIGHTED_UNION_HEURISTIC
int size;
#endif
LinkedListSet * head;
LinkedListSet * tail;
public:
MetaSet(LinkedListSet * head_, LinkedListSet * tail_) :
#ifdef WEIGHTED_UNION_HEURISTIC
size(1),
#endif
head(head_),
tail(tail_)
{
}
#ifdef WEIGHTED_UNION_HEURISTIC
int getSize()
{
return size;
}
void setSize(int size_)
{
this->size = size_;
}
#endif
LinkedListSet * getHead()
{
return head;
}
LinkedListSet * getTail()
{
return tail;
}
void setHead(LinkedListSet * head)
{
this->head = head;
}
void setTail(LinkedListSet * tail)
{
this->tail = tail;
}
};
std::vector<MetaSet*> sets;
public:
DisjointSetLinkedList(int size)
{
make_set(size);
}
virtual ~DisjointSet()
{
for(unsigned int i = 0 ; i < sets.size() ; i++)
{
MetaSet * meta = sets[i];
Set * node = meta->getHead();
while(node!=NULL)
{
Set * temp = node;
node = node->getNext();
delete temp;
}
meta->setHead(NULL);
meta->setTail(NULL);
}
// The error occurs here
// for(unsigned int i = 0 ; i < sets.size() ; i++)
// delete sets[i];
sets.clear();
}
void union_sets(unsigned int idx_left, unsigned int idx_right)
{
if(idx_left >= sets.size() ||
idx_right >= sets.size())
return;
MetaSet * set_left = find_set(idx_left);
MetaSet * set_right = find_set(idx_right);
if(set_left == set_right)
return;
#ifdef WEIGHTED_UNION_HEURISTIC
if(set_left->getSize() <
set_right->getSize())
{
MetaSet * temp = set_left;
set_left = set_right;
set_right = temp;
}
set_left->setSize(
set_left->getSize() +
set_right->getSize()
);
#endif
set_left->getTail()->setNext(
set_right->getHead());
set_left->setTail(
set_right->getTail());
LinkedListSet * node = set_right->getHead();
while(node != NULL)
{
sets[node->getPos()] = set_left;
node->setParent(set_left->getHead());
node = node->getNext();
}
delete set_right;
}
void print_list()
{
std::cout << "| ";
for(unsigned int i = 0 ; i < sets.size() ; i++)
std::cout << sets[i]->getHead()->getPos() << " | ";
std::cout << std::endl;
}
private:
void make_set(int size)
{
for(int i = 0 ; i < size ; i++)
{
LinkedListSet * node = new LinkedListSet(i);
sets.push_back(new MetaSet(node, node));
}
}
MetaSet * find_set(int i)
{
return sets[i];
}
};
int main()
{
{
DisjointSet disjoint_set(8);
disjoint_set.print_list();
disjoint_set.union_sets(0, 7);
disjoint_set.print_list();
disjoint_set.union_sets(3, 4);
disjoint_set.print_list();
disjoint_set.union_sets(0, 3);
disjoint_set.print_list();
disjoint_set.union_sets(0, 5);
disjoint_set.print_list();
}
std::cout << "Objects deleted!";
}