离散实验 判断集合之间是单射,满射还是双射

离散实验 判断集合之间是单射,满射还是双射通过C++实现集合间映射关系判断思路:创建判断两个集合之间是否是单射,满射,双射的函数,同时也分别创建三个函数,里面存放两集合间的映射关系,再通过刚刚创建的判断函数,进行验证是否满足条件。涉及的数学知识1.单射:设f是由集合A到集合B的映射,如果所有x,y∈A,且x≠y,都有f(x)≠f(y),则称f为由A到B的单射。2.满射:如果每个可能的像至少有一个变量映射其上(即像集合B中的每个元素在A中都有一个或一个以上的原像),或者说值域任何元素都有至少有一个变量与之对应,那这个映射就叫做满射。3.双

大家好,又见面了,我是你们的朋友全栈君。

通过C++实现集合间映射关系判断

思路:
创建判断两个集合之间是否是单射,满射,双射的函数,同时也分别创建三个函数,里面存放两集合间的映射关系,再通过刚刚创建的判断函数,进行验证是否满足条件。

涉及的数学知识

1.单射:设f是由集合A到集合B的映射,如果所有x,y∈A,且x≠y,都有f(x)≠f(y),则称f为由A到B的单射。
2.满射:如果每个可能的像至少有一个变量映射其上(即像集合B中的每个元素在A中都有一个或一个以上的原像),或者说值域任何元素都有至少有一个变量与之对应,那这个映射就叫做满射。
3.双射:既是单射又是满射的映射称为双射,亦称“一一映射”。

插入相应集合

思路:大体一致以单射举例
vector<int> srcvector<int> dst作为参数传进我们创建的map<int, int> BuildInjection
我们创建一个新的map<int, int> injection;函数用来存放两个集合间的映射关系。
由单射定义可以知道,当我们的x中的元素大于y中的元素时一定不满足我们的单射,然后我们按照x中的元素个数进行遍历将y中的元素与之对应,这个我们使用到pair<int,int> p(src[i],dst[i]);pair是将2个数据组合成一组数据,当需要这样的需求时就可以使用pair,其中我们的map就是将key和value放在一起来保存。我们将pair里面的数据插入到map中来,进行保存,方便我们下一次在判断是否为单射的时候使用

/* BuildInjection 功能:构造集合src到集合dst的单射,将建立的映射保存在返回值injection中 例如,将src中的元素1映射为dst中的元素3,则injection[1] = 3 */
map<int, int> BuildInjection(vector<int> src, vector<int> dst)
{ 
   
	map<int, int> injection;
	if(src.size()>dst.size()){ 
   
		cout<<"不能创建单射"<<endl;
	}else{ 
   
		for(int i=0;i<src.size();i++){ 
   
			pair<int,int> p(src[i],dst[i]);
			injection.insert(p);
		}
	}
	return injection;
}

/* BuildSurjection 功能:构造集合src到集合dst的满射,将建立的映射保存在返回值surjection中 */


map<int, int> BuildSurjection(vector<int> src, vector<int> dst)
{ 
   
	map<int, int> surjection;
	if(src.size()<dst.size()){ 
   
		cout<<"不能创建满射"<<endl;
	}else{ 
   
		for(int i=0;i<src.size();i++){ 
   
			pair<int,int> p(src[i],dst[i%dst.size()]);
			surjection.insert(p);
		}
	}

	return surjection;
}

/* BuildBijection 功能:构造集合src到集合dst的双射,将建立的映射保存在返回值bijection中 */

map<int, int> BuildBijection(vector <int> src, vector<int> dst)
{ 
   
	map<int, int> bijection;
	if(src.size()!=dst.size()){ 
   
		cout<<"不能创建双射"<<endl;
	}else{ 
   
		for(int i=0;i<src.size();i++){ 
   
			bijection[src[i]]=dst[i];
		}
	}
	return bijection;
}

1.1 判断是否是单射

