bec666 2019-09-14 17:21 采纳率: 88%
浏览 310
已采纳

(*D)[v][w]为何要加上*,不加*程序可以运行但是会出错这是为什么?

图片说明

#include "stdio.h"    
#include "stdlib.h"   
#include "io.h"  
#include "math.h"  
#include "time.h"

#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0
#define MAXEDGE 20
#define MAXVEX 20
#define INFINITY 65535

typedef int Status; /* Status是函数的类型,其值是函数结果状态代码,如OK等 */

typedef struct
{
    int vexs[MAXVEX];
    int arc[MAXVEX][MAXVEX];
    int numVertexes, numEdges;
}MGraph;

typedef int Patharc[MAXVEX][MAXVEX];
typedef int ShortPathTable[MAXVEX][MAXVEX];

/* 构件图 */
void CreateMGraph(MGraph *G)
{
    int i, j;

    /* printf("请输入边数和顶点数:"); */
    G->numEdges=16;
    G->numVertexes=9;

    for (i = 0; i < G->numVertexes; i++)/* 初始化图 */
    {
        G->vexs[i]=i;
    }

    for (i = 0; i < G->numVertexes; i++)/* 初始化图 */
    {
        for ( j = 0; j < G->numVertexes; j++)
        {
            if (i==j)
                G->arc[i][j]=0;
            else
                G->arc[i][j] = G->arc[j][i] = INFINITY;
        }
    }

    G->arc[0][1]=1;
    G->arc[0][2]=5; 
    G->arc[1][2]=3; 
    G->arc[1][3]=7; 
    G->arc[1][4]=5; 

    G->arc[2][4]=1; 
    G->arc[2][5]=7; 
    G->arc[3][4]=2; 
    G->arc[3][6]=3; 
    G->arc[4][5]=3;

    G->arc[4][6]=6;
    G->arc[4][7]=9; 
    G->arc[5][7]=5; 
    G->arc[6][7]=2; 
    G->arc[6][8]=7;

    G->arc[7][8]=4;


    for(i = 0; i < G->numVertexes; i++)
    {
        for(j = i; j < G->numVertexes; j++)
        {
            G->arc[j][i] =G->arc[i][j];
        }
    }

}

/* Floyd算法,求网图G中各顶点v到其余顶点w的最短路径P[v][w]及带权长度D[v][w]。 */    
void ShortestPath_Floyd(MGraph G, Patharc *P, ShortPathTable *D)
{    
    int v,w,k;    
    for(v=0; v<G.numVertexes; ++v) /* 初始化D与P */  
    {        
        for(w=0; w<G.numVertexes; ++w)  
        {
            (*D)[v][w]=G.arc[v][w]; /* D[v][w]值即为对应点间的权值 */
            (*P)[v][w]=w;               /* 初始化P */
        }
    }
    for(k=0; k<G.numVertexes; ++k)   
    {
        for(v=0; v<G.numVertexes; ++v)  
        {        
            for(w=0; w<G.numVertexes; ++w)    
            {
                if ((*D)[v][w]>(*D)[v][k]+(*D)[k][w])
                {/* 如果经过下标为k顶点路径比原两点间路径更短 */
                    (*D)[v][w]=(*D)[v][k]+(*D)[k][w];/* 将当前两点间权值设为更小的一个 */
                    (*P)[v][w]=(*P)[v][k];/* 路径设置为经过下标为k的顶点 */
                }
            }
        }
    }
}

int main(void)
{    
    int v,w,k;  
    MGraph G;    

    Patharc P;    
    ShortPathTable D; /* 求某点到其余各点的最短路径 */   

    CreateMGraph(&G);

    ShortestPath_Floyd(G,&P,&D);  

    printf("各顶点间最短路径如下:\n");  
    for(v=0; v<G.numVertexes; ++v)   
    {        
        for(w=v+1; w<G.numVertexes; w++)  
        {
            printf("v%d-v%d weight: %d ",v,w,D[v][w]);
            k=P[v][w];              /* 获得第一个路径顶点下标 */
            printf(" path: %d",v);  /* 打印源点 */
            while(k!=w)             /* 如果路径顶点下标不是终点 */
            {
                printf(" -> %d",k); /* 打印路径顶点 */

                k=P[k][w];          /* 获得下一个路径顶点下标 */
            }
            printf(" -> %d\n",w);   /* 打印终点 */
        }
        printf("\n");
    }

    printf("最短路径D\n");
    for(v=0; v<G.numVertexes; ++v)  
    {        
        for(w=0; w<G.numVertexes; ++w)    
        {
            printf("%d\t",D[v][w]);
        }
        printf("\n");
    }
    printf("最短路径P\n");
    for(v=0; v<G.numVertexes; ++v)  
    {        
        for(w=0; w<G.numVertexes; ++w)    
        {
            printf("%d ",P[v][w]);
        }
        printf("\n");
    }

    return 0;
}
  • 写回答

