用邻接矩阵表示的图为什么说越界了


/*已知有向图G用邻接矩阵存储,设计算法以分别求解顶点vi的入度、出度和度。
*/
#include<iostream>
using namespace std;
#define max 1000
#define INF 65535
typedef char element;
typedef int cellType;
typedef enum{UDG,UDN,DG,DN}GraphKind;//枚举图的类型
typedef struct GraphAdjMatrix {
    element data[max ];//顶点数组,存放顶点元素的值,从0开始
    cellType AdjMatrix[max ][max ];//邻接矩阵,元素类型为cellType
    int verNum;//顶点数
    int arcNum;//弧数
    GraphKind gkind;//图的类型,0-无向图,1-无向网,2-有向图,3-有向网
}Graph;//图的类型名
bool visited[max  + 1];  //全局数组,标记顶点是否已经访问,visited[0]单元不用
void visit(Graph& G, int verID)
{        //顶点编号从1开始,数组0单元不用
    cout << G.data[verID] << "\t";
    visited[verID] = true;
}
void strLTrim(char* str);  //删除字符串左边空格
//删除字符串、字符数组左边空格
void strLTrim(char* str)
{
    int i, j;
    int n = 0;
    n = strlen(str) + 1;
    for (i = 0; i < n; i++)
    {
        if (str[i] != ' ')  //找到左起第一个非空格位置
            break;
    }
    //以第一个非空格字符为手字符移动字符串
    for (j = 0; j < n; j++)
    {
        str[j] = str[i];
        i++;
    }
}
//从数据文件创建邻接矩阵表示的图
int CreateGraphFromFile(char fileName[], Graph& G)
{
    FILE* pFile;          //定义文件指针
    char str[1000];         //存放读出一行文本的字符串
    char strTemp[10];      //判断是否注释行
    cellType eWeight;      //边的信息,常为边的权值
    GraphKind graphType;  //图类型枚举变量
    errno_t err;
    err = fopen_s(&pFile,fileName, "r");
    if (!pFile)
    {
        cout << "错误:文件打开失败。" << endl;
        return false;
    }
    while (fgets(str, 1000, pFile) != NULL)
    {
        strLTrim(str);     //删除字符串左边空格,这是一个自定义的函数
        if (str[0] == '\n')    //空行,继续读取下一行
            continue;
        strncpy_s(strTemp,sizeof(strTemp), str, 2);
        if (strstr(strTemp, "//") != NULL)  //跳过注释行
            continue;
        else                       //非注释行、非空行,跳出循环
            break;
    }
    //循环结束,str中应该已经是图的标识Graph,判断标识是否正确
    if (strstr(str, "Graph") == NULL)
    {
        cout<<"错误:打开的文件格式错误! "<<endl;
        fclose(pFile); //关闭文件
        return false;
    }
    //读取图的类型,跳过空行
    while (fgets(str, 1000, pFile) != NULL)
    {
        strLTrim(str);    //删除字符串左边空格,这是一个自定义函数
        if (str[0] == '\n')   //空行,继续读取下一行
            continue;
        strncpy_s(strTemp, sizeof(strTemp), str, 2);
        if (strstr(strTemp, "//") != NULL)  //注释行,跳过,继续读取下一行
            continue;
        else                       //非空行,也非注释行,即图的类型标识
            break;
    }
    //设置图的类型
    if (strstr(str, "UDG"))
        graphType = UDG;    //无向图
    else if (strstr(str, "UDN"))
        graphType = UDN;    //无向网
    else if (strstr(str, "DG"))
        graphType = DG;     //有向图
    else if (strstr(str, "DN"))
        graphType = DN;     //有向网
    else
    {
        cout<<"错误:读取图的类型标记失败! "<<endl;
        fclose(pFile);       //关闭文件
        return false;
    }
    //读取顶点行数据到str。跳过空行
    while (fgets(str, 1000, pFile) != NULL)
    {
        strLTrim(str);      //删除字符串左边空格,这是一个自定义函数
        if (str[0] == '\n')     //空行,继续读取下一行
            continue;
        strncpy_s(strTemp, sizeof(strTemp), str, 2);
        if (strstr(strTemp, "//") != NULL)  //注释行,跳过,继续读取下一行
            continue;
        else                       //非空行,也非注释行,即图的顶点元素行
            break;
    }

    //顶点数据放入图的顶点数组    
    char* ptr = NULL;
    char* token = strtok_s(str, " ",&ptr);
    int nNum = 0;
    while (token != NULL)
    {
        G.data[nNum] = *token;
        token = strtok_s(NULL, " ",&ptr);
        nNum++;
    }
    //图的邻接矩阵初始化
    int nRow = 0;    //矩阵行下标
    int nCol = 0;     //矩阵列下标
    if (graphType == UDG || graphType == DG)
    {
        for (nRow = 0; nRow < nNum; nRow++)
            for (nCol = 0; nCol < nNum; nCol++)
                G.AdjMatrix[nRow][nCol] = 0;
    }
    else
    {
        for (nRow = 0; nRow < nNum; nRow++)
            for (nCol = 0; nCol < nNum; nCol++)
                G.AdjMatrix[nRow][nCol] = INF;  //INF表示无穷大
    }
    //循环读取边的数据到邻接矩阵
    int edgeNum = 0;         //边的数量
    element  Nf, Ns;     //边或弧的2个相邻顶点
    while (fgets(str, 1000, pFile) != NULL)
    {
        strLTrim(str);       //删除字符串左边空格,这是一个自定义函数
        if (str[0] == '\n')      //空行,继续读取下一行
            continue;
        strncpy_s(strTemp, sizeof(strTemp), str, 2);
        if (strstr(strTemp, "//") != NULL)  //注释行,跳过,继续读取下一行
            continue;
        char* ptr = NULL;
        char* token = strtok_s(str, " ", &ptr);
        if (token == NULL)         //分割为空串,失败退出
        {
            cout<<"错误:读取图的边数据失败! "<<endl;
            fclose(pFile);         //关闭文件
            return false;
        }
        Nf = *token;               //获取边的第一个顶点
        token = strtok_s(NULL, " ",&ptr);   //读取下一个子串,即第二个顶点
        if (token == NULL)          //分割为空串,失败退出
        {
            cout << "错误:读取图的边数据失败! " << endl;
            fclose(pFile);          //关闭文件
            return false;
        }
        Ns = *token;  //获取边的第二个顶点
                 //从第一个顶点获取行号        
        for (nRow = 0; nRow < nNum; nRow++)
        {
            if (G.data[nRow] == Nf)  //从顶点列表找到第一个顶点的编号
                break;
        }
        //从第二个顶点获取列号
        for (nCol = 0; nCol < nNum; nCol++)
        {
            if (G.data[nCol] == Ns)  //从顶点列表找到第二个顶点的编号
                break;
        }
        //如果为网,读取权值
        if (graphType == UDN || graphType == DN)
        {                //读取下一个子串,即边的附加信息,常为边的权重
            token = strtok_s(NULL, " ",&ptr);
            if (token == NULL)    //分割为空串,失败退出
            {
                cout << "错误:读取图的边数据失败! " << endl;
                fclose(pFile);    //关闭文件
                return false;
            }
            eWeight = atoi(token);  //取得边的附加信息
        }
        if (graphType == UDN || graphType == DN)
            G.AdjMatrix[nRow][nCol] = eWeight;
        //如果为网,邻接矩阵中对应的边设置权值,否则置为1
        else
            G.AdjMatrix[nRow][nCol] = 1;
        edgeNum++;   //边数加1
    }
    G.verNum = nNum;           //图的顶点数
    if (graphType == UDG || graphType == UDN)
        G.arcNum = edgeNum / 2;  //无向图或网的边数等于统计的数字除2  
    else
        G.arcNum = edgeNum;
    G.gkind = graphType;         //图的类型
    fclose(pFile);               //关闭文件
    return true;
}
//求入度
void inDegree(Graph G) {
    int i = 0, j = 0, s1 = 0;
    for (i = 0; i < G.verNum; i++) {
        for (j = 0; j < G.verNum; j++) {
            if (G.AdjMatrix[j][i] == 1)
                s1++;
        }
        cout << G.data[i] << "," << s1 << endl;
    }
}
//求出度
void outDegree(Graph G) {
    int i = 0, j = 0, s2 = 0;
    for (i = 0; i < G.verNum; i++) {
        for (j = 0; j < G.verNum; j++) {
            if (G.AdjMatrix[i][j] == 1)
                s2++;
        }
        cout << G.data[i] << "," << s2 << endl;
    }
}
//求度
void  Degree(Graph G) {
    int i = 0, j = 0, s  = 0;
    for (i = 0; i < G.verNum; i++) {
        for (j = 0; j < G.verNum; j++) {
            if ((G.AdjMatrix[i][j] == 1)|| (G.AdjMatrix[j][i] == 1))
                s ++;
        }
        cout << G.data[i] << "," << s  << endl;
    }
}
int main() {
    Graph G;
    char fileName[]=" ";
    cout << "输入要打开的文件名:";
    cin >> fileName;
    CreateGraphFromFile(fileName, G);
    cout << "顶点入度为:"<<endl;
    inDegree(G);
    cout << "顶点出度为:" << endl;
    outDegree(G);
    cout << "顶点的度为:" << endl;
     Degree(G);
     return 0;
}