思路:
在判断一组映射关系是否是单射时,我们主要去判断x中的元素在y中都有与之对应的,而且一个x对应一个y,主要采用的还是一种标记的思想,在传入进来的y中进行遍历,让y中的元素全部标记为1,我们再在那段映射关系中进行遍历,如果说有不等于1的就证明在这段映射关系中,有不是y中的元素,所以我们可以让他返回一个false;同时要注意的是即使y存在在这段映射关系中,也不能直接就判断这个映射是单射,因为其中有两个x对应同一个y的情况,所以我们可以通过一个计数的思想将这段映射关系中符合y中标记为1的自加,如果我们自加的个数>1就说明其中存在两个x对应同一个y,我们也让其返回false,反之,返回true
:在我们去判断自加数是否>1的时候,我们应该在我们创建的那个flag中及逆行遍历
:由于我们是写了一个变量通过改变这个变量的值进行改变这个函数的返回值的,所以要在我们发现自加数>1存在就让其停止循环,加上break

/* ValidateInjection 功能:验证给定的两个集合src和dst之间的映射injection是否为单射。 如果是单射则返回true,不是单射返回false */
bool ValidateInjection(vector<int> src, vector<int> dst, map<int, int> injection)
{ 
   
	bool bIsInjection = false;
	map<int,int>mp,flag; 
	map<int,int>::iterator it=injection.begin();
	if(injection.size()<src.size()){ 
   
		return false;
	} else{ 
   
	
		for(int i=0;i<dst.size();i++){ 
   
			mp[dst[i]]=1; flag[dst[i]]=0;
		}
		for(;it!=injection.end();it++){ 
   
			if(	!mp[it->second]) bIsInjection = false;
			flag[it->second]++;
		}
	}
	for(it=flag.begin();it!=flag.end();it++){ 
   
		if(it->second>1) { 
   
			bIsInjection = false;
			break;
		}else { 
   
			bIsInjection = true;
		}
		
	}
	
	return bIsInjection ;
}

1.2判断是否是满射

思路:
在判断一个映射是否是满射时,我们主要去判断每一个x都有y与之对应,同时y中都有x与之对应,采用的还是标记和计数的思想,主要和上面单射的区别就是在于计数,这一块,如果我们自加数要是少于我们y中的元素个数,就证明在我们这个映射关系中有y存在剩余,这不满足满射定义。返回false,否则返回true。

/* ValidateSurjection 功能:验证给定的两个集合src和dst之间的映射surjection是否为满射。 如果是满射则返回true,不是满射返回false */
bool ValidateSurjection(vector<int> src, vector<int> dst, map<int, int> surjection)
{ 
   
	bool bIsSurjection=false;
	map<int,int>mp,flag; 
	map<int,int>::iterator it= surjection.begin();
		for(int i=0;i<dst.size();i++){ 
   
			mp[dst[i]]=1; flag[dst[i]]=0;
		}
		for(;it!=surjection.end();it++){ 
   
			if(	!mp[it->second])  bIsSurjection = false;
			flag[it->second]++;
		}
	for(it=flag.begin();it!=flag.end();it++){ 
   
		if(it->second<dst.size())  bIsSurjection = false;
			 bIsSurjection = true;
	}
	return bIsSurjection;
}

1.3判断是否是双射

思路:
双射:即使单射也是满射,二者同时满足,所以我们可以使用上面我们判断单射和满射的函数及逆行判断是否是双射。

/* ValidateBijection 功能:验证给定的两个集合src和dst之间的映射bijection是否为双射。 如果是双射则返回true,不是满射返回false */
bool ValidateBijection(vector<int> src, vector<int> dst, map<int, int> bijection)
{ 
   
	bool bBiSurjection = false;
	if(bijection.size()!=src.size()){ 
   
		return false;
	} else{ 
   
		bBiSurjection = (ValidateInjection(src, dst, bijection) && ValidateSurjection(src, dst, bijection));
	}
	return bBiSurjection;
}

主函数

