離散數學實驗——集合的運算


實驗一 集合的運算

1.1實驗目的

集合論是一切數學的基礎,也是計算機科學不可或缺的,在數據結構、數據庫理論、開關理論、自動機理論和可計算理論等領域都有廣泛的應用。集合的運算規則是集合論中的重要內容。通過該組實驗,目的是讓學生更加深刻地理解集合的概念和性質,並掌握集合的運算規則等。

1.2實驗內容

1、選用恰當的數據結構實現集合的存儲;(數組、向量)

2、實現集合的基本操作:查找、插入、刪除、輸出;

3、判斷某個元素是否屬於集合;

4、實現集合的基本運算:並、交、差、對稱差運算;

5、判斷兩集合之間的關系:包含、相等;

6、求集合的冪集並輸出。

1.3主要算法思想

  集合的交:

        把需要求交集的集合中的元素全部放在一個新的字符串allElem中,比如A{a,b,c,d}B{a,d,e,f,g},allElem=abcdadefg”。

     然后利用兩次循環計算allElem中的每個字符出現的個數,用InNum記錄。計算完一個字符后,InNum歸零。

     如果InNum=集合的個數,則說明當前元素在所有的集合里,所以輸出當前元素。

//計算交集(多個集合進行計算)
string ListIntersect(string &SelectedList) {
	string NewList="";
	ListAllOutput();
	cout << endl << "請選擇需要求交集的集合:";
	cin >> SelectedList;
	//把所有集合放在一個字符穿里  
	string allElem="";
	for (int i = 0; i < SelectedList.length(); i++) {
		allElem += List[int(SelectedList[i]) - 65];
	}

	//判斷allElem出現了選中集合數量的次數
	for (int i = 0; i < allElem.length(); i++) {
		int InNum = 0;
		for (int j =i; j < allElem.length(); j++) {
			if (allElem[i] == allElem[j])
				InNum++;
		}
		if (InNum == SelectedList.length())
		{
			NewList += allElem[i];
		}
	}
	cout << "交集為";
	return NewList;
}

 

集合的並:

     把需要求並集的集合中的元素全部放在一個新的字符串allElem中,比如A{a,b,c,d}B{a,d,e,f,g},allElem=abcdadefg”。

     然后先利用InNum求出元素在allElem出現的次數,然后依次輸出allElem的元素,如果出現兩次,則只輸出一次。

//計算並集(多個集合進行計算)
string ListUnion(string &SelectedList) {
	string NewList="";
	ListAllOutput();
	cout << endl << "請選擇需要求並集的集合:";
	cin >> SelectedList;
	bool flag;
	//把所有集合放在一個字符穿里  
	string allElem = "";
	for (int i = 0; i < SelectedList.length(); i++) {
		allElem += List[int(SelectedList[i]) - 65];
	}
	//cout << "集合" << SelectedList << "的並集為:{";
	//排除allElem的重復元素就是並集
	for (int i = 0; i < allElem.length(); i++) {
		int InNum = 0;
		flag = true;
		for (int j = i; j < allElem.length(); j++) {
			if (allElem[i] == allElem[j])
				InNum++;
		}
		if (InNum <= 1)
		{
			NewList += allElem[i];
		}
			
	}
	cout << "並集為";
	return NewList;
}

  集合的差:

       輸入:集合名1-集合名2

     利用兩層循環,第一層遍歷集合名1的元素,第二層遍歷集合名2的元素,並判斷集合名1中的元素是否在集合名2中,如果在則不輸出。

//計算差集(也就是相對補集,,兩個集合進行計算)
string ListSubtract(string &SelectedList) {
	while (true) {
		ListAllOutput();
		cout << endl << "注意:求差集集合名順序不能改變"<<endl<<"例如:集合A:{a,b,c,d} B:{c,d,e,f}"<<endl<<"	則A-B={a,b}    B-A={e,f}";
		cout << endl << "請按照 ‘集合名1-集合名2’輸入:";
		cin >> SelectedList;
		if (SelectedList.length() > 3)
			cout << "輸入有誤!請重新輸入!" << endl;
		else
			break;
	}
	int List1Length = List[int(SelectedList[0]) - 65].length();
	int List2Length = List[int(SelectedList[2]) - 65].length();
	string NewList="";//保存
	bool flag;
	//cout << "" << SelectedList << "的集合為:{";
	for (int i = 0; i < List1Length; i++)//循環集合名1的長度
	{
		flag = true;
		for (int j = 0; j < List2Length; j++)//循環集合名2的長度   冒泡遍歷  依次用集合名1的元素跟所有集合名2中的元素比較  有相同則除去
		{
			if (List[int(SelectedList[0]) - 65][i] == List[int(SelectedList[2]) - 65][j])//集合名1中的第i個元素等於集合名2中的第j個元素
			{
				flag = false;
				break;
			}
		}
		if(flag)
			NewList += List[int(SelectedList[0]) - 65][i];

	}
	cout << "差集為";
	return NewList;

}

  

