Gale-Shapley 稳定匹配算法的C++实现

文章详细介绍了Gale-Shapley稳定匹配算法,包括算法的内涵、伪码表示以及C++实现过程。通过男生求婚和女生判断的逻辑,确保算法的稳定性和完备性。同时,证明了算法的有限步数、稳定性以及男性最佳策略,展示了算法在博弈论中的应用。

背景简述

Gale-Shapley 算法是针对稳定匹配问题提出的一种经典算法。
背景资料:考虑n对男女的配对,其中每个男生有一个心仪女生排序,而每个女生也有一个心仪男生排序。每个男生、女生都想匹配到自己最心仪的异性,但现实情况中上总会有一个男生(或女生)至少是两个女生的共同的最心仪对象。那么就需要找到一种折中的匹配方式,使得配对后的每对伴侣都不会再因追求更好伴侣,而产生配对破裂,即一种稳定的匹配。

稳定匹配的内涵

即每对配对成功的情侣,总是存在这种情况:
以情侣中的男性 X 举例,假如他的配偶不是他最心仪的异性 A,A 的当前配偶是Y,Y 在 A 心目中排序要比 X 高。那么 A 就不会舍弃当前配偶 Y,而去与 X 进行配对。假设 X 的当前配偶为 B , 同样的,所有在 X 的心目中比 B排名靠前的异性,都是这种情况,那么 B就是 X所能配到的稳定配偶;类似的,B 的稳定配偶也是 X。 则这一对配对就是稳定的。

Gale-Shapley 算法的伪码表示

Initialize each person to be free.

while (some man is free and hasn’t proposed to every woman)
{
Choose such a man m
w = 1st woman on m’s list to whom m has not yet proposed
if (w is free)
assign m and w to be engaged
else if (w prefers m to her fiancé m’)
assign m and w to be engaged, and m’ to be free
else
w rejects m
}

Gale-Shapley 算法的C++实现

实现思路

设置一个男生求婚函数,每次求婚时调用此函数,对其心仪女生进行降序求婚,直至该男生求婚成功;
设置一个女生判断函数,判断此次是否接受该男生的求婚,值得注意一点是,当女生抛弃当前对象而接受目前求婚对象时,函数应将该被抛弃的男生号码以某种形式传出;

设定一个男生待匹配队列 unpaired_man[n];
最开始将所有男生都装入此队列;
每次将队列头部的男生取出,调用求婚函数进行求婚,而被求婚女生则调用判断函数,当发生女生需要抛弃当前对象时,函数应接受到被抛弃男生的号码,将其配偶情况及配对情况进行重置,并压入队列尾部。
循环操作,直至男生待匹配队列为空,则匹配完成。

代码段

#include "stdafx.h"
#include <queue>
#include <iostream>
#include <Windows.h>
using namespace std;

class man
{
   
   
	int m[5];
	int m_ID;
	bool is_married ;
	int proposal_count;
	int married_ID ;
	
	friend class woman;
	friend void GS_Matching(man* _M, woman *_WM);//进行GS算法配对
	friend void func(man *_m); //输出每个男生的配对信息

public:
	void propose(woman &_wm, man *_M);  //男生的求婚函数,每次对一个女生求婚
	man(int *_m, int _m_ID)  // 构造函数对男生进行初始化
	{
   
   
		for(int i=0; i<5; i++)
		{
   
    m[i]=*_m; _m++;}
		m_ID = _m_ID;
		is_married = 0;
		proposal_count = 0;
		married_ID = 0;
	}
	man(){
   
   }
	void printInfo(man _M)//输出每个男生的心仪女生信息
	{
   
   
	cout<<"这是第"<<_M.m_ID<<"个男生"<<endl;
	cout<<"他的排序是"<<_M.m[0]<<" "<<_M.m[1]<<" "<<_M.m[2]<<" "<<_M.m[3]<<" "<<_M.m[4]<<" "<<endl;
	}
};

class woman
{
   
   
	int wm[5];
	int w_ID;
	bool is_married;
	int current_manID;
	int unlucky_m; 

	friend class man;
	friend void GS_Matching(man* _M, woman *_WM);//进行GS算法配对
	friend void func(woman *_wm);  //输出女生的配对信息

public:
	woman(int *_wm, int _wm_ID)
	{
   
   
		for
稳定匹配问题是一个经典的算法问题,其中Gale-Shapley算法是一种常用的解决方案。下面我简要介绍如何使用C语言编写程序来求解稳定匹配问题。 首先,我们需要定义一个结构体来表示每个人的偏好列表和当前匹配状态。偏好列表可以用整数数组来表示,数组的索引表示其他人的编号,数组的值表示对这个人的偏好等级。例如,假设有n个人,我们可以定义一个结构体如下: ```c typedef struct { int n; // 人数 int **preference; // 偏好列表 int *matching; // 当前匹配 } MatchingProblem; ``` 然后,我们可以使用如下的Gale-Shapley算法来求解稳定匹配问题: 1. 初始化所有人的匹配状态为空。 2. 循环直到没有人再能够改变匹配状态为止: a. 对于每个未匹配的人,选择他偏好列表中的下一个候选人,记为当前候选人。 b. 如果当前候选人未匹配,则直接将其与该人匹配。 c. 如果当前候选人已经匹配,判断当前候选人是否更优于当前匹配。如果是,将当前匹配与当前候选人匹配,将原先与当前候选人匹配的人重新放回未匹配状态。 3. 输出每个人的匹配结果。 在C语言中,我们可以使用指针和动态内存分配来操作偏好列表和当前匹配状态。具体实现可以参考下面的伪代码: ```c void gale_shapley(MatchingProblem *problem) { int *proposals = malloc(sizeof(int) * problem->n); // 存储每个人的偏好索引 int *acceptances = malloc(sizeof(int) * problem->n); // 存储每个人的匹配状态 // 初始化匹配状态和偏好索引 for (int i = 0; i < problem->n; i++) { acceptances[i] = -1; // -1表示未匹配状态 proposals[i] = 0; // 初始化偏好索引为0 } while (1) { // 查找未匹配的人 int unmatched = -1; for (int i = 0; i < problem->n; i++) { if (acceptances[i] == -1) { unmatched = i; break; } } if (unmatched == -1) { // 所有人都已匹配 break; } // 获取当前候选人 int current = problem->preference[unmatched][proposals[unmatched]]; proposals[unmatched]++; if (acceptances[current] == -1) { // 当前候选人未匹配 acceptances[current] = unmatched; acceptances[unmatched] = current; } else if (problem->preference[current][unmatched] < problem->preference[current][acceptances[current]]) { // 当前候选人更优 acceptances[acceptances[current]] = -1; // 原来的匹配放回未匹配状态 acceptances[current] = unmatched; acceptances[unmatched] = current; } } // 输出匹配结果 for (int i = 0; i < problem->n; i++) { printf("Person %d is matched with Person %d\n", i, acceptances[i]); } free(proposals); free(acceptances); } ``` 通过以上的程序,我们可以使用Gale-Shapley算法来求解稳定匹配问题。该算法具有良好的时间复杂度,并且可以保证返回的匹配结果是稳定的。希望这个回答可以帮助你理解如何使用C语言编写程序来求解稳定匹配问题。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值