【實驗目的】編程
掌握二元關係在計算機上的表示方法,並掌握若是斷定關係的性質。ide
【實驗內容】測試
編程判斷一個二元關係是否爲等價關係,若是是,求其商集。flex
例:A={1,2,3,4,5,6,7,8,9,10},R={<x,y>|x、y∈A∧y≡x (mod 5)}判斷R是否等價關係,若是是,求出各等價類。spa
A 上知足 關係的有 : code
<1,1>,<2,2>,<3,3>,<4,4>,<5,5>,<6,6>,<7,7>,<8,8>,<9,9>,<10,10>,blog
<1,6>,<2,7>,<3,8>,<4,9>,<5,10>,it
<6,1>,<7,2>,<8,3>,<9,4>,<10,5>io
【源程序及解析】class
#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("請輸入關係矩陣。\n"); 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("\n商集爲:\n"); 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("}\n"); } int main(void) { init(); // 初始化矩陣 if (judge_R(1)&&judge_S(1)&&judge_T(1)) // 判斷是不是等價關係 // if (judge_R&&judge_S&&judge_T) 怎麼這句沒報錯 show(); // 打印商集 else printf("該二元關係不是等價關係。\n"); 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 } } */
一,等價關係的判斷
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("\n商集爲:\n"); 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("}\n"); }
商集是由等價類組成的集合,由於全部的等價類都是沒有 交集 的,且若 xRy ,則 [x] = [y]
因此咱們先循環 二元關係的域,找出與全部與當前元素 連通的 元素,他們就組成了 一個等價類
再把 用過的元素標記一下,就能夠不用 小心重複了。
============ ========== ========= ======= ======= ===== ==== === == =
我好像是一個在海邊玩耍的孩子,不時爲拾到比一般更光滑的石子或更美麗的貝殼而歡欣鼓舞,
而展示在我面前的是徹底未探明的真理之海。
—— —— 艾薩克·牛頓