我想知道如何检查两个数组的子集和适当的子集。我无法找出检查两个数组子集的逻辑方法。这是我到目前为止所拥有的。
这是我的代码: Sets.h
#ifndef SETS_H
#define SETS_H
using namespace std;
class Sets{
private:
static const int SIZE = 5;
int arr[SIZE];
public:
Sets();
void addElement(int);
int getElement(int);
int getSize();
bool isSubset(Sets);
bool isProper(Sets);
void printSet();
void printOrderedPairs(Sets);
};
#endif
Sets.cpp
#include "Sets.h"
#include <iostream>
using namespace std;
Sets::Sets(){
for (int i = 0; i < SIZE; i++){
arr[i] = -1;
}
}
int Sets::getSize(){
return SIZE;
}
void Sets::addElement(int l){
for (int i = 0; i < SIZE; i++){
if (arr[i] == -1){
arr[i] = l;
break;
}
}
}
int Sets::getElement(int j){
if (j < SIZE){
return (-1);
}
else{
int temp;
temp = arr[j];
return temp;
}
}
bool Sets::isSubset(Sets b){
for (int i = 0; i < SIZE; i++){
for (int j = 0; j < SIZE; j++){
if (arr[i] != b.arr[i]){
return false;
}
}
}
return true;
}
bool Sets::isProper(Sets b){
for (int i = 0; i < SIZE; i++){
for (int j = 0; j < SIZE; j++){
if (arr[i] != b.arr[j]){
return false;
}
}
}
return true;
}
void Sets::printOrderedPairs(Sets b){
cout << "A X B = {";
for (int i = 0; i < SIZE-1; i++){
for (int j = 0; j < SIZE; j++){
cout << "(" << arr[i] << "," << b.arr[j] << ") , ";
}
}
cout << "}";
}
void Sets::printSet(){
cout << "{";
for (int i = 0; i < SIZE; i++){
cout << arr[i] << " ,";
}
cout << "}";
}
TestSets.cpp
#include <iostream>
#include "Sets.h"
using namespace std;
int main(){
Sets a;
Sets b;
a.addElement(1);
a.addElement(3);
a.addElement(5);
a.addElement(7);
a.addElement(9);
b.addElement(1);
b.addElement(3);
b.addElement(5);
b.addElement(7);
b.addElement(9);
cout << "Set A is ";
a.printSet();
cout << endl;
cout << "Set B is ";
b.printSet();
cout << "\n" << endl;
a.printOrderedPairs(b);
cout << "\n" << endl;
if (a.isSubset(b) == true){
cout << "Set B is subset of set A" << endl;
}
else{
cout << "Set B is not a subset of set A" << endl;
}
if (a.isProper(b) == true){
cout << "Set B is proper subset of set A" << endl;
}
else{
cout << "Set B is not a proper subset of set A" << endl;
}
system("PAUSE");
return 0;
}
此时任何帮助都会受到赞赏。提前谢谢。
答案 0 :(得分:0)
检查的方法是集合b是另一个集合的子集,是循环遍历b的每个元素并验证它是否存在于a中。如果两个集合都已排序(例如std::set的情况),则速度会更快。
你的类使用一个int数组(最好使用std::vector代替)固定大小(5,无论出于何种原因)。我认为这应该是使用动态分配的改进。
所以,要检查一个集合是否是一个子集我会建议你:
// a.isSubset(b) check if b is a subset of a
bool Sets::isSubset( const Sets &b ) {
for (int i = 0; i < b.size; i++ ) {
bool is_present = false;
for (int j = 0; j < size; j++ ) {
// b is a subset if all of its element are in a
// so check if any element of b is in a
if ( arr[j] == b.arr[i] ) {
is_present = true;
break;
}
}
if ( !is_present ) return false;
}
return true;
}
// a.isProper(b) check if b is a proper subset of a
bool Sets::isProper( const Sets &b) {
int n_equals = 0;
for (int i = 0; i < b.size; i++) {
bool is_present = false;
for (int j = 0; j < size; j++) {
// b is a prpoper subset if all of its element are in a
// but there exists at least one element of a that is not in b
if ( arr[j] == b.arr[i] ) {
is_present = true;
++n_equals;
break;
}
}
if ( !is_present ) return false;
}
return n_equals < size;
}
你的课程应该相应修改。
的修改
为了获得更好的性能并简化大多数算法,最好使用已排序的容器。例如,两个函数belove可能变为:
// a.isSubset(b) check if b is a subset of a. Requires that both are sorted
bool Sets::isSubset( const Sets &b ) {
for (int i = 0, j = 0; i < b.size; i++ ) {
// scan a, which is sorted
while ( j < size && arr[j] < b.arr[i] ) ++j;
if ( j == size || arr[j] > b.arr[i] )
// There's at least one element of b which not belongs to a
return false;
// b.arr[i] == arr[j], move on
}
// all the element of b are in a too
return true;
}
// a.isProper(b) check if b is a proper subset of a.
// It requires that both are sorted
bool Sets::isProper( const Sets &b ) {
int n_equals = 0;
for (int i = 0, j = 0; i < b.size; i++ ) {
while ( j < size && arr[j] < b.arr[i] ) ++j;
if ( j == size || arr[j] > b.arr[i] )
// b is a prpoper subset if all of its element are in a
// but there exists at least one element of a that is not in b
return false;
++n_equals;
}
return n_equals < size;
}
要强制排序,您只需修改添加元素的功能。我也添加了一些辅助函数:
#include <iostream>
using namespace std;
class Sets{
private:
int size;
int allocated;
int *arr;
// It's way better using a std::vector:
// vector<int> v;
// or you can cheat and use a std::set
public:
Sets();
~Sets();
void addElement(int);
void delElement(int);
int getLowerPos(int);
int getElement(int);
int getSize();
bool doesContain(int);
bool isSubset(const Sets &);
bool isProper(const Sets &);
void printSet();
void printOrderedPairs(const Sets &);
};
Sets::Sets() : size(0), allocated(0), arr(nullptr) { }
Sets::~Sets() {
delete[] arr;
}
int Sets::getSize(){
return size;
}
// Add an element if it isn't already present, keeping the array sorted
void Sets::addElement( int x ) {
int pos = this->getLowerPos(x);
if ( pos < size && arr[pos] == x ) return;
if ( size == allocated ) {
// it's time to expand the array. If it's empty, start from 8
allocated = allocated > 0 ? allocated * 2 : 8;
int *new_arr = new int[allocated];
for ( int i = 0; i < pos; i++ ) {
new_arr[i] = arr[i];
}
for ( int i = size; i > pos; --i ) {
new_arr[i] = arr[i - 1];
}
delete[] arr;
arr = new_arr;
}
else {
for ( int i = size; i > pos; --i ) {
arr[i] = arr[i - 1];
}
}
arr[pos] = x;
++size;
}
// Remove an element from the set if it is present, keeping the array sorted
void Sets::delElement( int x ) {
int pos = this->getLowerPos(x);
if ( pos == size || arr[pos] != x ) return;
// I move the elements and update size only, without deallocation.
--size;
for ( int i = pos; i < size; ++i ) {
arr[i] = arr[i + 1];
}
}
// I guess you want to return the element j of the set or -1 if it's not present
int Sets::getElement( int j ){
// consider using size_t instead of int for indeces or at least unsigned int
if ( j < 0 || j >= size )
// I assume all the elements are positive integers
return -1;
else
// why the temp?
return arr[j];
}
// Find the position of the lowest element in the set such that x <= arr[pos]
// with a binary search. It requires that the array is sorted.
// Return the value size if all the elements are lower then x
int Sets::getLowerPos( int x ) {
int first = 0, count = size - first, step, pos = 0;
while ( count > 0 ) {
step = count / 2;
pos = first + step;
if ( arr[pos] < x ) {
first = ++pos;
count -= step + 1;
}
else
count = step;
}
return first;
}
// Check if x is present in the set with a binary search.
// It requires that the array is sorted
bool Sets::doesContain( int x ) {
int pos = this->getLowerPos(x);
return ( pos != size && arr[pos] == x );
/*
// Or directly with a simple binary search:
int low = 0, high = size - 1, pos;
while ( low <= high ) {
pos = low + (high - low) / 2;
if ( x == arr[pos] )
return true;
else if ( x < arr[pos] )
high = pos - 1;
else
low = pos + 1;
}
return false;
*/
}
// ... isSubset() and isProper() as above ...
void Sets::printOrderedPairs( const Sets &b){
cout << "A X B = {";
for (int i = 0; i < size; i++){
for (int j = 0; j < b.size; j++){
cout << '(' << arr[i] << ", " << b.arr[j] << "), ";
}
}
cout << "\b\b} ";
}
void Sets::printSet(){
cout << '{';
for (int i = 0; i < size; i++){
cout << arr[i] << ", ";
}
cout << "\b\b} ";
}
int main(void) {
try {
Sets a;
Sets b;
a.addElement(9);
a.addElement(3);
a.addElement(7);
a.addElement(5);
a.addElement(1);
b.addElement(3);
b.addElement(7);
b.addElement(1);
b.addElement(5);
cout << "Set A is ";
a.printSet();
cout << "\nSet B is ";
b.printSet();
cout << "\n\n";
a.printOrderedPairs(b);
cout << "\n\n";
if ( a.isSubset(b) ) {
cout << "Set B is a subset of set A\n";
}
else {
cout << "Set B is not a subset of set A\n";
}
if ( a.isProper(b) ){
cout << "Set B is a proper subset of set A\n";
}
else{
cout << "Set B is not a proper subset of set A\n";
}
system("PAUSE");
}
catch ( const bad_alloc& e) {
cout << "Allocation failed: " << e.what() << '\n';
}
return 0;
}
现在输出是:
Set A is {1, 3, 5, 7, 9}
Set B is {1, 3, 5, 7}
A X B = {(1, 1), (1, 3), (1, 5), (1, 7), (3, 1), (3, 3), (3, 5), (3, 7), (5, 1), (5, 3), (5, 5), (5, 7), (7, 1), (7, 3), (7, 5), (7, 7), (9, 1), (9, 3), (9, 5), (9, 7)}
Set B is subset of set A
Set B is proper subset of set A