4/8/14 ¡ Self-referential Structures • A basic data type (building block) for complex data structures such as trees and linked lists. Linked List • Structure tags (i.e. tnode , node ) are required for self-referential structure declarations. typedef struct tnode typedef struct node { { Based on slides from K. N. King and Dianna Xu int x; int x; struct tnode *left; struct node *next; struct tnode *right; } Listnode; Bryn Mawr College } Treenode; CS246 Programming Paradigm Linked Lists Singly and Doubly Linked Lists • A linked list stores a lists of items ( struct s). • A singly linked list has each struct containing only one pointer to the next. • Linked lists are typically unbounded, that is, they can grow infinitely. • A doubly linked list has each struct containing both a pointer to the previous as well as the next • An array is a single consecutive piece of memory, a struct in the list. linked list is made of many pieces. • A linked list offers quick insertion, deletion and reordering of the items. single double head tail head tail • The last node in the list contains a null pointer. • No “ random access ” capability of an array. NULL NULL NULL struct node makenode Node *makenode (int x) { struct node { Node *new; int num; if ( (new = (Node *) malloc( sizeof(Node) ) )!= NULL) { struct node *next; new->num = x; //(*new).num = x; }; //scanf("%d", &new->num); An scanf example new -> next = NULL; typedef struct node Node; } Node *head = NULL; //the list is initially empty else { Node *tail = NULL; printf("Out of memory!\n"); exit(0); } return new; } 1 ¡
4/8/14 ¡ append delete void delete (Node *p) { void append (Node *p) { Node *tmp, *prev; if ((p == head) && (p == tail)) if (head == NULL) { head = tail = NULL; head = p; else if (p == head) tail = p; head = p->next; } else { else { for(tmp=head, prev=NULL; tmp!=p; prev=tmp, tmp=tmp->next); tail->next = p; if (p == tail) tail = p; tail = prev; } prev->next = p->next; } } free(p); } insert_after print/search /* insert a node p after p2 */ void print() { void insert_after (Node *p, Node *p2) { Node *tmp; p->next = p2->next; for (tmp = head; tmp != NULL; tmp = tmp->next) printf("%d ", tmp->num); if (p2 == tail) printf("\n"); tail = p; } Node *search(int x) { p2->next = p; Node *tmp; } for (tmp = head; tmp != NULL; tmp = tmp->next) if (tmp->num == x) return tmp; return NULL; } main clear int main() { void clear() { Node *tmp; Node *tmp, *tmp2; int i; for (tmp = head; tmp != NULL; tmp = tmp2) { for (i = 0; i < 10; i++) { tmp2 = tmp->next; tmp = makenode(i); free(tmp); append(tmp); } } head = tail = NULL; print(); } tmp = makenode(9); insert_after(tmp, head->next->next); • Note that this only works if structure Node does delete(head->next); not contain any other pointers to memory print(); } 2 ¡
4/8/14 ¡ General Purpose Linked Lists General Purpose makenode • void * Lnode *makenode (void *data) { Lnode *new = NULL; • Generic pointer – just a memory address if ((new = (Lnode *) malloc(Lnode)) != NULL) { • Can be casted to any type new->prev = NULL; new->next = NULL; struct llist_node { new->data = data; void *data; struct llist_node *prev; } struct llist_node *next; return new; }; } typedef struct llist_node Lnode; Avoid Memory Leaks Shallow and Deep Copy • There are two ways to make a copy of a linked list • Whenever dynamically allocated storages are in • Shallow copy: use, memory leaks are plentiful o The new list consist of duplicated pointers only • The problem is more evident when complicated data structures are used t1 h1 o Mixing: list of trees, trees of lists, etc o Nesting: list of lists of lists t2 h2 • Deep copy: • When implementing complex data structures, plan o The new list consist of duplicated data as well as pointers your clear / release functions very carefully Pointers to Pointers • A variable can be modified by a function if and only if it is passed by reference/pointer. • If the variable to be modified is a pointer itself, one must pass a pointer to pointer, i.e. one must always add an extra level of referencing. int make_node(Node **new) { *new=(Node *)malloc(sizeof(Node)); if (*new != NULL) return 1; else return 0; } 3 ¡
Recommend
More recommend