//从书上抄的例子,代码不是原创 不是原创 不是原创。
#include<iostream>
using namespace std;
//使用链表和整型指针实现的并查集算法
struct equivNode
{
int equivClass, //元素类标识符
size, //类的元素个数
next; //类中指向下一个元素的指针
//说实在的,这个链表节点有点让我晕。。。next居然是个整数而不是一个equivNode指针。
//这好像是一个数组模拟链表。。。你模拟就模拟呗,还非得说链表。。。大家都是成年人了,不如都坦诚一点。。
//wait!!这样写有一个很精妙的地方!!!所有类中的这个元素下一个元素的值存在next中,秒呀
};
class BingChaJi {
public:
//构造函数(初始化)
BingChaJi(int numberOfElements)
{
n = numberOfElements;
node = new equivNode[n + 1];
for (int e = 1; e <= n; e++)
{
node[e].equivClass = e;//现在是自己在自己的类里
node[e].next = 0;//链表中没有下一个节点,没有next的值就是0,所以数组的第一个元素没有用,从1开始用的。
node[e].size = 1;//现在一个类的元素个数是1个
}
}
void unite(int classA, int classB)//这样的参数命名就感觉舒服多了
{
//合并类classA和classB
//假设classA!=classB
//classA和classB是链表首元素*******重 要!********
//使classA成为较小的类(小的类加入大的类比较容易)
if (node[classA].size > node[classB].size)
{
swap(classA, classB);//这里很简单的,就是两个变量的值交换了一下,不用惊慌
}
//改变较小类的equivClass值
int k;
for (k = classA; node[k].next != 0; k = node[k].next)
node[k].equivClass = classB;
node[k].equivClass = classB;//链表的最后一个节点(漏网之鱼)
//在链表classB的首元素之后插入链表classA
node[classB].size += node[classA].size;
node[k].next = node[classB].next;//这里两行真心晕,只要记住数组下标是本元素的值,next是本类下一个元素的值就可,如果next是0就说明这个是本类中最后一个元素节点。
node[classB].next = classA;//达成了类似 b a a a a a a a b b b b b b b的效果??(a是原本的classA中的元素)
}
//相比于上面的硬核这个显得舒服多了
int find(int theElement)
{
//查找包含元素theElement的类
return node[theElement].equivClass;
}
private:
equivNode* node;//节点的数组,一个类的在一个“链表”里,不同的类在不同的“数组”元素中,应该是这么回事。
int n;//元素的个数
};
使用链表和整型指针实现的并查集算法
最新推荐文章于 2023-08-19 21:12:54 发布