From 870cfe302debd8b711c9aba41fb45767990b058a Mon Sep 17 00:00:00 2001 From: Leonardo Date: Tue, 11 Jun 2019 00:42:11 -0300 Subject: [PATCH] Added more set functions Added is_subset, is_superset, is_proper_subset, is_proper_superset, is_disjointset --- TODO | 2 +- examples/README.md | 14 ++++++ src/hashset.h | 109 ++++++++++++++++++++++++++++++++++++++++++++ src/treeset.h | 110 +++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 234 insertions(+), 1 deletion(-) create mode 100644 examples/README.md diff --git a/TODO b/TODO index 2018593..224148c 100644 --- a/TODO +++ b/TODO @@ -23,8 +23,8 @@ Before 2.0 1.5 OK - Remove PUBLIC and PRIVATE OK - Allow for struct to be a possible data type (instead of just pointer to struct) + OK - Set functions: is_subset, is_proper_subset, is_superset, is_proper_superset, is_disjointset Iterator move and move_to - Set functions: is_subset, is_superset, is_disjointset from_array - Creates a collection with all the elements in a specified array to_array - Creates an array with all the elements inside the collection diff --git a/examples/README.md b/examples/README.md new file mode 100644 index 0000000..b9850a1 --- /dev/null +++ b/examples/README.md @@ -0,0 +1,14 @@ +# Examples + +* deque - DEQUE collection examples +* hashmap - HASHMAP collection examples +* hashset - HASHSET collection examples +* heap - HEAP collection examples +* iterators - Examples of using the collection's iterators +* linkedlist - LINKEDLIST collection examples +* list - LIST collection examples +* others - Other examples, generally more robust and using multiple collections +* queue - QUEUE collection examples +* stack - STACK collection examples +* treemap - TREEMAP collection examples +* treeset - TREESET collection examples diff --git a/src/hashset.h b/src/hashset.h index 2b214b3..7c17358 100644 --- a/src/hashset.h +++ b/src/hashset.h @@ -169,6 +169,11 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, FMOD SNAME *PFX##_intersection(SNAME *_set1_, SNAME *_set2_); \ FMOD SNAME *PFX##_difference(SNAME *_set1_, SNAME *_set2_); \ FMOD SNAME *PFX##_symmetric_difference(SNAME *_set1_, SNAME *_set2_); \ + FMOD bool PFX##_is_subset(SNAME *_set1_, SNAME *_set2_); \ + FMOD bool PFX##_is_superset(SNAME *_set1_, SNAME *_set2_); \ + FMOD bool PFX##_is_proper_subset(SNAME *_set1_, SNAME *_set2_); \ + FMOD bool PFX##_is_proper_superset(SNAME *_set1_, SNAME *_set2_); \ + FMOD bool PFX##_is_disjointset(SNAME *_set1_, SNAME *_set2_); \ \ /* Iterator Functions */ \ /* Iterator Allocation and Deallocation */ \ @@ -506,6 +511,110 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, return _set_r_; \ } \ \ + /* Is _set1_ a subset of _set2_ ? */ \ + /* A set X is a subset of a set Y when: X <= Y */ \ + /* If X is a subset of Y, then Y is a superset of X */ \ + FMOD bool PFX##_is_subset(SNAME *_set1_, SNAME *_set2_) \ + { \ + /* If the cardinality of _set1_ is greater than that of _set2_, then it is safe to */ \ + /* say that _set1_ can't be a subset of _set2_ */ \ + if (PFX##_count(_set1_) > PFX##_count(_set2_)) \ + return false; \ + \ + /* The empty set is a subset of all sets */ \ + if (PFX##_empty(_set1_)) \ + return true; \ + \ + SNAME##_iter iter; \ + \ + PFX##_iter_init(&iter, _set1_); \ + \ + for (PFX##_iter_to_start(&iter); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \ + { \ + V value = PFX##_iter_value(&iter); \ + \ + if (!PFX##_contains(_set2_, value)) \ + return false; \ + } \ + \ + return true; \ + } \ + \ + /* Is _set1_ a superset of _set2_ ? */ \ + /* A set X is a superset of a set Y when: X >= Y */ \ + /* If X is a superset of Y, then Y is a subset of X */ \ + FMOD bool PFX##_is_superset(SNAME *_set1_, SNAME *_set2_) \ + { \ + return PFX##_is_subset(_set2_, _set1_); \ + } \ + \ + /* Is _set1_ a proper subset of _set2_ ? */ \ + /* A set X is a proper subset of a set Y when: X < Y */ \ + /* If X is a proper subset of Y, then Y is a proper superset of X */ \ + FMOD bool PFX##_is_proper_subset(SNAME *_set1_, SNAME *_set2_) \ + { \ + /* If the cardinality of _set1_ is greater than or equal to that of _set2_, then it */ \ + /* is safe to say that _set1_ can't be a proper subset of _set2_ */ \ + if (PFX##_count(_set1_) >= PFX##_count(_set2_)) \ + return false; \ + \ + if (PFX##_empty(_set1_)) \ + { \ + /* The empty set is a proper subset of all non-empty sets */ \ + if (!PFX##_empty(_set2_)) \ + return true; \ + /* The empty set is not a proper subset of itself (this is true for any set) */ \ + else \ + return false; \ + } \ + \ + SNAME##_iter iter; \ + \ + PFX##_iter_init(&iter, _set1_); \ + \ + for (PFX##_iter_to_start(&iter); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \ + { \ + V value = PFX##_iter_value(&iter); \ + \ + if (!PFX##_contains(_set2_, value)) \ + return false; \ + } \ + \ + return true; \ + } \ + \ + /* Is _set1_ a proper superset of _set2_ ? */ \ + /* A set X is a proper superset of a set Y when: X > Y */ \ + /* If X is a proper superset of Y, then Y is a proper subset of X */ \ + FMOD bool PFX##_is_proper_superset(SNAME *_set1_, SNAME *_set2_) \ + { \ + return PFX##_is_proper_subset(_set2_, _set1_); \ + } \ + \ + /* Is _set1_ a disjointset of _set2_ ? */ \ + /* A set X is a disjointset of a set Y if their intersection is empty, that is, if */ \ + /* there are no elements in common between the two */ \ + FMOD bool PFX##_is_disjointset(SNAME *_set1_, SNAME *_set2_) \ + { \ + /* The intersection of an empty set with any other set will result in an empty set */ \ + if (PFX##_empty(_set1_)) \ + return true; \ + \ + SNAME##_iter iter; \ + \ + PFX##_iter_init(&iter, _set1_); \ + \ + for (PFX##_iter_to_start(&iter); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \ + { \ + V value = PFX##_iter_value(&iter); \ + \ + if (PFX##_contains(_set2_, value)) \ + return false; \ + } \ + \ + return true; \ + } \ + \ FMOD SNAME##_iter *PFX##_iter_new(SNAME *target) \ { \ SNAME##_iter *iter = malloc(sizeof(SNAME##_iter)); \ diff --git a/src/treeset.h b/src/treeset.h index b09c879..14ebd7a 100644 --- a/src/treeset.h +++ b/src/treeset.h @@ -120,6 +120,11 @@ FMOD SNAME *PFX##_intersection(SNAME *_set1_, SNAME *_set2_); \ FMOD SNAME *PFX##_difference(SNAME *_set1_, SNAME *_set2_); \ FMOD SNAME *PFX##_symmetric_difference(SNAME *_set1_, SNAME *_set2_); \ + FMOD bool PFX##_is_subset(SNAME *_set1_, SNAME *_set2_); \ + FMOD bool PFX##_is_superset(SNAME *_set1_, SNAME *_set2_); \ + FMOD bool PFX##_is_proper_subset(SNAME *_set1_, SNAME *_set2_); \ + FMOD bool PFX##_is_proper_superset(SNAME *_set1_, SNAME *_set2_); \ + FMOD bool PFX##_is_disjointset(SNAME *_set1_, SNAME *_set2_); \ \ /* Iterator Functions */ \ /* Iterator Allocation and Deallocation */ \ @@ -592,6 +597,111 @@ return _set_r_; \ } \ \ + /* Is _set1_ a subset of _set2_ ? */ \ + /* A set X is a subset of a set Y when: X <= Y */ \ + /* If X is a subset of Y, then Y is a superset of X */ \ + FMOD bool PFX##_is_subset(SNAME *_set1_, SNAME *_set2_) \ + { \ + /* If the cardinality of _set1_ is greater than that of _set2_, then it is safe */ \ + /* to say that _set1_ can't be a subset of _set2_ */ \ + if (PFX##_count(_set1_) > PFX##_count(_set2_)) \ + return false; \ + \ + /* The empty set is a subset of all sets */ \ + if (PFX##_empty(_set1_)) \ + return true; \ + \ + SNAME##_iter iter; \ + \ + PFX##_iter_init(&iter, _set1_); \ + \ + for (PFX##_iter_to_start(&iter); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \ + { \ + V value = PFX##_iter_value(&iter); \ + \ + if (!PFX##_contains(_set2_, value)) \ + return false; \ + } \ + \ + return true; \ + } \ + \ + /* Is _set1_ a superset of _set2_ ? */ \ + /* A set X is a superset of a set Y when: X >= Y */ \ + /* If X is a superset of Y, then Y is a subset of X */ \ + FMOD bool PFX##_is_superset(SNAME *_set1_, SNAME *_set2_) \ + { \ + return PFX##_is_subset(_set2_, _set1_); \ + } \ + \ + /* Is _set1_ a proper subset of _set2_ ? */ \ + /* A set X is a proper subset of a set Y when: X < Y */ \ + /* If X is a proper subset of Y, then Y is a proper superset of X */ \ + FMOD bool PFX##_is_proper_subset(SNAME *_set1_, SNAME *_set2_) \ + { \ + /* If the cardinality of _set1_ is greater than or equal to that of _set2_, then */ \ + /* it is safe to say that _set1_ can't be a proper subset of _set2_ */ \ + if (PFX##_count(_set1_) >= PFX##_count(_set2_)) \ + return false; \ + \ + if (PFX##_empty(_set1_)) \ + { \ + /* The empty set is a proper subset of all non-empty sets */ \ + if (!PFX##_empty(_set2_)) \ + return true; \ + /* The empty set is not a proper subset of itself (this is true for any set) */ \ + else \ + return false; \ + } \ + \ + SNAME##_iter iter; \ + \ + PFX##_iter_init(&iter, _set1_); \ + \ + for (PFX##_iter_to_start(&iter); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \ + { \ + V value = PFX##_iter_value(&iter); \ + \ + if (!PFX##_contains(_set2_, value)) \ + return false; \ + } \ + \ + return true; \ + } \ + \ + /* Is _set1_ a proper superset of _set2_ ? */ \ + /* A set X is a proper superset of a set Y when: X > Y */ \ + /* If X is a proper superset of Y, then Y is a proper subset of X */ \ + FMOD bool PFX##_is_proper_superset(SNAME *_set1_, SNAME *_set2_) \ + { \ + return PFX##_is_proper_subset(_set2_, _set1_); \ + } \ + \ + /* Is _set1_ a disjointset of _set2_ ? */ \ + /* A set X is a disjointset of a set Y if their intersection is empty, that is, if */ \ + /* there are no elements in common between the two */ \ + FMOD bool PFX##_is_disjointset(SNAME *_set1_, SNAME *_set2_) \ + { \ + /* The intersection of an empty set with any other set will result in an empty */ \ + /* set */ \ + if (PFX##_empty(_set1_)) \ + return true; \ + \ + SNAME##_iter iter; \ + \ + PFX##_iter_init(&iter, _set1_); \ + \ + for (PFX##_iter_to_start(&iter); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \ + { \ + V value = PFX##_iter_value(&iter); \ + \ + if (PFX##_contains(_set2_, value)) \ + return false; \ + } \ + \ + return true; \ + } \ + \ FMOD SNAME##_iter *PFX##_iter_new(SNAME *target) \ { \ SNAME##_iter *iter = malloc(sizeof(SNAME##_iter)); \