克鲁斯卡尔算法得最小生成树
在写kruskal算法时,输入6个节点,9条边,但是输入第一个边之后程序输出直接跑飞了
代码如下,感觉不像是CreatVDN()函数出现的问题,但是输入却在输入边的权值的时候跑飞了,请问有没有指点
你程序实在写得太烂的(不要介意),我忍不住帮你改了一下,有些地方用面向对象写会更舒服,你没用那就没改了
介于你使用了C++的一些特性,那许多地方可以优化
std::swap
直接交换结构体变量struct AMGraph
直接定义,不需要使用typedef
const
变量代替魔数和宏定义需要注意几个地方
kruskal
函数的AMGraph G
当参数会导致这个结构体全部拷贝一遍,即无缘无故浪费了内存,所以用const AMGraph &G
替代EDGE Edge[99*50];
,会导致程序混乱,即需要缩小变量作用域main
里的AMGraph G
,使用new
动态开辟在堆上int parent[G.vexnum];
这种写法sort
就和std::sort
撞车了,可能会带来不必要的麻烦sort
将打印分离出去,kruskal
函数也可以拆我懒得处理了你只要一点一点看我写的程序和你的比较,探究我为什么这么写(当然我写的不一定全是对的),就一定有收获
总得来说你写代码的能力有点弱(缺乏debug的能力),需要多多练习,C语言语法掌握得还算OK,但C++基本只会使用std::cin
和std::cout
,如果数据结构和算法能放一放那就先放一放,多去写写Online Judge练习一下debug能力,比如编程题 - PAT (Basic Level) Practice,如果不想学习C++,那么尽量把程序写成纯C的,比如用scanf
和printf
替代
有什么问题都可以在网站问我,我很乐意解答
#include<iostream>
const int MAX_WEIGHT = 32767;
const int NUM = 100;
//邻接矩阵来表示图
struct AMGraph {
int vexnum, arcnum;
int arcs[NUM][NUM];
char vexs[NUM];
};
//定义边
struct EDGE {
union {
int lowcost;
int length;
};
char begin, end;
};
//找出顶点在顶点数组的位置,如果没这个顶点,返回-1
int LocateVex(const AMGraph &G, char v)
{
for (int i = 0; i < G.vexnum; i++)
if (G.vexs[i] == v) return i;
return -1;
}
//寻找根节点,输入是parent数组和要寻找其根节点的元素序号
//输出是根节点的序号
int Find(int parent[], int L)
{
while (parent[L] > -1)
L = parent[L];
return L;
}
//冒泡法对边从小到大排序
void BubbleSort(EDGE Edge[], int length)
{
for (int i = 0; i < length - 1; i++)
for (int j = 0; j < length - 1 - i; j++)
if (Edge[j].length > Edge[j + 1].length)
std::swap(Edge[j], Edge[j + 1]);
}
void Print(EDGE Edge[], const AMGraph& G, const char * text)
{
std::cout << '\n' << text << " is:\n";
for (int i = 0; i < G.arcnum; i++)
std::cout << Edge[i].begin << "<-->" << Edge[i].end << ": " << Edge[i].length << '\n';
}
//为无向图赋值,同时Edge数组初始化
void CreateVDN(AMGraph& G,EDGE Edge[])
{
std::cout << "input the number of vexnum and arcnum separate with space key\n";
std::cin >> G.vexnum >> G.arcnum;
std::cout << "\ninput name of vertex\n";
for (int i = 0; i < G.vexnum; i++){
std::cout << "input No." << i + 1 << " vertex: ";
std::cin >> G.vexs[i];
}
for (int i = 0; i < G.vexnum; i++)
for (int j = 0; j < G.vexnum; j++)
G.arcs[i][j]=i == j?0:MAX_WEIGHT;
std::cout << "\ninput the weight of arc[weight vex1 vex2]:\n";
for (int k = 0; k < G.arcnum;){
EDGE in;
std::cout << "input the No." << k + 1 << " arc: ";
std::cin >> in.length >> in.begin >> in.end;
int i = LocateVex(G, in.begin),j = LocateVex(G, in.end);
if (i == -1 || j == -1){
std::cout << "error data, retry!\n";
}else{
G.arcs[i][j] = G.arcs[i][j] = in.length;
Edge[k++]=in;
}
}
}
//kruskal算法
//1.根据G的邻接矩阵初始化edge数组
//2.对edge数组进行排序
//3.创建parnet数组,根据edge数组对parent数组进行处理,并在处理时输出最小生成树的边
void Kruskal(const AMGraph &G,EDGE Edge[])
{
Print(Edge, G, "the Edge[]");
BubbleSort(Edge, G.arcnum);
Print(Edge, G, "after sorting the Edge[]");
int* parent = new int[G.vexnum];
for (int i = 0; i < G.vexnum;i++)
parent[i] = -1;
std::cout << "\nmini tree :\n";
//两个停止循环条件:要么循环完了,还没找到足够的边生成最小生成树,要么没循环完就找齐了边来生成最小生成树
for (int num = 0, i = 0; i < G.arcnum && num < G.vexnum - 1; i++){
int vex1 = Find(parent, LocateVex(G, Edge[i].begin));
int vex2 = Find(parent, LocateVex(G, Edge[i].end));
if (vex1 != vex2){ //如果是不同的树,就合并且生成一条边
parent[vex2] = vex1;
std::cout << Edge[i].begin << "<-->" << Edge[i].end << '\n';
num++;
}
}
delete[] parent;
}
int main()
{
EDGE *E = new EDGE[99 * 50];
AMGraph *G = new(AMGraph);
CreateVDN(*G,E);
Kruskal(*G,E);
delete G;
delete[] E;
return 0;
}