集合的對稱差:

     將求對稱差的集合中的元素全部放在一個新的字符串allElem中。

   定義一個flag,利用兩層循環將allElem中的每個元素於其他元素比較,若相等則是交集就不輸出,若沒有相等的則說明不是交集就輸出。

//計算對稱差(可以多個集合計算)
string ListSymDifference(string& SelectedList) {
	string NewList = "";
	ListAllOutput();
	cout << endl << "請選擇需要求對稱差的集合:";
	cin >> SelectedList;
	bool flag;
	//把所有集合放在一個字符穿里  
	string allElem = "";
	for (int i = 0; i < SelectedList.length(); i++) {
		allElem += List[int(SelectedList[i]) - 65];
	}
	for (int i = 0; i < allElem.length(); i++) {
		flag = true;
		for (int j = 0; j < allElem.length(); j++) {
			if (i == j)
				continue;
			if (allElem[i] == allElem[j])
			{
				flag = false;
				break;
			}
		}
		if (flag) {
			NewList += allElem[i];
		}
	}
	cout << "對稱差為";
	return NewList;
}

  

集合求冪集:

     利用三層循環,第一層循環是計算i元子集。

     第二層循環是計算包含第j個元素的所有i元子集

     第三層循環則是第j個元素的i元子集的所有組合。

//求冪集
void PowerSet() {
	char ListName;//需要求冪集的集合名
	ListAllOutput();
	cout << endl << "請選擇要求冪集的集合:";
	cin >> ListName;
	string PowerSet;//冪集字符串
	int ListLength = List[int(ListName) - 65].length();
	cout << "{{},";//首先輸出空集
	for (int i = 1; i <= ListLength; i++) {//第一層循環是計算幾元子集
		/// <summary>
		/// 第二層循環是計算包含第j+1個元素的所有i元子集
		/// 例如:A{a,b,c,d}  
		/// 當j=0 i=1,則有{a}
		/// 當j=0 i=2,則有{a,b} {a,c} {a,d}
		/// </summary>
		for (int j = 0; j < ListLength; j++) {
			if (j + i > ListLength)
				break;
			//求一元子集直接求
			if (i == 1) {
				cout << "{" << List[int(ListName) - 65][j] << "},";
			}
			else
			{
				//其他元子集利用循環求
				int n = 0;
				for (int k = j + 1; k < ListLength; k++) {
					if (n == 0)
					{
						cout << "{";
						cout << List[int(ListName) - 65][j];
					}
					n++;
					if (n == i)
					{
						k=k-i+1;
						n = 0;
						cout << "},";
						continue;
					}
					else
					{
						cout << "," << List[int(ListName) - 65][k];
					}
				}
				if (i == ListLength)
					cout << "}";
				else
					cout << "},";
			}
		}
	}
	cout << "}";
}

  

完整代碼:

#include<iostream>
#include<string>
using namespace std;
#define MAXSIZE 26

string* List=new string[MAXSIZE];//定義全局集合數組
int ListNum=0;//定義全局變量集合的數量
//創建集合
void ListCreat() {
	if (ListNum >= MAXSIZE) {
		cout << "只能創建26個集合!" << endl;
		return;
	}
	while (true)
	{
		cout << "請輸入" << (char)(ListNum + 65) << "集合的的元素:";//加65是因為A的ASCII值為65讓集合名稱變成字母
		cin >> List[ListNum];
		bool flag;
		for (int j = 0; j < List[ListNum].length(); j++) {
			flag = true;
			for (int k = j + 1; k < List[ListNum].length(); k++) {
				if (List[ListNum][j] == List[ListNum][k])
				{
					flag = false;
					break;
				}
			}
			if (!flag)
				break;
		}
		if (!flag) {
			cout << "集合中不允許存在相同元素!,請重新輸入!" << endl;;
		}
		else
		{
			break;
		}
	}
	++ListNum;
}
/// <summary>
/// 刪除集合  當刪除一個集合時它后面的的集合依次往前
/// 比如 當前有集合 A  B  C  D時,刪除B則C集合變成B集合,D集合變成C集合;
/// 類似於順序表
/// </summary>
void ListDelete() {
	char ListName;
	cout << "請輸入集合的名稱:";
	cin >> ListName;
	if ((int(ListName) - 65) > ListNum)//沒有創建那么多集合
	{
		cout << "沒有該集合!";
	}
	else {
		for (int i = (int(ListName) - 65); i < ListNum; i++) {
			List[i] = List[i + 1];
		}
		--ListNum;
	}
}




