Example #1
0
//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
}
Example #2
0
//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;
}