C稳定的婚姻计划永远不会结束

bqf10yzr  于 2023-03-28  发布在  其他
关注(0)|答案(1)|浏览(119)

我有一个C程序,据我所知,应该按预期工作。它试图实现Gale-Shapley稳定婚姻算法。在我的程序中,你给予程序一个3x 3或4x 4矩阵的文件。当程序执行时,它会提示一个文件名,读取文件,并将结果显示为n × n矩阵。示例矩阵如下:

3
2  1  3 
2  3  1
3  2  2

2  3  1  
3  1  2 
2  3  1

结果矩阵如下所示:
还有一个4x 4矩阵示例:

4
1  2  3  4 
1  4  3  2
2  1  3  4
4  2  3  1 

4  3  1  2 
2  4  1  3
4  1  3  2
3  2  1  4

现在,我以为代码工作正常,但是函数中似乎有问题。代码如下:

#include <stdio.h>
#include <stdlib.h>

#define MAX_N 10

int n;
int pref_m[MAX_N][MAX_N], pref_w[MAX_N][MAX_N];
int match[MAX_N], engaged[MAX_N];

void stable_marriage()
{
    int i, m, w, m1;
    for (i = 0; i < n; i++)
        engaged[i] = -1; // initialize engaged[] to -1 to indicate unengaged persons
    while (1) {
        m = -1;
        for (i = 0; i < n; i++) {
            if (engaged[i] == -1) { // use -1 to indicate unengaged persons
                m = i;
                break;
            }
        }
        if (m == -1) {
            break;
        } 
        printf("Made it");
        for (i = 0; i < n && match[m] == -1; i++) { // use -1 to indicate unassigned persons
            w = pref_m[m][i];
            if (engaged[w] == -1) {
                engaged[w] = m;
                match[m] = w;
            } else {
                m1 = engaged[w];
                if (pref_w[w][m] < pref_w[w][m1]) {
                    engaged[m1] = -1; // unengage m1 before engaging m
                    engaged[w] = m;
                    match[m] = w;
                    match[m1] = -1; // unassign m1
                }
                // add tie-breaking logic here if desired
            }
        }
    }
}

int main()
{
    char filename[256];
    printf("Enter file name: ");
    scanf("%s", filename);
    FILE *file = fopen(filename, "r");
 
    fscanf(file, "%d", &n);
    printf("n = %d\n", n);
    int i, j;
    for (i = 0; i < n; i++) {
        for (j = 0; j < n; j++) {
            fscanf(file, "%d", &pref_m[i][j]);
            printf("%d ", pref_m[i][j]);
            pref_m[i][j]--;
        }
    }
    for (i = 0; i < n; i++) {
        for (j = 0; j < n; j++) {
            fscanf(file, "%d", &pref_w[i][j]);
            printf("%d ", pref_w[i][j]);
            pref_w[i][j]--;
        }
    }
    fclose(file);
    stable_marriage();
    printf("Solution:\n");
    for (i = 0; i < n; i++) {
        for (j = 0; j < n; j++) {
            if (match[i] == j) {
                printf("1 ");
            } else {
                printf("0 ");
            }
        }
        printf("\n");
    }
    return 0;
}

在第二个while循环之前的函数中似乎有一个无限循环。Made It print语句永远运行,但当我在for循环之后有print语句时,它不会到达那里。有什么帮助吗?

drnojrws

drnojrws1#

match数组从未像engaged数组那样初始化为-1。因为在print语句之后的for循环中的一个条件是检查match[m] == -1并索引到未初始化的数组会导致undefined behavior。这导致循环永远不会进入,因为其中一个and条件为false。
初始化match数组的解决方案:

for (i = 0; i < n; i++) {
        engaged[i] = -1; // initialize engaged[] to -1 to indicate unengaged persons
        match[i] = -1;
    }

此外,match[m]值在第一次迭代后立即设置为0。这会锁定循环并阻止您进入它,从而创建另一个无限循环。解决方案是使用标志来检查匹配,而不是像这样索引检查:

int found_match = 0;
        for (i = 0; i < n && !found_match; i++) {
            w = pref_m[m][i];
            if (engaged[w] == -1) {
                engaged[w] = m;
                match[m] = w;
                found_match = 1;
            } else {
                m1 = engaged[w];
                if (pref_w[w][m] < pref_w[w][m1]) {
                    engaged[m1] = -1; // unengage m1 before engaging m
                    engaged[w] = m;
                    match[m] = w;
                    match[m1] = -1; // unassign m1
                    found_match = 1;
                }
                // add tie-breaking logic here if desired
            }

相关问题