You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PageRank算法实现输出异常,排查Main/GetGraph函数问题

PageRank算法实现结果异常排查

我用以下代码实现PageRank算法,程序先将文件信息存入Graph结构,再计算PageRank值,但测试输出与正确结果不符。怀疑问题出在Main函数的数学运算逻辑,或是GetGraph函数的实现上,无法确定具体原因,希望能定位错误所在。

主函数核心代码

double d = atof(argv[1]);
double diffPR = atof(argv[2]);
int maxIterations = atoi(argv[3]);

FILE *fp = fopen("collection.txt", "r"); 
char *urlList[MAX]; 
char tempStringOne[MAX];    

for (int i = 0; fscanf(fp, "%s", tempStringOne) != EOF; i++)
{ 
    urlList[i] = malloc(strlen(tempStringOne) + 1); 
    strcpy(urlList[i], tempStringOne); 
}
fclose(fp); 

Graph urlGraph = GetGraph(); 

int numUrls = checkNumberUrls();
// 初始化每个URL的PR值为1/N
double *PR = malloc(numUrls * sizeof(double));
for (int i = 0; i < numUrls; i++) {
    PR[i] = 1.0 / numUrls;
}

while (iteration < maxIterations && diff >= diffPR) {
    // 计算新的PR值
    int t = iteration;
    // PR(u,t+1) = (1-d)/N + d * sum(PR(v,t) / outDegree(v))
    double *newPR = malloc(numUrls * sizeof(double));
    for (int i = 0; i < numUrls; i++) {
        double sum = 0;
        for (int j = 0; j < numUrls; j++) {
            if (isConnected(urlGraph, j, i)) {
                sum += PR[j] / outDegree(urlGraph, j);
            }
        }
        newPR[i] = (1 - d) / numUrls + d * sum;
    }
    // 计算差值
    diff = 0;
    for (int i = 0; i < numUrls; i++) {
        diff += fabs(newPR[i] - PR[i]);
    }
    // 更新PR值
    for (int i = 0; i < numUrls; i++) {
        PR[i] = newPR[i];
    }
    iteration++;
}

GetGraph函数实现

Graph GetGraph()
{
    FILE *fp = fopen("collection.txt", "r"); 
    char *urlList[MAX]; 
    char tempStringOne[MAX]; 
    
    for (int i = 0; fscanf(fp, "%s", tempStringOne) != EOF; i++)
    { 
        urlList[i] = malloc(strlen(tempStringOne) + 1); 
        strcpy(urlList[i], tempStringOne); 
    }
    fclose(fp);

    int numUrls = checkNumberUrls();
    Graph urlGraph = newGraph(numUrls);

    for (int i = 0; i < numUrls; i++) {
        char *url = urlList[i];
        char *filename = malloc(strlen(url) + 5);
        strcpy(filename, url);
        strcat(filename, ".txt");
        FILE *fp = fopen(filename, "r");
        char tempStringTwo[MAX];
        while (fscanf(fp, "%s", tempStringTwo) != EOF) {
            if (strcmp(tempStringTwo, "#start") == 0) {
                fscanf(fp, "%s", tempStringTwo);
                while (strcmp(tempStringTwo, "#end") != 0) {
                    for (int j = 0; j < numUrls; j++) {
                        if (strcmp(tempStringTwo, urlList[j]) == 0) {
                            Edge e = {i, j};
                            insertEdge(urlGraph, e);
                        }
                    }
                    fscanf(fp, "%s", tempStringTwo);
                }
            }
        }
        fclose(fp);
    }
    return urlGraph;
}

可能的错误点排查

  • 循环变量未初始化:主函数中iteration和diff变量未定义初始值。iteration应初始化为0,diff应初始化为一个大于diffPR的数值(比如1e9),否则第一次循环可能直接不执行,导致PR值始终是初始的1/N。
  • 死节点(出度为0)未处理:当某个节点j的出度为0时,PR[j]/outDegree(urlGraph,j)会触发除以0的错误,得到NaN,导致后续计算全部失效。PageRank规范中,这类节点的PR值应平均分配给所有节点,需要在计算sum时判断:若outDegree(urlGraph,j)为0,则添加PR[j]/numUrls而非除以0。
  • 边方向或连接判断逻辑错误:GetGraph中插入的边是i→j(当前页面i指向页面j),主函数中判断isConnected(urlGraph,j,i)是检查j→i的边是否存在,这部分逻辑是正确的(找所有指向i的节点j),但需要确认isConnected函数的实现是否确实是判断“从第一个参数到第二个参数是否有边”。
  • URL数量一致性问题:checkNumberUrls()的返回值需与collection.txt中实际的URL数量严格一致。主函数和GetGraph中都调用了该函数,若其实现有误(比如硬编码数量或读取逻辑错误),会导致Graph大小或循环范围出错。
  • 文件读取逻辑漏洞:GetGraph中读取URL对应txt文件时,若#start后直接是#end(无任何链接),或文件中存在非URL内容(在#start和#end之间),会导致错误的边插入或遗漏。需要确保只处理有效的URL链接。
  • 内存泄漏:主函数中每次循环都malloc(newPR)但未free,虽然不影响结果正确性,但会导致内存溢出,需要在更新PR后添加free(newPR)。

内容的提问来源于stack exchange,提问作者Dunkle Nacht

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 01:05:45