[Algorithms] Gale-Shapley算法(婚姻匹配问题,高考录取机制)

本文深入解析Gale-Shapley算法,一种确保稳定匹配的市场机制,应用于婚配问题和高考录取机制中,避免‘高分低就’现象,实现个人与机构间的最优匹配。

盖尔-沙普利算法(Gale-Shapley)

简称“GS算法”,也称为延迟接受算法。是盖尔和沙普利为了寻找一个稳定匹配而设计出的市场机制。

稳定婚配问题

这是GS算法主要的应用领域,假设现在有五位男士(A,B,C,D,E),四位女士(a,b,c,d),他们参加一档相亲节目,如何配对能保证最终的相亲结果是稳定的

稳定婚姻就是不存在两个人都认为对方比自己现在的婚配对象更好,例如A与a婚配,B与b婚配,但是A认为b比a更适合自己,b也认为A比B更适合自己,这就是一种不稳定的婚姻关系

而Gale-Shapley算法得到的最终结果一定是一组稳定的婚配关系

算法流程:

初始状态下

关系未知

首先,参加婚配的男士和女士根据各自情况对异性做出排序(根据偏好程度)

做出排序

所有人都完成自己的偏好列表后

全部排序

开始进行邀请,由男士邀请女士,男士根据自己的偏好列表发出邀请,女士在收到邀请后会决定接收或拒绝
当自己现在没有婚配对象并且邀请人在自己考虑范围之内时这位女士会“暂时”接收邀请,当这名女士已经有暂时婚配对象时,女士会将这两名邀请人进行比较,接收其中更偏好的邀请人的邀请,拒绝另外一位的邀请

第一轮

可以看到在第一轮的邀请过程中,男士A与女士b暂时达成婚配关系,男士B与女士c暂时达成婚配关系,男士D与女士d暂时达成婚配关系,而男士C与男士E的邀请都被拒绝
在第二轮的邀请中,上一轮确定婚配关系的男士会放弃邀请,上一轮邀请失败或者被拒绝的男士按照偏好表顺序继续发出邀请

第二轮

在第二轮邀请过程中,C与D的邀请均失败,男士C是由于女士b更偏好A,男士E则是由于不在女士c的考虑范围之内

第三轮

可见第三轮邀请仍然以两位的失败告终

第四轮

第四轮邀请,男士C比男士D更被女士d偏好,所以邀请成功,男士D则被拒绝,达成的暂时婚配关系失效。而男士E则再次被拒绝,并且由于他已经邀请了自己偏好表中的所有女士,所以他被迫出局

第五轮

接下来的五,六,七轮中,只有男士D不断发出邀请,但都被拒绝

最终结果

最终,男士D,男士E由于邀请都被拒绝而出局,女士A由于未接收任何邀请也被迫出局。而男士A与女士b,男士B与女士c,男士C与女士d,最终确定婚配关系。
并且达成的都是稳定的婚配关系。

算法的结果

算法最终的结果是稳定匹配的婚姻关系,但不一定是匹配最大的婚姻关系,例如 A-a,B-b,C-c,D-d 可以构成四对匹配关系,但这并不是稳定的因为相较于各自现在的对象,A更偏好b,b也更偏好A。

另外算法中的结果,对于发出邀请的一方往往只能将就,而被邀请的一方往往拥有更好的选择(邀请者在与被邀请者确定暂时匹配关系后,被邀请者可以继续接收更偏好的人的邀请,并结束这段暂时匹配关系,而邀请者就只能继续匹配更不偏好的被邀请者)

算法实现

Man类,表示婚姻匹配问题中发出邀请的男士

package Gender;
import edu.princeton.cs.algs4.Queue;


/*
 * 男性类Man
 * 继承了可比类Comparable
 * 实现了婚配过程中的发出邀请
 * 以及暂时接收后被拒绝等过程
 */


public class Man implements Comparable<Man>{
    private char name;  //男性姓名
    public int[] favorNum;
    private Queue<Woman> favor;  //利用先进先出队列实现男性的偏好队列
    private boolean status;  //男性婚配状态,是否暂时拥有婚配对象
    private Woman current_Girl;  //当前婚配对象
    private boolean failed;  //通过偏好队列是否为空判断是否出局



    //构造函数
    public Man(char name_in,int numWoman){
        name=name_in;
        favorNum=new int[numWoman];
        favor= new Queue<>();  //初始化队列
        status=false;  //初始状态无婚配状态
        current_Girl=null;  //暂定女友为null
        failed=false;  //初始状态没有出局
    }

    //通过数组进行入队操作,获取偏好队列
    public void EntryQueue(Woman[] womanGroup){
        for (int favorGirl : favorNum) {
            favor.enqueue(womanGroup[favorGirl]);
        }
    }

    //定义Invitation方法,用于对异性发出邀请并处理
    public int Invitation(){
        //如果已有婚配,本轮放弃发送邀请
        if(status) return 0;
        //如果已出局,本轮放弃发送邀请
        if(failed) return 0;
        //正常发送邀请
        else{
            //从偏好队列中出队,获取当前最偏好的异性
            Woman Girl=favor.dequeue();
            //调用Woman的ReceiveInvitation()方法,获得邀请的结果
            boolean result=Girl.ReceiveInvitation(this
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值