//insert avoids duplicates as stated in the reqs // since duplicates are important for the word frequency I made it return a special error code of 2 int SLInsert(SortedListPtr list, void *newObj){ if(list == NULL){ printf("List was not allocated properly\n"); return 0; } else{ //allocate a temporary node, which will be inserted into the list if its valid, free'd if its a duplicate //each parameter is explained in the header file NodePtr tempNode = (NodePtr) malloc(sizeof(struct Node)); tempNode->data = newObj; tempNode->next = NULL; tempNode->numPointers = 0; tempNode->isValid = true; if(list->head == NULL){ //if this is the first item to be added to the list list->head = tempNode; //simply make it the head of the list } else if(list->head->next == NULL){ //there is only 1 item in the list if(list->comparator(list->head->data, newObj) == 0){ //same as head free(tempNode); //don't need it to store data return 2; } else if(list->comparator(list->head->data, newObj) < 0){ //new object is smaller (it becomes second on list) list->head->next = tempNode; return 1; } else{ //new object is larger, it becomes the head tempNode->next = list->head; list->head = tempNode; return 1; } } else{ //there are at least 2 items in the list if(list->comparator(list->head->data, newObj) == 0){ //since the loop beggins on second object we must check it against head first list->destroyer(tempNode->data); free(tempNode); //don't need it to store data return 2; } else if(list->comparator(list->head->data, newObj) > 0){ //if object is larger than head it becomes head tempNode->next = list->head; list->head = tempNode; return 1; } NodePtr traverse = list->head->next; NodePtr lagging = list->head; while(traverse != NULL){ if(list->comparator(traverse->data, newObj) == 0){ //duplicate list->destroyer(tempNode->data); free(tempNode); //don't need it to store data return 2; //duplicate error } else if(list->comparator(traverse->data, newObj) < 0){ //new object is smaller (it goes towards end of list) lagging = traverse; traverse = traverse->next; } else{ //new object is larger (add it to this spot) tempNode->next = traverse; lagging->next = tempNode; return 1; } } if(list->comparator(lagging->data, newObj) < 0){ //tests one more time, if smaller than last item, adds to the end of the list lagging->next = tempNode; return 1; } } } return 1; //makes compiler happy }
//also acts as a sort of garbage collection, when looking for newObj, it looks for invalid objects with no pointers to free the node int SLRemove(SortedListPtr list, void *newObj){ //base cases, avoids segfault if(list == NULL){ printf("List was not allocated properly\n"); return 0; } else if(list->head == NULL){ printf("List is empty\n"); return 0; } //checks against head else if(list->comparator(list->head->data, newObj) == 0){ if(list->head->numPointers == 0){ NodePtr tempNode = list->head; //must save node to be freed list->head = list->head->next; //update head list->destroyer(tempNode->data); free(tempNode); return 1; } else{ if(!list->head->isValid){ //if item was already removed but still has a pointer printf("Item was not found\n"); return 0; } list->head->isValid = false; return 1; } } else { NodePtr lagging = list->head; NodePtr traverse = list->head->next; while(traverse != NULL) { //garbage collection !!TEST GARBAGE COLLECTION MAKE SURE IT WORKS PROPERLY if(!(traverse->isValid) && (traverse->numPointers == 0)){ lagging->next = traverse->next; list->destroyer(traverse->data); free(traverse); traverse = lagging->next; } if(list->comparator(traverse->data, newObj) == 0) { if(traverse->numPointers == 0){ lagging->next = traverse->next; list->destroyer(traverse->data); free(traverse); return 1; } else{ if(!traverse->isValid){ //if item was already removed but still has a pointer printf("Item was not found\n"); return 0; } traverse->isValid = false; return 1; } } lagging = traverse; traverse = traverse->next; } } //garbage collection for first item, done last so parsing isn't affected !!TEST THIS CASE AS WELL if(!(list->head->isValid) && (list->head->numPointers == 0)){ NodePtr oldHead = list->head; //keep track of the old head to be free'd list->head = list->head->next; list->destroyer(oldHead->data); free(oldHead); } printf("Item was not found\n"); return 0; }