//規范化輸出集合,用於集合的基本運算
void StandardOutput(string elems) {
	cout << ":{";
	for (int i = 0; i < elems.length(); i++)
	{
		if (i != elems.length() - 1)
			cout << elems[i] << ",";
		else
			cout << elems[i];
	}
	cout << "}" << endl;
}
//查找
void ElemLocate(char ListName) {
	int ListLength = List[int(ListName) - 65].length();
	char elem;//要查找的元素
	cout << "請輸入要查找的元素:";
	cin >> elem;
	for (int i = 0; i < ListLength; i++) {
		if (List[int(ListName) - 65][i] == elem)
		{
			cout << elem << "是第" << i + 1 << "個元素";
			return;
		}
	}
	cout << "該集合沒有該元素!";
}
//插入,直接在字符串最后面插入
void ElemInsert(char ListName) {
	char elem;//要查找的元素
	cout << "請輸入要插入的元素:";
	cin >> elem;
	List[int(ListName) - 65] += elem;
}
//刪除
void ElemDelete(char ListName) {
	int ListLength = List[int(ListName) - 65].length();
	char elem;//要刪除的元素
	cout << "請輸入要刪除的元素:";
	cin >> elem;

	for (int i = 0; i < ListLength; i++)
	{
		if (List[int(ListName) - 65][i] == elem) {
			List[int(ListName) - 65].erase(i,1);
			return;
		}
	}
	cout << "該集合沒有該元素!";
}
//輸出集合元素
void ListOutput(char ListName) {

		cout << "集合" << ListName<<":{";
	for (int i = 0; i < List[int(ListName) - 65].length(); i++)
	{
		if(i != List[int(ListName)-65].length() - 1)
			cout << List[int(ListName) - 65][i] << ",";
		else
			cout << List[int(ListName) - 65][i];
	}
	cout << "}" << endl;
}
//判斷某個元素是否屬於集合
bool IsBelong(char elem,char ListName) {
	int ListLength = List[int(ListName) - 65].length();
	for (int i = 0; i < ListLength; i++) {
		if (elem == List[int(ListName) - 65][i])
			return true;
	}
	return false;
}
//輸出所有集合
void ListAllOutput() {
	cout << "當前集合有:" << endl;
	for (int i = 0; i < ListNum; i++) {
		cout << "集合" << (char)(i + 65) << ":{";
		for (int j = 0; j < List[i].length(); j++) {
			if (j != List[i].length() - 1)
				cout << List[i][j] << ",";
			else
				cout << List[i][j];
		}
		cout << "}" << endl;
	}
}
#pragma region 集合的基本運算
//計算交集(多個集合進行計算)
string ListIntersect(string &SelectedList) {
	string NewList="";
	ListAllOutput();
	cout << endl << "請選擇需要求交集的集合:";
	cin >> SelectedList;
	//把所有集合放在一個字符穿里  
	string allElem="";
	for (int i = 0; i < SelectedList.length(); i++) {
		allElem += List[int(SelectedList[i]) - 65];
	}

	//判斷allElem出現了選中集合數量的次數
	for (int i = 0; i < allElem.length(); i++) {
		int InNum = 0;
		for (int j =i; j < allElem.length(); j++) {
			if (allElem[i] == allElem[j])
				InNum++;
		}
		if (InNum == SelectedList.length())
		{
			NewList += allElem[i];
		}
	}
	cout << "交集為";
	return NewList;
}
//計算並集(多個集合進行計算)
string ListUnion(string &SelectedList) {
	string NewList="";
	ListAllOutput();
	cout << endl << "請選擇需要求並集的集合:";
	cin >> SelectedList;
	bool flag;
	//把所有集合放在一個字符穿里  
	string allElem = "";
	for (int i = 0; i < SelectedList.length(); i++) {
		allElem += List[int(SelectedList[i]) - 65];
	}
	//cout << "集合" << SelectedList << "的並集為:{";
	//排除allElem的重復元素就是並集
	for (int i = 0; i < allElem.length(); i++) {
		int InNum = 0;
		flag = true;
		for (int j = i; j < allElem.length(); j++) {
			if (allElem[i] == allElem[j])
				InNum++;
		}
		if (InNum <= 1)
		{
			NewList += allElem[i];
		}
			
	}
	cout << "並集為";
	return NewList;
}
//計算差集(也就是相對補集,,兩個集合進行計算)
string ListSubtract(string &SelectedList) {
	while (true) {
		ListAllOutput();
		cout << endl << "注意:求差集集合名順序不能改變"<<endl<<"例如:集合A:{a,b,c,d} B:{c,d,e,f}"<<endl<<"	則A-B={a,b}    B-A={e,f}";
		cout << endl << "請按照 ‘集合名1-集合名2’輸入:";
		cin >> SelectedList;
		if (SelectedList.length() > 3)
			cout << "輸入有誤!請重新輸入!" << endl;
		else
			break;
	}
	int List1Length = List[int(SelectedList[0]) - 65].length();
	int List2Length = List[int(SelectedList[2]) - 65].length();
	string NewList="";//保存
	bool flag;
	//cout << "" << SelectedList << "的集合為:{";
	for (int i = 0; i < List1Length; i++)//循環集合名1的長度
	{
		flag = true;
		for (int j = 0; j < List2Length; j++)//循環集合名2的長度   冒泡遍歷  依次用集合名1的元素跟所有集合名2中的元素比較  有相同則除去
		{
			if (List[int(SelectedList[0]) - 65][i] == List[int(SelectedList[2]) - 65][j])//集合名1中的第i個元素等於集合名2中的第j個元素
			{
				flag = false;
				break;
			}
		}
		if(flag)
			NewList += List[int(SelectedList[0]) - 65][i];

	}
	cout << "差集為";
	return NewList;

}
//計算對稱差(可以多個集合計算)
string ListSymDifference(string& SelectedList) {
	string NewList = "";
	ListAllOutput();
	cout << endl << "請選擇需要求對稱差的集合:";
	cin >> SelectedList;
	bool flag;
	//把所有集合放在一個字符穿里  
	string allElem = "";
	for (int i = 0; i < SelectedList.length(); i++) {
		allElem += List[int(SelectedList[i]) - 65];
	}
	for (int i = 0; i < allElem.length(); i++) {
		flag = true;
		for (int j = 0; j < allElem.length(); j++) {
			if (i == j)
				continue;
			if (allElem[i] == allElem[j])
			{
				flag = false;
				break;
			}
		}
		if (flag) {
			NewList += allElem[i];
		}
	}
	cout << "對稱差為";
	return NewList;
}
//判斷相等(兩個集合進行計算)
bool IsEqual(char& List1, char& List2) {
	ListAllOutput();
	int InNum = 0;
	bool flag=true;
	cout << endl << "請選擇需要判斷的集合(用空號隔開):";
	cin >> List1 >> List2;
	//如果兩個集合的長度不一樣 不可能相同
	if (List[int(List1) - 65].length() != List[int(List2) - 65].length())
		return false;
	for (int i = 0; i < List[int(List1) - 65].length(); i++) {
		for (int j = 0; j < List[int(List2) - 65].length(); j++) {
			if (List[int(List1) - 65][i] == List[int(List2) - 65][j])
			{
				InNum++;
				break;
			}
		}

	}
	if (InNum == List[int(List1) - 65].length())
		return true;
	else
		return false;
}
//判斷是否包含
bool IsContain(char &List1,char &List2) {
	int InNum = 0;//用來判斷集合名1中的元素有幾個在集合名2中 如果InNum=集合名1的長度說明  集合名2中有所有的集合名1的元素  則是包含
	bool flag;
	ListAllOutput();
	cout << endl << "集合名1包含於集合名2";
	cout << endl << "請先輸入集合名1:";
	cin >> List1;
	cout << "請輸入集合名2:";
	cin >> List2;
	//如果集合名1的元素比集合名2中的元素多,則不可能是包含
	if (List[int(List1) - 65].length() > List[int(List2) - 65].length())
		return false;
	for (int i = 0; i < List[int(List1) - 65].length(); i++) {
		flag = false;
		for (int j = 0; j < List[int(List2) - 65].length(); j++) {
			if (List[int(List1) - 65][i] == List[int(List2) - 65][j])
			{
				InNum++;
				break;
			}
		}
	}
	if (InNum == List[int(List1) - 65].length())
		return true;
	else
		return false;
}
#pragma endregion

