zoukankan      html  css  js  c++  java
  • 离散实验——二元关系及其性质

    【实验目的】

    掌握二元关系在计算机上的表示方法,并掌握如果判定关系的性质。

    【实验内容】

    编程判断一个二元关系是否为等价关系,如果是,求其商集。

    例:A={1,2,3,4,5,6,7,8,9,10},R={<x,y>|x、y∈A∧y≡x (mod 5)}判断R是否等价关系,如果是,求出各等价类。

    A 上满足 关系的有 : 

    <1,1>,<2,2>,<3,3>,<4,4>,<5,5>,<6,6>,<7,7>,<8,8>,<9,9>,<10,10>,

    <1,6>,<2,7>,<3,8>,<4,9>,<5,10>,

    <6,1>,<7,2>,<8,3>,<9,4>,<10,5>

     

    【源程序及解析】

    #define _CRT_SECURE_NO_WARNINGS
    #include<stdio.h>
    #include<stdlib.h>
    #define N 10086
    int a[N][N], n;
    void init()
    {
        printf("请输入二元关系的域的个数:");
        scanf("%d", &n);
        printf("请输入关系矩阵。
    ");
        for (int i = 0; i < n; i++){
            for (int j = 0; j < n; j++){
                scanf("%d", &a[i][j]);
            }
        }
    }
    int judge_R(int flag)   // 判断是不是 自反关系
    {
        for (int i = 0; i < n&&flag; i++)
            if (a[i][i] == 0)
                flag = 0;
        if (flag)
            return 1;
        return 0;
    }
    int judge_S(int flag)   // 判断是不是 对称关系
    {
        for (int i = 0; i < n; i++)
            for (int j = 0; j < n; j++)
                if (a[i][j] && !a[j][i])
                    flag = 0;
        if (flag)
            return 1;
        return 0;
    }
    int judge_T(int flag)   // 判断是不是 传递关系
    {
        for (int i = 0; i < n&&flag; i++)
            for (int j = 0; j < n&&flag; j++)
                for (int k = 0; k < n&&flag; k++)
                    if (a[i][j] && a[j][k] && !a[i][k])
                        flag = 0;
        if (flag)
            return 1;
        return 0;
    }
    void show()
    {
        int fld[N];  // 二元关系的 域
        for (int i = 0; i < n; i++)
            fld[i] = i + 1;   // i 代表第 i 个元素
    
        printf("
    商集为:
    ");
        printf("{ ");
        for (int i = 0; i < n; i++)   //循环所有元素
        {
            if (fld[i])   // 如果当前元素 所属的等价类 还没打印出来
            {
                printf("{ ");
                for (int j = 0; j < n; j++)
                {
                    if (a[i][j] && fld[j])  //  如果与当前元素连通的元素 所属的等价类 还没打印出来
                    {
                        printf("%d ", fld[j]);
                        fld[j] = 0;   // 标记 用过的元素,至于 i,因为不会重复循环,所以不用 标记
                    }
                }
                printf("} ");
            }
        }
        printf("}
    ");
    }
    int main(void)
    {
        init();   // 初始化矩阵
       
        if (judge_R(1)&&judge_S(1)&&judge_T(1))  // 判断是否是等价关系
            // if (judge_R&&judge_S&&judge_T)  怎么这句没报错
            show();    // 打印商集
        else
            printf("该二元关系不是等价关系。
    ");
    
        system("pause");
        return 0;
    }
    /*测试数据:
    10
    1 0 0 0 0 1 0 0 0 0
    0 1 0 0 0 0 1 0 0 0
    0 0 1 0 0 0 0 1 0 0
    0 0 0 1 0 0 0 0 1 0
    0 0 0 0 1 0 0 0 0 1
    1 0 0 0 0 1 0 0 0 0 
    0 1 0 0 0 0 1 0 0 0 
    0 0 1 0 0 0 0 1 0 0
    0 0 0 1 0 0 0 0 1 0 
    0 0 0 0 1 0 0 0 0 1 
    
    结果为:
    商集为:
    { { 1 6 } { 2 7 } { 3 8 } { 4 9 } { 5 10 } }
    */
    View Code

     一,等价关系的判断

    1,自反性 (Reflexve) 的判断 

    若 关系矩阵 主对角线上的元素都是 1,则 R 具有自反性

    int judge_R(int flag)   // 判断是不是 自反关系
    {
    	for (int i = 0; i < n&&flag; i++)
    		if (a[i][i] == 0)
    			flag = 0;
    	if (flag)
    		return 1;
    	return 0;
    }
    

    2,对称关系 ( Symmetric)  的判断

    若 关系矩阵 a [ i] [ j ] == a [ j ] [ i ],则 R 具有对称性

    int judge_S(int flag)   // 判断是不是 对称关系
    {
    	for (int i = 0; i < n; i++)
    		for (int j = 0; j < n; j++)
    			if (a[i][j] && !a[j][i])
    				flag = 0;
    	if (flag)
    		return 1;
    	return 0;
    }
    

      

    3,传递性(Transitive)的判断

    若 关系矩阵 对任意的存在 i 通过 j 到达  k  的路径,都有 i 直接到达  k 的路径,则 R 具有 传递性

    即 如果 a[i][j] ==1, a[j][k] ==1,则 a[i][k] ==1

    int judge_T(int flag)   // 判断是不是 传递关系
    {
    	for (int i = 0; i < n&&flag; i++)
    		for (int j = 0; j < n&&flag; j++)
    			for (int k = 0; k < n&&flag; k++)
    				if (a[i][j] && a[j][k] && !a[i][k])
    					flag = 0;
    	if (flag)
    		return 1;
    	return 0;
    }
    

      

     二,商集的求法

    void show()
    {
    	int fld[N];  // 二元关系的 域
    	for (int i = 0; i < n; i++)
    		fld[i] = i + 1;   // i 代表第 i 个元素
    
    	printf("
    商集为:
    ");
    	printf("{ ");
    	for (int i = 0; i < n; i++)   //循环所有元素
    	{
    		if (fld[i])   // 如果当前元素 所属的等价类 还没打印出来
    		{
    			printf("{ ");
    			for (int j = 0; j < n; j++)
    			{
    				if (a[i][j] && fld[j])  //  如果与当前元素连通的元素 所属的等价类 还没打印出来
    				{
    					printf("%d ", fld[j]);
    					fld[j] = 0;   // 标记 用过的元素,至于 i,因为不会重复循环,所以不用 标记
    				}
    			}
    			printf("} ");
    		}
    	}
    	printf("}
    ");
    }
    

    商集是由等价类组成的集合,因为所有的等价类都是没有 交集 的,且若 xRy ,则 [x] = [y]

    所以我们先循环 二元关系的域,找出与所有与当前元素 连通的 元素,他们就组成了 一个等价类

    再把 用过的元素标记一下,就可以不用 当心重复了。

      

    ============ ========== ========= ======= ======= ===== ==== === == =

    我好像是一个在海边玩耍的孩子,不时为拾到比通常更光滑的石子或更美丽的贝壳而欢欣鼓舞,

    而展现在我面前的是完全未探明的真理之海。

                              —— —— 艾萨克·牛顿

     

     

     

     

  • 相关阅读:
    Ubuntu里Eclipse关联Jdk
    解决Ubuntu自带编译器不好使问题
    Ubuntu英文变为中文
    两个VirtualBox版本装的语言不一样?
    Hadoop-2.0 目录简介
    Eclipse项目里面看源码和文档
    Eclipse搭建Struts2环境
    2017,崭新的一年!
    cl-closure-template 中文乱码的解决方法
    common-list基础知识--多值的返回与接收
  • 原文地址:https://www.cnblogs.com/asdfknjhu/p/13046893.html
Copyright © 2011-2022 走看看