离散数学大作业

题目:设R为有限集合A上的关系(n=|A|),则编写程序实现如下问题:

  • 试使用关系性质判断的等价条件(如:自反、对称、传递)判断关系R是否是等价关系?
  • 若R是等价关系,则求由R诱导的集合A的划分。
  • R不是等价关系,则求包含R最小等价关系
  • 求集合A上等价关系的个数。

编程语言:C语言或者C++。

解题思路描述:

1.定义一个函数来检查给定的关系是否是等价关系。

  • 检查该关系是否具有自反性。
  • 检查该关系是否具有对称性。
  • 检查该关系是否具有传递性。
//定义一个函数来检查给定的关系是否是等价关系。

bool is_equivalence_relation(vector<vector<int>>& R, int n) {

//检查自反性

for (int i = 0; i < n; i++) {

if (!R[i][i]) return false;

}

 

//检查对称性

for (int i = 0; i < n; i++) {

for (int j = 0; j < n; j++) {

if (R[i][j]) {

if (!R[j][i]) return false;

}

}

}

 

//检查传递性

for (int i = 0; i < n; i++) {

for (int j = 0; j < n; j++) {

for (int k = 0; k < n; k++) {

if (R[i][j] && R[j][k]) {

if (!R[i][k]) return false;

}

}

}

}

return true;

}

 

2.将定义一个函数来计算由给定的等价关系诱导的集合A的划分。

(1)初始化一个空的划分结果P,以及一个长度为n的标记数组visited。

(2)对于每个未被访问过的元素i,执行以下步骤:

a.从i开始,向前遍历R的第i行,标记所有与i关联的元素为已访问,并将它们加入到划分结果P中。

b.从i开始,向后遍历R的第i列,标记所有与i关联的元素为已访问,并将它们加入到划分结果P中。

(3)返回划分结果P。

//定义一个函数来计算由给定的等价关系诱导的集合A的划分。

vector<vector<int>> induce_partitions(vector<vector<int>>& R, int n) {

vector<vector<int>> partitions(n);

for (int i = 0; i < n; i++) {

partitions[i].push_back(i);

}

 

for (int i = 0; i < n; i++) {

for (int j = 0; j < n; j++) {

if (R[i][j]) {

merge(partitions[i], partitions[j]);

}

}

}

return partitions;

}
 

3.定义一个函数求包含R最小的等价关系。

(1)初始化两个二维矩阵trans和result,并把它们的大小都设置为n*n(n为输入矩阵R的大小)。我们将trans初始化为R的副本,并将result初始化为全零矩阵。

(2)使用Floyd的算法计算传递闭包。反复遍历trans矩阵,如果发现某个元素trans[i][j]为1,则再遍历一行j,将trans[k][j]设为1。这个过程一直持续到没有更多的改变发生。

(3)遍历trans矩阵,如果trans[i][j]为1,则将result[i][j]设为1。这样,result矩阵就变成了包含R的最小等价关系。

//定义一个函数求包含R最小的等价关系。

vector<vector<int>> closure(vector<vector<int>>& R,int n) {

vector<vector<int>> trans(n, vector<int>(n));

vector<vector<int>> result(n, vector<int>(n));

for (int i = 0; i < n; i++) {

for (int j = 0; j < n; j++) {

trans[i][j] = R[i][j];

}

}
 

bool changed = true;

while (changed) {

changed = false;

for (int i = 0; i < n; i++) {

for (int j = 0; j < n; j++) {

if (trans[i][j]) {

for (int k = 0; k < n; k++) {

if (!trans[k][j]) {

trans[k][j] = 1;

changed = true;

}

}

}

}

}

}

 

for (int i = 0; i < n; i++) {

for (int j = 0; j < n; j++) {

if (trans[i][j]) {

result[i][j] = 1;

}

else {

result[i][j] = 0;

}

}

}

return result;

}

 

4.定义一个函数来计算集合A上所有可能的等价关系的数量。

假设每个元素都可以与任何其他元素关联,从而产生n^2个可能的等价关系。

//定义一个函数来计算集合A上所有可能的等价关系的数量。

int count_equivalence_relations(int n) {

return n * (n - 1);

}

 

5.程序的主函数如下:

int main() {

int n;

cout << "输入集合A中元素的个数: ";

cin >> n;

 

vector<vector<int>> R(n, vector<int>(n, false));

cout << "输入关系R(0表示没有关系,1表示有关系):" << endl;

for (int i = 0; i < n; i++) {

for (int j = 0; j < n; j++) {

cin >> R[i][j];

}

}

 

if (is_equivalence_relation(R, n)) {

vector<vector<int>> partitions = induce_partitions(R, n);

cout << "给定的关系R构成等价关系。" << endl;

cout << "由R诱导的集合A的划分为:" << endl;

for (int i = 0; i < partitions.size(); i++) {

cout << "{ ";

for (int j = 0; j < partitions[i].size(); j++) {

cout << partitions[i][j] << " ";

}

cout << "}" << endl;

}

}

else {

vector<vector<int>> result = closure(R, n);

cout << "给定的关系R不构成等价关系。" << endl;

cout << "包含R最小的等价关系为:" << endl;

for (int i = 0; i < result.size(); i++) {

for (int j = 0; j < result[i].size(); j++) {

cout << result[i][j] << " ";

}

cout << endl;

}

}

 

cout << "有" << n << "个元素的集合上等价关系的个数为:" << count_equivalence_relations(n) << endl;

return 0;

}

测试用例说明:

测试样例1:

测试样例2:

作者:星尘旅人
1.本网站部分素材来源于网络,仅供大家参考学习,如有侵权,请联系博主删除处理。
2.本网站一切内容不代表本站立场,并不代表本站赞同其观点和对其真实性负责。
3.版权&许可请详阅版权声明
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
下一篇
//音乐播放