/* Integer linked list example. CSE374 22sp and previously. */ #include #include // a single list node struct Node { int val; struct Node * tail; }; // return a new node containing integer x and a null tail field struct Node * int_node(int x) { struct Node * ans = (struct Node*)malloc(sizeof(struct Node)); ans->val = x; ans->tail = NULL; return ans; } // Return a new linked list containing the integers in p[0..len-1] struct Node * from_array(int len, int* p) { struct Node * ans = NULL; int i; for (i = len-1; i >= 0; --i) { struct Node * next = int_node(p[i]); next->tail = ans; ans = next; } return ans; } // free the whole list; better not use any other pointers // to any list elements (and better not have a cicular list) void free_list(struct Node * lst) { while (lst != NULL) { struct Node * next = lst->tail; // must precede next statement free(lst); lst = next; } } // Print lst to stdout void print(struct Node * lst) { printf("\n["); while (lst != NULL) { // could just say while (lst) ... printf(" %d ", lst->val); lst = lst->tail; } printf("]\n"); } // == "x appears in lst" int member(struct Node *lst, int x) { for (; lst != NULL; lst = lst->tail) if (lst->val == x) return 1; return 0; } // length of lst (recursively) int length1(struct Node *lst) { if (lst == NULL) return 0; return 1 + length1(lst->tail); } // length of lst (iteratively) int length2(struct Node *lst) { int ans = 0; while (lst != NULL) { ++ans; lst = lst->tail; } return ans; } // sharing with lst2, copying of lst1 struct Node* append1(struct Node* lst1, struct Node *lst2) { if (lst1 == NULL) return lst2; struct Node * ans = append1(lst1->tail, lst2); struct Node * first = int_node(lst1->val); first->tail = ans; return first; } // sharing with lst2, copying of lst1 struct Node* append2(struct Node*lst1, struct Node *lst2) { if (lst1 == NULL) return lst2; struct Node *result = int_node(lst1->val); struct Node *prev = result; lst1 = lst1->tail; while (lst1 != NULL) { struct Node * first = int_node(lst1->val); prev->tail = first; prev = first; lst1 = lst1->tail; } prev->tail = lst2; return result; } // change lst1; return val only necessary if lst1 is NULL // creates lots of _aliasing_ struct Node* destructive_append(struct Node*lst1, struct Node*lst2) { struct Node* ans; if (lst1 == NULL) return lst2; ans = lst1; while (lst1->tail != NULL) lst1 = lst1->tail; lst1->tail = lst2; return ans; } void test() { int arr1[5] = { 2, 4, 6, 8, 10}; int arr2[3] = { 1, 2, 3}; int arr3[4] = {20, 0, 0, 0}; struct Node * lst1 = from_array(5, arr1); struct Node * lst2 = from_array(3, arr2); struct Node * lst3 = from_array(4, arr3); print(lst1); print(lst2); print(lst3); print(append1(lst1, lst2)); // space leak! print(append2(lst1, lst2)); // space leak! print(lst1); print(lst2); destructive_append(lst1, lst2); // ignore result b/c lst1 not NULL print(lst1); print(lst2); append1(lst1, lst1); destructive_append(lst1, lst1); // An awfully bad idea! Why? // print(lst1); // space-leak: lst1 (cannot call free_list) // not lst2 (now part of lst1) // lst3 (can call free_list) } int main(int argc, char**argv) { test(); return EXIT_SUCCESS; }