2条回答

  • 无形有道 2019-09-14 18:19
    关注

    关于(*D)[v][w]和(D)[v][w]的含义和区别,以及引发异常的原因解读

    // 解读你的部分代码
    #define MAXVEX 20
    typedef int ShortPathTable[MAXVEX][MAXVEX];
    void ShortestPath_Floyd(MGraph G, Patharc *P, ShortPathTable *D)
    {
        /* 
         * 此处 D 的原型表达式为: int (*)[20][20]
         *
         * 1)说明 D 是一个指针(三维数组指针),指向一个整型的二维数组。该二维
         * 数组的长度是20*20=400,即D的步长是400
         * 
         * 2)而 *D 则是一个整型的二维数组,或者称 *D 是一个指向非常量的常量指
         * 针,或者被称为行指针,步长为20
         */
    
         int v,w;
    
        /*
         * 此处 (*D)[v][w] 表示二维数组第 v 行第 w 列元素的值。用指针表达式
         * 为: (*D)[v][w] = *((*D)[v]+w) = *(*((*D)+v)+w)  【地址偏移量=v*20+w】
         */
         (*D)[v][w]=...;
    
        /*
         * 此处 (D)[v][w] 表示三维数组指针 D 的下标运算,指向第 v 行(每行步长
         * 为400)第 w 列(每列步长20)的整型一维数组(形参为 int [20])。指针地址表达式
         * 为: (D)[v][w] = *(D[v])+w = **(D+v)+w 【地址偏移量=v*400+w*20】
         *
         * PS: (D)[v][w] = D[v][w] = &(D[v][w][0])
         * 
         * 【异常】注意指针表达式中的v、w在下标运算中与形参(int [_v][_w])行列下标是错位的,实际对应的是整型的
         * 三维数组(int [v][w][0])下标顺序。很明显只要v>0时,该行代码就会发生指针越界引发异常(行下标越界)
         */
        (D)[v][w]=...;
    
        // PPS:
        /*
         * 此处 *D[v][w] 表示一维数组第w个元素的值。用指针表达式
         * 为: *(*(D[v])+w) = *(**(D+v)+w) 【地址偏移量=v*400+w*20+0】
         *
         * PPPS: *D[v][w] = *(D[v][w]) = D[v][w][0]
         */
        *D[v][w]=...;
    }
    
    

    如果要使用 (D)[v][w] 作为实参计算是可以的哈,只需要改变函数形参即可,代码如下:

    /**
      * 新变量类型ShortPathTable实质也是一个二维数组,而使用二维数组作为函数参数,函
      * 数调用时传递的是一个指针,不会发生构造拷贝。因此函数内的值修改,其实是在原地
      * 址进行修改,函数返回后当然会保留修改后的值。
      */
    void ShortestPath_Floyd(MGraph G, Patharc P, ShortPathTable D)
    {
        int v,w,k;
    
        // 此处 (D)[v][w] 表示整型二维数组的第 v 行第 w 列元素的值(表达式是正确的)
        (D)[v][w]=(D)[v][k]+(D)[k][w];
    }
    
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

问题事件

  • 已采纳回答 11月8日

悬赏问题

  • ¥15 求学软件的前人们指明方向🥺
  • ¥50 如何增强飞上天的树莓派的热点信号强度,以使得笔记本可以在地面实现远程桌面连接
  • ¥15 MCNP里如何定义多个源?
  • ¥20 双层网络上信息-疾病传播
  • ¥50 paddlepaddle pinn
  • ¥20 idea运行测试代码报错问题
  • ¥15 网络监控:网络故障告警通知
  • ¥15 django项目运行报编码错误
  • ¥15 STM32驱动继电器
  • ¥15 Windows server update services