·
#include __FILE__

你程序实在写得太烂的(不要介意),我忍不住帮你改了一下,有些地方用面向对象写会更舒服,你没用那就没改了

介于你使用了C++的一些特性,那许多地方可以优化

  • std::swap直接交换结构体变量
  • struct AMGraph直接定义,不需要使用typedef
  • const变量代替魔数和宏定义

需要注意几个地方

  • 函数参数拷贝问题,比如kruskal函数的AMGraph G当参数会导致这个结构体全部拷贝一遍,即无缘无故浪费了内存,所以用const AMGraph &G替代
  • 全局变量尽量少用,比如EDGE Edge[99*50];,会导致程序混乱,即需要缩小变量作用域
  • 大变量不要放在栈上,比如main里的AMGraph G,使用new动态开辟在堆上
  • 区分C和C++的不同点,比如C++不支持int parent[G.vexnum];这种写法
  • 不要打开std命名空间,比如你的程序的sort就和std::sort撞车了,可能会带来不必要的麻烦
  • 拆分函数的功能,比如sort将打印分离出去,kruskal函数也可以拆我懒得处理了
  • ...

你只要一点一点看我写的程序和你的比较,探究我为什么这么写(当然我写的不一定全是对的),就一定有收获

总得来说你写代码的能力有点弱(缺乏debug的能力),需要多多练习,C语言语法掌握得还算OK,但C++基本只会使用std::cinstd::cout,如果数据结构和算法能放一放那就先放一放,多去写写Online Judge练习一下debug能力,比如编程题 - PAT (Basic Level) Practice,如果不想学习C++,那么尽量把程序写成纯C的,比如用scanfprintf替代

有什么问题都可以在网站问我,我很乐意解答

#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;
}
Replies
2

谢谢你的建议,真的很感动写了这么多建议,无以言表

C++确实用的不多,不太熟练,您提的问题我觉得都是很对的,我好好对比一下,谢谢