C++ Gale-Shapley算法的实现

C++ Implementation of Gale-Shapley algorithm

本文关键字:实现 算法 Gale-Shapley C++      更新时间:2023-10-16

昨天我在算法课上做功课,这是Gale-Shapley算法的实现,它是一种算法,用于解决相同数量的男性和女性之间的匹配问题,他们有自己的匹配优先级。然后编码后,我发现它不能很好地运行,因为输入各不相同,但我只是想不通为什么,也许它有sth。与内存溢出有关。如果有人能指出我的错误,那将对我有很大帮助。非常感谢!这是我的教科书中的代码和伪代码:

#include <iostream>
using namespace std;
bool isOneFree(int n,bool*P)    // test if there's at least one man Free.
{
    for(int i=0;i<n;i++)
    {
        if(*(P+i)==true)    return true;
    }
    return false;
}
int* Matching(int n,int**MP,int**WP) // numbers, priority lists of males and females.
{
    bool isManFree[n],isWomanFree[n],isManProposed[n][n];   // to represent matching states.
    int match[n];   // index-value(man-woman) pair
    for(int i=0;i<n;i++)    // initialize values.
    {
        isManFree[i]=true;
        isWomanFree[i]=true;
        for(int j=0;j<n;j++){   isManProposed[i][j]=false;    }
        match[i]=-1;
    }
    while(isOneFree(n,isManFree))   // all matching completed if it returns false.
    {
        int indexM;
        for(int i=0;i<n;i++)
        {
            if(isManFree[i]==true)  { indexM=i; break; }    // we'll try matching this guy with a girl!
        }
        int indexWo;
        for(int i=0;i<n;i++)
        {
            int w=MP[indexM][i];
            if(isManProposed[indexM][w]==false)  { indexWo=w;   break;}  // current priority
        }
        isManProposed[indexM][indexWo]=true;
        if(isWomanFree[indexWo])
        {
            isManFree[indexM]=false;
            isWomanFree[indexWo]=false;
            match[indexM]=indexWo; // they're engaged!
        }
        else    // she's engaged to someone already.
        {
            int indexRival; // find the competitor's index.
            for(int i=0;i<n;i++)
            {
                if(match[i]==indexWo){ indexRival=i;    break; }
            }
            int pM,pRival;
            for(int i=0;i<n;i++)
            {
                if(WP[indexWo][i]==indexM)  pM=i;
                if(WP[indexWo][i]==indexRival)  pRival=i;
            }
            if(pM<pRival)   // the girl's decision
            {
                isManFree[indexM]=false;
                isManFree[indexRival]=true;
                isWomanFree[indexWo]=false;
                match[indexM]=indexWo;  // change the match
            }
        }
    }
    return match;
}
int main()
{
    int n;
    cin>>n;
    int**MP,**WP;
    MP=new int*[n];
    for(int i=0;i<n;i++)    // a lot of inputs
    {
        MP[i]=new int[n];
        for(int j=0;j<n;j++)
        {
            cin>>MP[i][j];
        }
    }
    WP=new int*[n];
    for(int i=0;i<n;i++)
    {
        WP[i]=new int[n];
        for(int j=0;j<n;j++)
        {
            cin>>WP[i][j];
        }
    }
    for(int i=0;i<n;i++)
    {
        for(int j=0;j<n;j++)
        {
            MP[i][j]--; // inputs are 1~n, get indexes 0~n-1
            WP[i][j]--;
        }
    }
    int*match=Matching(n,MP,WP);
    for(int i=0;i<n;i++)
    {
        cout<<*(match+i)+1<<" ";    // output: matching result
    }
    return 0;
}

伪代码:

Initially all m belongs to M and w belongs to W are free
While there is a man m who is free and hasn’t proposed to every woman
    Choose such a man m
    Let w be the highest-ranked woman in m’s preference list to whom m has not yet proposed
    If w is free then
        (m, w) become engaged
    Else w is currently engaged to m’
        If w prefers m’ to m then
            m remains free
        Else w prefers m to m’
            (m,w) become engaged
            m’becomes free
        Endif
    Endif
Endwhile
Return the set S of engaged pairs

下面是示例输入和输出:

52 1 4 5 3
4 2 1 3 5
2 5 3 4 1
1 4 3 2 5
2 4 1 5 3
5 1 2 4 3
3 2 4 1 5
2 3 4 5 1
1 5 4 3 2
4 2 5 3 1

1 3 2 5 4

快速浏览一下您的代码,我看到的一个问题是函数

int* Matching(int n,int**MP,int**WP)

返回局部变量的地址,这是一个很大的禁忌。

我会按如下方式更改代码:

int* Matching(int n,int**MP,int**WP) // numbers, priority lists of males and females.
{
    bool isManFree[n],isWomanFree[n],isManProposed[n][n];   // to represent matching states.
    int *match = new int[n];   // index-value(man-woman) pair
完成后,

请释放它:

int*match=Matching(n,MP,WP);
for(int i=0;i<n;i++)
{
    cout<<*(match+i)+1<<" ";    // output: matching result
}
delete [] match;
return 0;

此外,您还应该释放内存

int **MPint **WP

我相信这就是问题所在,发生这种情况是因为像 int match[n]; 这样的局部变量的内存仅在分配它的函数内有效。

如果您有兴趣,对此有一个更"科学"的解释。