stList *stSet_getKeys(stSet *set) { stList *list = stList_construct(); stSetIterator *iterator = stSet_getIterator(set); void *item; while ((item = stSet_getNext(iterator)) != NULL) { stList_append(list, item); } stSet_destructIterator(iterator); return list; }
stSet *stSet_getUnion(stSet *set1, stSet *set2) { stSet_verifySetsHaveSameFunctions(set1, set2); stSet *set3 = stSet_construct3(stSet_getHashFunction(set1), stSet_getEqualityFunction(set1), NULL); // Add everything stSetIterator *sit= stSet_getIterator(set1); void *o; while ((o = stSet_getNext(sit)) != NULL) { stSet_insert(set3, o); } stSet_destructIterator(sit); sit = stSet_getIterator(set2); while ((o = stSet_getNext(sit)) != NULL) { stSet_insert(set3, o); } stSet_destructIterator(sit); return set3; }
static void test_stSet_testIterator(CuTest *testCase) { testSetup(); stSetIterator *iterator = stSet_getIterator(set0); stSetIterator *iteratorCopy = stSet_copyIterator(iterator); int64_t i = 0; stSet *seen = stSet_construct(); for (i = 0; i < 6; i++) { void *o = stSet_getNext(iterator); CuAssertTrue(testCase, o != NULL); CuAssertTrue(testCase, stSet_search(set0, o) != NULL); CuAssertTrue(testCase, stSet_search(seen, o) == NULL); CuAssertTrue(testCase, stSet_getNext(iteratorCopy) == o); stSet_insert(seen, o); } CuAssertTrue(testCase, stSet_getNext(iterator) == NULL); CuAssertTrue(testCase, stSet_getNext(iterator) == NULL); CuAssertTrue(testCase, stSet_getNext(iteratorCopy) == NULL); stSet_destruct(seen); stSet_destructIterator(iterator); stSet_destructIterator(iteratorCopy); testTeardown(); }
stSet *stSet_getDifference(stSet *set1, stSet *set2) { stSet_verifySetsHaveSameFunctions(set1, set2); stSet *set3 = stSet_construct3(stSet_getHashFunction(set1), stSet_getEqualityFunction(set1), NULL); // Add those from set1 only if they are not in set2 stSetIterator *sit= stSet_getIterator(set1); void *o; while ((o = stSet_getNext(sit)) != NULL) { if (stSet_search(set2, o) == NULL) { stSet_insert(set3, o); } } stSet_destructIterator(sit); return set3; }
static void test_stSet_getIntersection(CuTest* testCase) { testSetup(); // Check intersection of empty sets is empty stSet *set2 = stSet_construct(); stSet *set3 = stSet_construct(); stSet *set4 = stSet_getIntersection(set2, set3); CuAssertTrue(testCase, stSet_size(set4) == 0); stSet_destruct(set2); stSet_destruct(set3); stSet_destruct(set4); // Check intersection of non empty set and empty set is empy set2 = stSet_construct(); set3 = stSet_getIntersection(set0, set2); CuAssertTrue(testCase, stSet_size(set3) == 0); stSet_destruct(set2); stSet_destruct(set3); // Check intersection of two non-empty overlapping sets is correct set2 = stSet_construct(); set3 = stSet_construct(); stIntTuple **uniqs = (stIntTuple **) st_malloc(sizeof(*uniqs) * 4); uniqs[0] = stIntTuple_construct2(9, 0); uniqs[1] = stIntTuple_construct2(9, 1); uniqs[2] = stIntTuple_construct2(9, 2); uniqs[3] = stIntTuple_construct2(9, 3); stIntTuple **common = (stIntTuple **) st_malloc(sizeof(*uniqs) * 5); common[0] = stIntTuple_construct2(5, 0); common[1] = stIntTuple_construct2(5, 1); common[2] = stIntTuple_construct2(5, 2); common[3] = stIntTuple_construct2(5, 3); common[4] = stIntTuple_construct2(5, 4); for (int i = 0; i < 5; ++i) { stSet_insert(set2, common[i]); stSet_insert(set3, common[i]); } stSet_insert(set2, uniqs[0]); stSet_insert(set2, uniqs[1]); stSet_insert(set3, uniqs[2]); stSet_insert(set3, uniqs[3]); set4 = stSet_getIntersection(set2, set3); CuAssertTrue(testCase, stSet_size(set4) == 5); stSetIterator *sit = stSet_getIterator(set4); stIntTuple *itup; while ((itup = stSet_getNext(sit)) != NULL) { CuAssertTrue(testCase, stSet_search(set2, itup) != NULL); CuAssertTrue(testCase, stSet_search(set3, itup) != NULL); } for (int i = 0; i < 4; ++i) { CuAssertTrue(testCase, stSet_search(set4, uniqs[i]) == NULL); } stSet_destructIterator(sit); stSet_destruct(set2); stSet_destruct(set3); stSet_destruct(set4); // Check we get an exception with sets with different functions. stTry { stSet_getIntersection(set0, set1); } stCatch(except) { CuAssertTrue(testCase, stExcept_getId(except) == SET_EXCEPTION_ID); } stTryEnd testTeardown(); }
void *stNaiveConnectedComponentNodeIterator_getNext(stNaiveConnectedComponentNodeIterator *it) { return stSet_getNext(it->it); }
// Compute the connected components, if they haven't been computed // already since the last modification. static void computeConnectedComponents(stNaiveConnectivity *connectivity) { if (connectivity->connectedComponentCache != NULL) { // Already computed the connected components. return; } stHashIterator *nodeIt = stHash_getIterator(connectivity->nodesToAdjList); void *node; stNaiveConnectedComponent *componentsHead = NULL; while ((node = stHash_getNext(nodeIt)) != NULL) { stSet *myNodeSet = stSet_construct(); stSet_insert(myNodeSet, node); struct adjacency *adjList = stHash_search(connectivity->nodesToAdjList, node); if (adjList != NULL) { while (adjList != NULL) { stSet_insert(myNodeSet, adjList->toNode); adjList = adjList->next; } } // Now go through the existing connected components and see if // this overlaps any of them. If it's not a full overlap, then // this set becomes the union, and we continue looking for // additional overlaps, then this becomes a new connected // component. If we find that this is a subset of an existing // component, we can quit early, since we can't possibly add // to it or any others. stNaiveConnectedComponent *curComponent = componentsHead; while (curComponent != NULL) { stNaiveConnectedComponent *next = curComponent->next; // Find out whether our node set is a subset of this // connected component, or if it shares any overlap. bool isSubset = true; bool overlap = false; stSetIterator *myNodeIt = stSet_getIterator(myNodeSet); void *node; while ((node = stSet_getNext(myNodeIt)) != NULL) { if (stSet_search(curComponent->nodes, node)) { overlap = true; } else { isSubset = false; } } stSet_destructIterator(myNodeIt); if (isSubset) { assert(overlap == true); // Quit early. stSet_destruct(myNodeSet); myNodeSet = NULL; break; } else if (overlap) { stSet *newNodeSet = stSet_getUnion(myNodeSet, curComponent->nodes); stSet_destruct(myNodeSet); removeComponent(&componentsHead, curComponent); myNodeSet = newNodeSet; } curComponent = next; } if (myNodeSet != NULL) { // We have a new (or possibly merged) connected component to // add to the list. stNaiveConnectedComponent *newComponent = malloc(sizeof(stNaiveConnectedComponent)); newComponent->nodes = myNodeSet; newComponent->next = componentsHead; componentsHead = newComponent; } } stHash_destructIterator(nodeIt); connectivity->connectedComponentCache = componentsHead; }