img

img


想问一下这是为什么,说我内存超了?

不知道你这个问题是否已经解决, 如果还没有解决的话:
  • 你可以看下这个问题的回答https://ask.csdn.net/questions/7607150
  • 我还给你找了一篇非常好的博客,你可以看看是否有帮助,链接:每次选择一个数放到最后,把数组调成有序需要多少次操作?
  • 除此之外, 这篇博客: 牛逼!一行代码居然能解决这么多曾经困扰我半天的算法题中的 老铁,要不点个赞再走可好?么么哒 部分也许能够解决你的问题, 你可以仔细阅读以下内容或者直接跳转源博客中阅读:

    1、给俺点个赞呗,可以让更多的人看到这篇文章,顺便激励下我,嘻嘻。

    2、老铁们,关注我的原创微信公众号「帅地玩编程」,专注于写算法 + 计算机基础知识(计算机网络+ 操作系统+数据库+Linux)。

    保存让你看完有所收获,不信你打我。后台回复『电子书』送你一份精选电子书大礼包,包含各类技能的优质电子书。

  • 您还可以看一下 张传波老师的软件设计是怎样炼成的?课程中的 架构设计的第一层拆解小节, 巩固相关知识点
  • 以下回答来自chatgpt:

    回答:

    首先,我们需要了解邻接矩阵的概念。邻接矩阵是用矩阵来表示图的一种方式,其中矩阵的行和列代表图中的节点,矩阵中的值表示两个节点之间是否存在边。

    那么为什么会出现越界错误呢?可能是因为矩阵的大小没有设置正确,导致访问了非矩阵范围内的内存。解决这个问题的方法是在创建邻接矩阵时,确保矩阵的大小与节点数目一致。

    以下是可能出现越界错误的示例代码:

    node_num = 10
    matrix = [[0] * node_num] * node_num
    
    # 访问矩阵中不存在的一行或一列,会出现IndexError
    matrix[node_num][0] = 1
    

    为了避免这种问题,我们可以使用numpy库来创建矩阵,并使用numpy提供的函数来操作矩阵。以下是使用numpy的示例代码:

    import numpy as np
    
    node_num = 10
    matrix = np.zeros((node_num, node_num))
    
    # 在矩阵中赋值
    matrix[0][1] = 1
    

    通过使用numpy,我们可以简化代码,并避免越界错误。


如果你已经解决了该问题, 非常希望你能够分享一下解决方案, 写成博客, 将相关链接放在评论区, 以帮助更多的人 ^-^

创建的时候,每次更新verNum的时候,可以和max校验一下,看看有没有超