int main()
{ 
   
	vector<int> setA, setB, setC;
	for (int i = 0; i < 10; i++)
		setA.push_back(i);
	for (int i = 50; i < 70; i++)
		setB.push_back(i);
	for (int i = 130; i < 140; i++)
		setC.push_back(i);

	map<int, int>::iterator iter;
	
	map<int, int> injection;
	injection = BuildInjection(setA, setB);
	for (iter = injection.begin(); iter != injection.end(); iter++)
		cout << iter->first << "->" << iter->second << endl;
	cout << ValidateInjection(setA, setB, injection) << endl;
	system("pause");

	map<int, int> surjection;
	surjection = BuildSurjection(setB, setA);
	for (iter = surjection.begin(); iter != surjection.end(); iter++)
		cout << iter->first << "->" << iter->second << endl;
	cout << ValidateSurjection(setB, setA, surjection) << endl;
	system("pause");

	map<int, int> bijection;
	bijection = BuildBijection(setA, setC);
	for (iter = bijection.begin(); iter != bijection.end(); iter++)
		cout << iter->first << "->" << iter->second << endl;
	cout << ValidateBijection(setA, setC, bijection) << endl;
	system("pause");

    return 0;
}

总结

1.此次实验总体上采用的是一种计数和标记的思想,能实现这个想法主要是map函数它有两个参数,一个是key,一个是value值,:key值不能有重复的,有重复的会自动将其删除一个,但是value值可以有重复的,这让标记可以实现。本次计数也是通过创建map函数进行计数的flag[it->second]++;
2.同时注意我们要判断函数的范围即我们要在哪个for循环中进行遍历
3.对pair的元素进行操作的时候,通过first和sencond访问it->second

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/132991.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 小程序怎么开发自己的小程序_微信小程序建议使用

    小程序怎么开发自己的小程序_微信小程序建议使用微信小程序入门前言随着科技的不断进步,很多功能将会开放,那么很多需求也将会因为现实而得到满足,这是一种不需要下载和安装就可以使用的应用软件。用户只需扫描和搜索就可以打开应用程序。它很容易使用,而且很容易实现。小程序带来了巨大的流量,吸引了很多大的人和企业家前来追踪,也显示出它强大的生命力。小程序是下一个被确定为互联网新品种的程序,信已经成为不可缺少的交流工具,小程序依附于微信,用户搜索起来也会更方便,其实这就是小程序发展的前景和优势。提示:以下是本篇文章正文内容,下面案例可供参考一、小程序的概

    2022年9月27日
    2
  • cmap用法,很详细(转)

    http://hi.baidu.com/wei83523408/blog/item/878ebd3b8898d5e115cecb2b.html一、Map的基本知识  映射(Map),又称为字典(Dictionary),是由关键字(Key)及其对应的元素值(Value)所组成的元素单元(Element)的表单式集合。通常,对于Map而言,使用给定的Key,可以迅速地从

    2022年4月3日
    211
  • vim插件管理工具pathogen[通俗易懂]

    vim插件管理工具pathogen[通俗易懂]因为vim编辑的时候,实在记不住复杂的目录结构,为了更方便展示,所以想到安装树形目录插件,自然是用到最多的NERDTree。说到安装vim插件首先需要安装vim插件管理工具啊。简单说一下vim插件管理工具pathogen,官网http://www.vim.org/scripts/script.php?script_id=2332。

    2025年7月25日
    3
  • c#窗体应用程序怎么保存_importedfile用什么打开

    c#窗体应用程序怎么保存_importedfile用什么打开选择保存文件时先将文件名生成传入,点击OK和取消使用FileOK委托。///<summary>///另存文件对话框///</summary>///<paramname=”fileName”>想命名的文件名</param>///<returns>&lt…

    2022年10月8日
    3
  • Jenkins教程(Windows版)

    Jenkins教程(Windows版)安装Java环境安装过程省略环境变量JAVA_HOME=C:\ProgramFiles\Java\jdk1.8.0_191PATH增加%JAVA_HOME%\binjava-version安装Maven环境安装过程省略环境变量MAVEN_HOME=D:\apache-maven-3.5.4PATH增加%MAVEN_HOME%\binmvn-v安装Tomcat环境安装过程省略环境变量CATALINA_BASE=D:\apache-tom..

    2022年5月14日
    40
  • win10任务栏图标显示白色方块_win10图标左下角有白色方块

    win10任务栏图标显示白色方块_win10图标左下角有白色方块首先打开一个文件夹点击【查看】菜单,然后勾选【隐藏的项目】;使用【Win】+【R】打开【运行】输入%localappdata%;删除【Iconcache.db】;在任务栏右键的打开【任务管理器】;找到【Windows资源管理器】右键选择【重新启动】。…

    2022年8月31日
    5

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号