//求冪集
void PowerSet() {
	char ListName;//需要求冪集的集合名
	ListAllOutput();
	cout << endl << "請選擇要求冪集的集合:";
	cin >> ListName;
	string PowerSet;//冪集字符串
	int ListLength = List[int(ListName) - 65].length();
	cout << "{{},";//首先輸出空集
	for (int i = 1; i <= ListLength; i++) {//第一層循環是計算幾元子集
		/// <summary>
		/// 第二層循環是計算包含第j+1個元素的所有i元子集
		/// 例如:A{a,b,c,d}  
		/// 當j=0 i=1,則有{a}
		/// 當j=0 i=2,則有{a,b} {a,c} {a,d}
		/// </summary>
		for (int j = 0; j < ListLength; j++) {
			if (j + i > ListLength)
				break;
			//求一元子集直接求
			if (i == 1) {
				cout << "{" << List[int(ListName) - 65][j] << "},";
			}
			else
			{
				//其他元子集利用循環求
				int n = 0;
				for (int k = j + 1; k < ListLength; k++) {
					if (n == 0)
					{
						cout << "{";
						cout << List[int(ListName) - 65][j];
					}
					n++;
					if (n == i)
					{
						k=k-i+1;
						n = 0;
						cout << "},";
						continue;
					}
					else
					{
						cout << "," << List[int(ListName) - 65][k];
					}
				}
				if (i == ListLength)
					cout << "}";
				else
					cout << "},";
			}
		}
	}
	cout << "}";
}

