一、基础
定义边
struct Edge{
int nextNode; // 下一条结点编号
int cost; //该边的权重
};
为每一个结点都建立一个单链表来保存与其相邻的边权值和结点的信息。使用vector对象。
vector<Edge> edge[N]
上述单链表的一些操作:
- 清空单链表
for(int i=0; i<N; i++){
edge[i].clear();
}
向单链表添加信息
Edge tmp; //准备一个Edge结构体
tmp.nextNode = 3; //下一结点编号为3
tmp.cost = 38; //该边权值为38
edge[1].push_back(tmp);//将该边加入结点 1 单链表中
- 查询某个结点的所有邻接信息(遍历vector)
for(int i=0; i<edge[2].size(); i++){//对edge[2]进行遍历,即对所有与结点2相邻的边进行遍历,edge[2].size()表示其大小
int nextNode = edge[2][i].nextNode; //读出邻接结点
int cost = edge[2][i].cost;//读出该边权值
}
- 删除结点 1 的单链表中
edge[1][i]
所对应的边信息
edge[1].erase(edge[1].begin() + i, edge[1].begin() + i + 1);//即vector.erase(vector.begin() + 第一个要删除的元素编号,vector.begin() + 最后一个要删除元素的编号 + 1
二、并查集
定义一个数组,用双亲表示法来表示各种树,(所有集合元素个数总和为N)
int Tree[N];
用Tree[i]
来表示结点i的双亲结点,若Tree[i]
为 -1 则表示该结点不存在双亲结点,即结点 i 为其所在树的根结点。
查找结点 x 所在树的根结点
- 递归
int findRoot(int x){
if (Tree[x] == -1) return x; //若当前结点为根结点则返回该结点号
else return findRoot(Tree [x]); //否则递归查找其双亲结点的根结点
}
- 非递归
int findRoot(int x){
int ret;
while(Tree[x] != -1) x = Tree[x];//若当前结点为非根结点则一直查找其双亲结点
return ret;
}
若需要在查找过程中添加路径压缩的优化
- 递归
int findRoot(int x){
if(Tree[x] == -1) return x;
else{
int tmp = findRoot(Tree[x]);
Tree[x] = tmp;//将当前结点的双亲结点设置为查找返回的根结点编号
return tmp;
}
}
- 非递归
int findRoot(int x) {
int ret;
int tmp = x;
while(Tree[x] != -1) x = Tree[x];
ret = x;
x = tmp; //再做一次从结点 x 到根结点的遍历
while(Tree[x] != -1){
int t = Tree[x];
Tree[x] = ret;
x = t;//遍历过程中将这些结点的双亲结点都设置为已经查找得到的根结点编号
}
return ret;
}