这个还少了个/吧
没有贴代码!无法知道你是什么原因导致地死循环
视频一开始就提及了关于是否可以纳入已选边集合的条件:判断现有边是否已经形成闭环,如果是则舍弃。
醉了,我怎么直接看的kruskal
这是克鲁斯卡尔算法的原理啊
在邻接矩阵里取出所有边后找出最小边
最小边对应的点不在集合中则添加进去
一个在的话则把另一个添加到该点集合中
两个都在同一个点集合中,只能抛弃这条边,为什么呢?因为会形成回环。例如:有一个点集合为{A,B,C},要找的边为AC,对应两个点都在,再选AC这条边的话A-B,B-C,A-C就形成回环,所以在程序里continue跳过
两个点在不同的点集合中,说明这两个点集合代表的边可以通过当前这条边连接起来,对应程序里的处理就是拼接两个vector
这样大家没法判断你出的是什么错呀朋友,这句代码本身没有错的。
段错误一般都是内存问题导致的。 你要检查下首先是不是内存不足,或者说你程序有没有存在内存泄漏。
111
检测一下的类名有没有写正确?
想明白了。应该以“这一层”和“下一层”的说法来说好理解一些,毕竟以“上一层”来说,是以正在查找的和preVec里的节点有连接的节点所构成的一层节点为参照点,然而这一层节点是不一定有的。
按道理讲,创建动态分配的数组时是不可以初始化的,只能在后续将其所有元素逐一设置为零。
所以,在构造函数中创建完矩阵数组后,是需要给数组全部元素赋值为零的。否则就是随机数。
有个便捷函数是:memset(m_pMatrix, 0, m_iCapacity *m_iCapacity * sizeof(int));。教程里面也有的。
你的意思是在for (int i = 0; i < m_iCapacity; i++)前用 m_pNodeArray[temp].m_bIsVisited =
true
;吗?这样效果是一样的,当把点放进去时就已经用到了,等下加下一个的时候才设置为已访问有点说不过去
这个图
想通了,递归调用实际上是一个嵌套循环,它需要一层一层的从内将每一个for循环执行完再跳出当前循环,直到跳到第一个for循环,并继续执行下去。这个时候nodeIndex=0,i=2,再在第一行寻找下一个点即D
顶顶顶
m_pEdge[edgeCount] = edgeVec[edgeIndex];
edgeCount++;
不是nodeIndex
箭头是指针方式,点是索引方式。这里m_pNodeArray[m_iNodeCount].m_cData=...是为数组赋值
广度优先遍历是一层一层的遍历,同层节点之间的输出顺序与矩阵的排列有关,也就是和一开始节点的输入顺序有关,但是同层节点的输出顺序并不是广度优先搜索的重点。
当然要是非按照固定的一种顺序,在输入节点的代码上写个排序就行了。
这是创建的对象指针,对象的周期结束后会自动释放内存
引用是为了获取这个引用参数,而不是作为形参使用。
比如在其他面向对象语言中,需要一个数值,就用return value返回,
C++支持获取引用的参数,这样可以不用为了获取某种类型的值而改变方法返回参数类型
标记啊,标记哪些点被访问过,这样就遇到被访问的点会跳过,就能保证最后搜索了所有的点
//将当前点置为被访问
m_pNodeArray[nodeIndex].m_bIsVisited = true;
这里应该是把nextnodeindex放进去 函数是nodevc.back(nextnodeindex) 你手误了 那样是放不进去的 这样的话 下一次还从A找 所以就错了
我学的Java还在看
看边的数量的话也是可以的,因为不形成闭环,N-1 条边是一定与N个点相连接的。
这个等式表明两个结点位于同一集合里。这能够得到这两个结点可以通过其他结点相连的结论,所以如果A,B再直接相连便会形成闭环
void CMap::kruskalTree()
{
int value = 0;
int edgeCount = 0;
vector<vector<int>> nodeSets;
//之前一直显示vector subscript out of range,这是因为后面出现对vector直接取vec[]的语句,这是不对的
//因为vector没有分配空间,我在这里分配空间后就可以了。
nodeSets.resize(m_iCapacity*m_iCapacity);
vector<Edge>edgeVec;
for (int i = 0; i < m_iCapacity; i++)
{
for (int k = i+1; k < m_iCapacity; k++)
{
getValueFromMatrix(i, k, value);
if (value != 0)
{
Edge edge(i,k, value);
edgeVec.push_back(edge);
}
}
}
//1.找出算法结束条件
while (edgeCount < m_iCapacity -1)
{
//2从边集合中找出最小边
int minEdgeIndex = getMinEdge(edgeVec);
edgeVec[minEdgeIndex].m_bSelected = true;
//3找出连接最小边的点
int nodeAIndex = edgeVec[minEdgeIndex].m_iNodeIndexA;
int nodeBIndex = edgeVec[minEdgeIndex].m_iNodeIndexB;
//4找出点所在的点的集合
bool nodeAIsInSet = false;
bool nodeBIsInSet = false;
int nodeAInSetLabel = -1;
int nodeBInSetLabel = -1;
for (int i = 0; i < (int)nodeSets.size(); i++)
{
nodeAIsInSet = IsInset(nodeSets[i], nodeAIndex);
if (nodeAIsInSet)//点在指定的集合中
{
nodeAInSetLabel = i;//A点所在的点集合的索引
}
}
for (int i = 0; i < (int)nodeSets.size(); i++)
{
nodeBIsInSet = IsInset(nodeSets[i], nodeBIndex);
if (nodeBIsInSet)//点在指定的集合中
{
nodeBInSetLabel = i;//A点所在的点集合的索引
}
}
//5根据点所在的集合的不同做出不同的处理
if (nodeAInSetLabel == -1 && nodeBInSetLabel == -1)
{
vector<int>vec;
vec.push_back(nodeAIndex);
vec.push_back(nodeBIndex);
nodeSets.push_back(vec);
}
else
if (nodeAInSetLabel == -1 && nodeBInSetLabel != -1)//A不在任何集合中
{
nodeSets[nodeBIndex].push_back(nodeAIndex);
}
else
if (nodeAInSetLabel != -1 && nodeBInSetLabel == -1)
{
nodeSets[nodeAIndex].push_back(nodeBIndex);
}
else
if (nodeAInSetLabel != -1 && nodeBInSetLabel != -1 && nodeAInSetLabel != nodeBInSetLabel)
{
mergeNodeSet(nodeSets[nodeAIndex], nodeSets[nodeBIndex]);//把B合并到A当中,B销毁
for (int k = nodeBInSetLabel; k < (int)nodeSets.size()-1; k++)
{
nodeSets[k] = nodeSets[k + 1];
}
}
else
if (nodeAInSetLabel != -1 && nodeBInSetLabel != -1 && nodeAInSetLabel == nodeBInSetLabel)
{
continue;
}
m_pEdge[edgeCount] = edgeVec[minEdgeIndex];//保存边
edgeCount++;
cout << edgeVec[minEdgeIndex].m_iNodeIndexA << "-------------" << edgeVec[minEdgeIndex].m_iNodeIndexB << " ";
cout << edgeVec[minEdgeIndex].m_iWeightValue << endl;
}
}
https://github.com/silenceccm/Data-structure-graph
主对角线的元素是顶点到自己的 自己与自己是没有连线的 上面的两个代码就是对应于无向图所说的 因为无向图隐含的就是每个顶点都有两条弧 所以就是对称矩阵 只要有连线的都要进行赋权值。