void main() {
	int opearateNum = 0;//操作值
	while (true)
	{
		char List1, List2;//用於  判斷包含和相等關系
		cout << "0、創建集合\n1、集合的基本操作\n2、判斷元素是否屬於集合\n3、集合的基本運算\n4、判斷是否包含\n5、判斷是否相等\n6、求冪集\n輸入負數退出\n請輸入:";
		cin >> opearateNum;
		if (opearateNum < 0)
			break;
		switch (opearateNum) {
		case 0:
			ListCreat();
			system("pause");
			system("cls");
			break;
		case 1:
			int opearateNum_2;
			ListAllOutput();
			char ListName;
			cout << "請輸入需要操作的集合的名稱:";
			cin >> ListName;
			while (true) {
				system("cls");
				ListOutput(ListName);
				cout << "1、查找\t2、插入\t3、刪除\t4、輸出\t輸入負數返回\n請輸入:";
				cin >> opearateNum_2;
				if (opearateNum_2 < 0)
					break;
				switch (opearateNum_2)
				{
				case 1:
					ElemLocate(ListName);
					cout << endl;
					system("pause");
					system("cls");
					break;
				case 2:
					ElemInsert(ListName);
					ListOutput(ListName);
					system("pause");
					system("cls");
					break;
				case 3:
					ElemDelete(ListName);
					ListOutput(ListName);
					system("pause");
					system("cls");
					break;
				case 4:
					ListOutput(ListName);
					system("pause");
					system("cls");
					break;
				default:
					cout << "無效操作!";
					break;
				}
			}
			system("pause");
			system("cls");
			break;
		case 2:
			char elem, ListName_2;
			cout << "請輸入元素值和集合名(用空號隔開):";
			cin >> elem >> ListName_2;
			if (IsBelong(elem, ListName_2))
				cout << elem << "屬於集合" << ListName_2 << endl;
			else
				cout << elem << "不屬於集合" << ListName_2 << endl;
			system("pause");
			system("cls");
			break;
		case 3:
			while (true) {
				string SelectedList;
				int opearateNum_3;
				system("cls");
				cout << "1、交\t2、並\t3、差\t4、對稱差\t輸入負數返回\n請輸入:";
				cin >> opearateNum_3;
				if (opearateNum_3 < 0)
					break;
				switch (opearateNum_3)
				{
				case 1:
					StandardOutput(ListIntersect(SelectedList));
					system("pause");
					system("cls");
					break;
				case 2:
					StandardOutput(ListUnion(SelectedList));
					system("pause");
					system("cls");
					break;
				case 3:
					StandardOutput(ListSubtract(SelectedList));
					system("pause");
					system("cls");
					break;
				case 4:
					StandardOutput(ListSymDifference(SelectedList));
					system("pause");
					system("cls");
					break;
				default:
					cout << "無效操作!";
					break;
				}
			}
			system("pause");
			system("cls");
			break;
		case 4:
			if (IsContain(List1, List2))
				cout << List1 << "包含於" << List2; 
			else
				cout << List1 << "不包含於" << List2;
			cout << endl;
			system("pause");
			system("cls");
			break;
		case 5:
			if(IsEqual(List1, List2))
				cout <<"集合"<< List1 << "與" << "集合"<<List2<<"相等";
			else
				cout << "集合" << List1 << "與" << "集合" << List2 << "不相等";
			cout << endl;
			system("pause");
			system("cls");
			break;
		case 6:
			PowerSet();
			system("pause");
			system("cls");
			break;
		default:
			cout << "無效操作!";
			break;
		}

	}
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM