集合论:对关系矩阵的操作(C++)

一、功能及运行结果如下:


二、代码说明

1、关系即为序偶的集合:{ <a, b> , <b, c> , ... },这里采用了set<Order>来表示关系,其中Struct Order是序偶。

2、在Order内部重载"<",定义序偶的大小,保证set容器能插入、查找特定序偶。

三、代码知识点

set容器:embrace操作

结构体:重载"<",含参构造函数,可以作为返回值

四、C++11代码

#include <iostream>
#include <cctype>
#include <set>
#include <map>
#include <cstring>
#include <iomanip>
#define N 30
using namespace std;

//序偶,重载了"<"
struct Order {
	char left, right;
	Order(char u, char v)
	{
		left = u;
		right = v;
	}
	bool operator < (const Order& t) const
	{
		if (left != t.left) return left < t.left;
		return right < t.right;
	}
};

//改写:int printYsh(char a[]) 输入集合A
void inputSet(set<char>& a) {
	string str;
	cin >> str;
	for (auto p : str)
		if (isalnum(p)) a.insert(p);
}

//改写:int inputRelaYsh(char a[][3]) 输入关系序列
void inputRela(set<Order>& r) {
	string str;
	cin >> str;
	for (size_t i = 0; i < str.size(); ++i)
	{
		if (isalnum(str[i]))
		{
			for (size_t j = i + 1; j < str.size(); ++j)
			{
				if (isalnum(str[j]))
				{
					r.emplace(str[i], str[j]);
					i = j;
					break;
				}
			}
		}
	}
}

//改写:int printYsh(char a[]) 打印集合A
void printSet(const set<char>& a) {
	size_t count = 0;
	for (auto p : a)
	{
		++count;
		cout << p;
		if (count != a.size()) cout << ",";
	}
	cout << endl;
}

//改写:int printRelaYsh(char a[][3], int n) 打印关系序列
void printRela(const set<Order>& r) {
	int count = 0;
	for (auto p : r)
	{
		++count;
		cout << "<" << p.left << "," << p.right << ">";
		if (count != r.size()) cout << ",";
	}
	cout << endl;
}

//改写:int printRelaMatrix(int M[][N], int n) 打印关系矩阵
void printMatrix(bool m[][N], int n) {
	for (int i = 0; i < n; ++i)
	{
		for (int j = 0; j < n; ++j)
			cout << setw(4) << m[i][j];
		cout << endl;
	}
}

//改写:void matrixmulti(int M[][100], int R[][N], int T[][N], int n) 矩阵乘法 M *= R
void matrixMulti(bool M[][N], bool R[][N], int rank) {
	bool T[N][N] = { 0 };
	for (int i = 0; i < rank; ++i)
		for (int j = 0; j < rank; ++j)
			for (int k = 0; k < rank; ++k)
				T[i][j] |= (M[i][k] & R[k][j]);
	memcpy(M, T, sizeof(T));
}

//改写:int rPower(char R[][3], char T[][3], int nR, int n, int np) 矩阵的幂次运算
void matrixPow(bool base[][N], int n, int rank, bool res[][N]) {
	memset(res, 0, sizeof(bool) * N * N);
	for (int i = 0; i < rank; ++i)
		res[i][i] = 1;
	while (n)
	{
		if (n & 1) matrixMulti(res, base, rank);
		matrixMulti(base, base, rank);
		n >>= 1;
	}
}

//改写:void rela2matrix(char a[], char R[][3], int nR, int M[][N]) 关系转化为邻接矩阵
void toMatrix(const set<Order>& r, bool m[][N], const set<char>& a) {
	map<char, int> Am;
	int count = 0;
	for (auto p : a)
		Am[p] = count++;
	memset(m, 0, sizeof(bool) * N * N);
	for (auto p : r)
		m[Am[p.left]][Am[p.right]] = 1;
}

//改写:int matrix2rela(char a[], char R[][3], int M[][N]) 邻接矩阵转化为关系
set<Order> toRela(bool m[][N], const set<char>& a) {
	set<Order> r;
	char As[N];
	int count = 0;
	for (auto p : a)
		As[count++] = p;
	for (int i = 0; i < a.size(); ++i)
		for (int j = 0; j < a.size(); ++j)
			if (m[i][j] == 1) r.emplace(As[i], As[j]);
	return r;
}

//改写:int relaCompose(char R[][3], char S[][3], char T[][3], int nR, int nS) 关系的复合
set<Order> relaCompose(const set<Order>& r1, const set<Order>& r2) {
	set<Order> tmp;
	for (auto p : r1)
	{
		for (auto q : r2)
		{
			if (p.right == q.left)
				tmp.emplace(p.left, q.right);
			else if (q.left > p.right)
				break;
		}
	}
	return tmp;
}

//改写:int relaSelf(char a[], char R[][3], int nR, char T[][3]) 自反闭包
set<Order> relaSelf(const set<Order>& r, const set<char>& A) {
	set<Order> tmp(r);
	for (auto p : A)
		tmp.emplace(p, p);
	return tmp;
}

