#include #include #include #include /* Write code to remove duplicates from an unsorted linked list. FOLLOW UP How would you solve this problem if a temporary buffer is not allowed? */ struct elt { struct elt *next; int value; }; /* * We could make a struct for this, * but it would have only one component, * so this is quicker. */ typedef struct elt *List; /* insert a new value on the list */ void insert(List *lst, int value) { struct elt *e; e = malloc(sizeof(struct elt)); assert(e); e->value = value; e->next = *lst; //lst = &e; // causes seg fault *lst = e; } int listEmpty(const List *lst) { return (*lst == 0); } void listPrint( List *lst){ struct elt *e; for (e = *lst; e != 0; e = e->next){ printf("%d ", e->value); } printf("\n"); } void listDestroy(List *lst){ struct elt *e; struct elt *last; for (e = *lst; e != 0; e = e->next){ if (last) free(last); last = e; } if (last) free(last); } bool findNode(const List *lst, int val){ struct elt *e; for (e = *lst; e != 0; e = e->next){ if (e == NULL) return false; if (e->value == val) return true; } return false; } void xdeleteNode(List *lst, int val){ struct elt *e; struct elt *tmp; if (e == NULL) return; if (e->value == val) { e->value = e->next->value; tmp = e->next; e->next = e->next->next; free(tmp); } //deleteNode(&e->next, val); } bool deleteNode(List *lst, int val){ struct elt *e; struct elt *tmp; for (e = *lst; e != 0; ){ if (e == NULL) return false; printf("next: %p %d\n", e, e->value); if (e->value == val) { e->value = e->next->value; tmp = e->next; e->next = e->next->next; free(tmp); } e = e->next; } return false; } struct elt *ListDelete(struct elt *currP, int val) { /* See if we are at end of list. */ if (currP == NULL) return NULL; /* * Check to see if current node is one * to be deleted. */ if (currP->value == val) { struct elt *tempNextP; /* Save the next pointer in the node. */ tempNextP = currP->next; /* Deallocate the node. */ //free(currP); /* * Return the NEW pointer to where we * were called from. I.e., the pointer * the previous call will use to "skip * over" the removed node. */ return tempNextP; } /* * Check the rest of the list, fixing the next * pointer in case the next node is the one * removed. */ currP->next = ListDelete(currP->next, val); /* * Return the pointer to where we were called * from. Since we did not remove this node it * will be the same. */ return currP; } void removeDup(List *lst){ struct elt *e; if (lst == NULL) return; for (e = *lst; e != 0; ){ if (e == NULL) return; if (e->next == NULL) return; printf("removedup: %p %d\n", e, e->value); listPrint(lst); e = ListDelete(e, e->value); //deleteNode(&e->next, e->value); e = e->next; } } int main(int argc, char ** argv){ if (argc<2) { fprintf(stderr, "Usage: %s [integers]+\n", argv[0]); exit(1); } List mylist = NULL; int val; for (int i = 1; i < argc; i++){ val = atoi(argv[i]); if (val) { insert(&mylist, val); } } listPrint(&mylist); for (int i = 1; i < 10; i++){ printf("Searching for %d ...%s\n", i, (findNode(&mylist, i)) ? " YES!" : " NO"); } listPrint(&mylist); printf("remove dup...\n"); removeDup(&mylist); listPrint(&mylist); listDestroy(&mylist); }