给定一集合A和集合A上的一个二元关系,判断其性质,然后根据性质判定是否为等价、相容、偏序关系。

目录

离散数学知识点回顾

关系及其表示 

关系的性质

关系的类型

数据结构 

集合

关系

算法 与 源代码

集合的读取

关系的读取 

自反的与反自反的

对称的与反对称的

传递的

关系的类型

 完整源代码

心得


离散数学知识点回顾

关系及其表示 

任一序偶的集合确定了一个二元关系R,R中任一序偶<x,y>可记作xRy

设R为定义在集合X上的二元关系 

关系的性质

自反的:如果对于每个x属于X,有xRx,则称二元关系R是自反的。

对称的:如果对于每个x,y属于X,每当xRy,就有yRx,则称二元关系R是对称的。

传递的:如果对于任意x,y,z属于X,每当xRy,yRz时就有xRz,称二元关系R是传递的。

反自反的:如果对于每一个x属于X,都有<x,x>不属于R,则称二元关系R是反自反的。

反对称的:对于每一个x,y属于X,每当xRy和yRx必有x=y,则称二元关系R是反对称的。

关系的类型

等价关系:若R是自反的,对称的和传递的,则R称为等价关系。

相容关系:若R是自反的,对称的,则R是相容关系。

偏序关系:若R满足自反性、反对称性和传递性,则称R是X上的一个偏序关系。 

数据结构 

集合

采用元素类型为int的vector容器来表示集合,储存集合中的元素。

设置bool类型的一维数组,索引与元素值呈现一一对应关系,数组元素值为ture时表示索引所对应的元素值存在于集合内,为false则表示不属于集合。

关系

采用元素类型为pair<int,int>的vector容器来表示关系,储存关系中的序偶。

设置bool类型的二维数组, 索引对与序偶呈现一一对应关系,数组元素值为ture时表示索引对所对应的序偶存在于关系中,为false则表示不在关系内。

算法 与 源代码

集合的读取

算法:

先输入集合中元素的个数,然后依次读取集合中的元素,在把元素放入集合之前,需要先判断该元素是否已经在集合内,若在已经存在于集合内则返回错误信息,否则将元素放入集合,并且更新相应的bool类型的数组的值。

源代码:

Status Preprocessing_Set()
{
	cout << "请输入集合中元素的个数:" << endl;
	int N;
	cin >> N;
	cout << "请输入集合中的元素(以空格分隔):" << endl;
	while (N--)
	{
		int Factor;
		cin >> Factor;
		if (Element[Factor])
		{
			cout << "集合中不允许存在值相同的元素" << endl;
			return 0;
		}
		else
		{
			Element[Factor] = true;
			Set.push_back(Factor);
		}
	}
	return 1;
}

关系的读取 

算法:

先输入关系中序偶的个数,然后依次读取关系中的序偶,在把序偶放入关系之前,需要先判断该序偶中的第一元素和第二元素是否在集合中,而且还需要判断该序偶是否已经存在于关系中,如若第一、二元素在集合内且序偶并没有已经存在于关系中,则将序偶放入关系内,并且更新相应的bool类型数组的值,否则返回错误信息。

源代码:

Status Preprocessing_Rel()
{
	cout << "请输入关系中序偶的个数:" << endl;
	int N;
	cin >> N;
	cout << "请输入关系中的序偶(格式:元素1 元素2 元素3 元素4.....):" << endl;
	while (N--)
	{
		pair<int, int> p;
		cin >> p.first >> p.second;
		if (Element[p.first] && Element[p.second] && !Pair[p.first][p.second])
		{
			Pair[p.first][p.second] = true;
			Relation.push_back(p);
		}
		else
		{
			cout << "关系并非集合上的关系或关系中出现重复的序偶" << endl;
			return 0;
		}
	}
	return 1;
}

自反的与反自反的

算法:

核心思想是计算关系中满足自反性的序偶的个数,判断该个数是否与集合中元素个数相等。

若该个数为零,说明关系满足反自反性,若两者相等,则关系满足自反性。

:满足自反的序偶:这种说法不严谨,是我自己编造的,其实就是<x,x>的个数)

源代码:

Status IsZf()
{
	int num = 0; //满足自反序偶的个数
	for (auto a : Set)
	{
		if (Pair[a][a])
			num++;
	}
	if (!num)
		return 2;
	else if (num == Set.size())
		return 1;
	else
		return 0;
}

对称的与反对称的

算法:

在考虑对称与反对称时,需要将第一元素和第二元素相等的序偶特殊处理,所以设置了两个变量分别记录满足对称序偶的序偶个数,以及第一元素和第二元素相等的序偶个数(即满足自反的序偶个数)。

源代码:

Status IsDc()
{
	int num_equal = 0, num_symmetry = 0; //num_equal记录<i,i>的个数,num_symmetry记录满足序偶对称的个数
	for (auto a : Relation)
	{
		if (Pair[a.second][a.first])
			num_symmetry++;
		if (a.first == a.second)
			num_equal++;
	}
	if (num_symmetry == num_equal)
		return 2;
	else if (num_symmetry == Set.size())
		return 1;
	else
		return 0;
}

:个人认为这块是比较难顺的,需要搞清楚基本概念才能通畅理解)

传递的

算法:

双重循环,外层循环是遍历关系中的每一个序偶,内层循环同样也是遍历关系中的每一个序偶,当外层序偶的第二个元素的等于内层序偶的第一个元素时,判断由外层序偶第一个元素和内层序偶第二个元素组成的序偶是否在关系内,若在,则继续,若不在,则直接返回错误信息。若外层序偶的第二个元素的不等于内层序偶的第一个元素时,则继续遍历下一个序偶。

源代码:

