實驗一 集合的運算
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; } } }