//改写:int relaSym(char R[][3], char T[][3], int nR) 对称闭包
set<Order> relaSym(const set<Order>& r, const set<char>& A) {
	set<Order> tmp(r);
	for (auto p : r)
		if(p.left!=p.right)
			tmp.emplace(p.right, p.left);
	return tmp;
}

//改写:int trorder(char R[][3], char RM[][3], int nR, int n) 传递闭包
void relaTran(set<Order> tmp, const set<char> a) {
	bool res[N][N];
	bool rn[N][N];
	bool r1[N][N];
	toMatrix(tmp, r1, a);
	memcpy(rn, r1, sizeof(r1));
	memcpy(res, r1, sizeof(r1));

	for (int c = 1; c < a.size(); ++c)
	{
		printRela(toRela(rn, a));
		matrixMulti(rn, r1, a.size());

		for (int i = 0; i < a.size(); ++i)
			for (int j = 0; j < a.size(); ++j)
				res[i][j] |= rn[i][j];
	}

	printRela(toRela(res, a));
}

//改写:int trmatrix(int R[][N], int n) warshall算法求传递闭包
void warShall(bool R[][N], int n) {
	for (int j = 0; j < n; ++j)
	{
		for (int i = 0; i < n; ++i)
		{
			if (R[i][j])
			{
				for (int k = 0; k < n; ++k)
					R[i][k] |= R[j][k];
			}
		}
	}
}

int main()
{
	set<Order> R1;
	set<Order> R2;
	set<char> A;
	bool matrix1[N][N];
	bool matrix2[N][N];
	int nChoice;
	int n;
	while (true)
	{
		printf("\n========================\n");
		printf("1...输入相关元素值\n");
		printf("2...R1*R2关系的复合\n");
		printf("3...自反闭包\n");
		printf("4...对称闭包\n");
		printf("5...序偶形式的关系转关系矩阵\n");
		printf("6...利用矩阵求关系的复合\n");
		printf("7...利用序偶形式的复合求传递闭包\n");
		printf("8...利用warshall算法的求传递闭包\n");
		printf("9...R2*R1关系的复合\n");
		printf("10..R1的任意次方\n");
		printf("11..R2的任意次方\n");
		printf("0...退出\n");
		printf("========================\n您的选择: ");
		cin >> nChoice;
		if (nChoice == 0) break;

		if (nChoice == 1)
		{
			printf("输入集合A:");
			inputSet(A);
			printf("输入关系R1:");
			inputRela(R1);
			printf("输入关系R2:");
			inputRela(R2);
			printf("A:");
			printSet(A);
			printf("关系R1:");
			printRela(R1);
			printf("关系R2:");
			printRela(R2);
		}
		else if (nChoice == 2)
		{
			printf("R1@R2:");
			printRela(relaCompose(R1, R2));
		}
		else if (nChoice == 9)
		{
			printf("R2@R1:");
			printRela(relaCompose(R2, R1));
		}
		else if (nChoice == 3)
		{
			cout << "R1的自反闭包:";
			printRela(relaSelf(R1, A));
		}
		else if (nChoice == 4)
		{
			printf("R1的对称闭包:");
			printRela(relaSym(R1, A));
		}
		else if (nChoice == 5)
		{
			printf("R1关系的序偶");
			printRela(R1);
			printf("R1关系的矩阵\n");
			toMatrix(R1, matrix1, A);
			printMatrix(matrix1, A.size());
		}
		else if (nChoice == 6)
		{
			printf("R1关系的矩阵\n");
			toMatrix(R1, matrix1, A);
			printMatrix(matrix1, A.size());
			printf("R2关系的矩阵\n");
			toMatrix(R2, matrix2, A);
			printMatrix(matrix2, A.size());
			printf("复合后的矩阵\n");
			matrixMulti(matrix1, matrix2, A.size());
			printMatrix(matrix1, A.size());
			printf("\n复合后的序偶");
			printRela(toRela(matrix1, A));
		}
		else if (nChoice == 7)
			relaTran(R1, A);
		else if (nChoice == 8)
		{
			printf("R1关系的序偶");
			printRela(R1);
			printf("R1关系中的矩阵\n");
			toMatrix(R1, matrix1, A);
			printMatrix(matrix1, A.size());
			printf("warshall后的矩阵\n");
			warShall(matrix1, A.size());
			printMatrix(matrix1,A.size());
			printf("\n序偶");
			printRela(toRela(matrix1, A));
		}
		else if (nChoice == 10)
		{
			printf("输入n:");
			cin >> n;
			toMatrix(R1, matrix1, A);
			matrixPow(matrix1, n, A.size(), matrix2);
			printf("R1的%d次方:\n", n);
			printMatrix(matrix2, A.size());
			printf("\n转化为序偶\n");
			printRela(toRela(matrix2, A));

		}
		else if (nChoice == 11)
		{
			printf("输入n:");
			cin >> n;
			toMatrix(R2, matrix1, A);
			matrixPow(matrix1, n, A.size(), matrix2);
			printf("R2的%d次方:\n", n);
			printMatrix(matrix2, A.size());
			printf("\n序偶转换为数组\n");
			printRela(toRela(matrix2, A));
		}
	}
	system("pause");
	return 0;
}

猜你喜欢

转载自blog.csdn.net/leelitian3/article/details/80565881