Status IsCd()
{
	for (auto a : Relation)
		for (auto b : Relation)
			if (a.second == b.first)
				if (!Pair[a.first][b.second])
					return 0;
	return 1;
}

关系的类型

算法:

算法核心其实就是概念的辨析,概念整明白了,那算法也就不难写。

源代码:

void Rel_Type()
{
	if (IsZf() == 1)
		if (IsDc() == 1)
			if (IsCd())
				cout << "该关系为等价关系" << endl;
			else
				cout << "该关系为相容关系" << endl;
		else if (IsDc() == 2 && IsCd())
			cout << "该关系为偏序关系" << endl;
		else
			cout << "既不是偏序关系,也不是相容关系,更不是等价关系" << endl;
	else
		cout << "既不是偏序关系,也不是相容关系,更不是等价关系" << endl;
}

 完整源代码

#include <bits/stdc++.h>

using namespace std;

typedef int Status;

/* 集合——存放元素,关系——存放序偶 */
vector<int> Set;				 //集合
vector<pair<int, int>> Relation; //关系

/* 标记元素(序偶)是否在集合(关系)中,在则为TRUE,不在则为FALSE */
bool Element[100] = {0};   //元素是否在集合中
bool Pair[100][100] = {0}; //序偶是否在关系中

Status Preprocessing_Set(); //集合预处理,即读入元素数据的过程,出错->0,正确->1
Status Preprocessing_Rel(); //关系预处理,即读入序偶数据的过程,出错->0,正确->1
Status IsZf();				//判断是否具有自反性,自反性->1,反自反性->2,既不自反也不反自反->0
Status IsDc();				//判断是否具有对称性,对称性->1,反对称性->2,既不对称也不反对称->0
Status IsCd();				//判断是否具有传递性,传递性->1,不传递->0
void Rel_Character();		//检验关系的性质
void Rel_Type();			//检验关系的类型

int main()
{
	if (Preprocessing_Set() && Preprocessing_Rel())
	{
		Rel_Character();
		Rel_Type();
	}
	return 0;
}

Status Preprocessing_Set()
{
	cout << "请输入集合中元素的个数:" << endl;
	int N;
	cin >> N;
	cout << "请输入集合中的元素(以空格分隔):" << endl;
	while (N--)
	{
		int Factor;
		cin >> Factor;
		if (Element[Factor])
		{
			cout << "集合中不允许存在值相同的元素" << endl;
			return 0;
		}
		else
		{
			Element[Factor] = true;
			Set.push_back(Factor);
		}
	}
	return 1;
}
Status Preprocessing_Rel()
{
	cout << "请输入关系中序偶的个数:" << endl;
	int N;
	cin >> N;
	cout << "请输入关系中的序偶(格式:元素1 元素2 元素3 元素4.....):" << endl;
	while (N--)
	{
		pair<int, int> p;
		cin >> p.first >> p.second;
		if (Element[p.first] && Element[p.second] && !Pair[p.first][p.second])
		{
			Pair[p.first][p.second] = true;
			Relation.push_back(p);
		}
		else
		{
			cout << "关系并非集合上的关系或关系中出现重复的序偶" << endl;
			return 0;
		}
	}
	return 1;
}
Status IsZf()
{
	int num = 0; //满足自反序偶的个数
	for (auto a : Set)
	{
		if (Pair[a][a])
			num++;
	}
	if (!num)
		return 2;
	else if (num == Set.size())
		return 1;
	else
		return 0;
}
Status IsDc()
{
	int num_equal = 0, num_symmetry = 0; //num_equal记录<i,i>的个数,num_symmetry记录满足序偶对称的个数
	for (auto a : Relation)
	{
		if (Pair[a.second][a.first])
			num_symmetry++;
		if (a.first == a.second)
			num_equal++;
	}
	if (num_symmetry == num_equal)
		return 2;
	else if (num_symmetry == Set.size())
		return 1;
	else
		return 0;
}
Status IsCd()
{
	for (auto a : Relation)
		for (auto b : Relation)
			if (a.second == b.first)
				if (!Pair[a.first][b.second])
					return 0;
	return 1;
}
void Rel_Character()
{
	//自反性与反自反性的检验
	switch (IsZf())
	{
	case 0:
		cout << "既不自反也不反自反" << endl;
		break;
	case 1:
		cout << "满足自反性" << endl;
		break;
	case 2:
		cout << "满足反自反性" << endl;
	}
	//对称性与反对称性的检验
	switch (IsDc())
	{
	case 0:
		cout << "既不对称也不反对称" << endl;
		break;
	case 1:
		cout << "满足对称性" << endl;
		break;
	case 2:
		cout << "满足反对称性" << endl;
	}
	//传递性的检验
	switch (IsCd())
	{
	case 0:
		cout << "不满足传递性" << endl;
		break;
	case 1:
		cout << "满足传递性" << endl;
	}
}
void Rel_Type()
{
	if (IsZf() == 1)
		if (IsDc() == 1)
			if (IsCd())
				cout << "该关系为等价关系" << endl;
			else
				cout << "该关系为相容关系" << endl;
		else if (IsDc() == 2 && IsCd())
			cout << "该关系为偏序关系" << endl;
		else
			cout << "既不是偏序关系,也不是相容关系,更不是等价关系" << endl;
	else
		cout << "既不是偏序关系,也不是相容关系,更不是等价关系" << endl;
}

心得

学习了c++之后,会觉得c语言有时候很笨重很麻烦,所以总想着直接利用c++里面的模板、函数去解决问题,有时候这样会适得其反,反而效率变得低下,所以还是要根据实际情况,结合问题去选择相应的数据结构和算法,结合实际永远不会丢。

  • 2
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

罗马尼亚硬拉

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值