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
相关产品推荐
相关产品推荐

