Lecture 15. Dynamic Data StructuresListsList HeadersA Simple List ModuleImplementing the List ModuleSorting RevisitedOther Kinds of ListsCopyright 1996 David R. Hanson Computer Science 126, Fall 1996 15-1November 7, 1996 10:22 AMLecture 15. Dynamic Data Structures•Pointers and structures can be used to build data structures that expand and shrink during execution, e.g., lists, stacks, queues, trees, …• Dynamic data structures are constructed using self-referential structure typesstruct node {int value;struct node *link;};Declares a structure type with two fieldsvalue holds a integerlink holds a pointer to a struct nodeThe type struct node is defined in terms of itself — self referencestruct node n1, n2, n3;n1.value = 4;n1.link = &n2;n2.value = 5;n2.link = &n3;n3.value = 6;n3.link = NULL;Builds a singly linked list with 3 nodes holding 4, 5, and 64n1linkvalue5n26NULLn3Copyright 1996 David R. Hanson Computer Science 126, Fall 1996 15-2November 7, 1996 10:22 AMLists•Use a pointer to traverse a list — follow the link fields until you reach NULLstruct node *p;for (p = &n1; p != NULL; p = p->link)4printf("%d\n", p->value); 56• Use emalloc/malloc to allocate as many struct nodes as neededstruct node *newnode = emalloc(sizeof (struct node));newnode->value = 8;newnode->link = NULL;• To add a new node at the end of the list, walk a pointer down to the last nodefor (p = &n1; p->link != NULL; p = p->link);p->link = newnode;4n15 6NULL8NULLnewnodep4n15 6 8NULLCopyright 1996 David R. Hanson Computer Science 126, Fall 1996 15-3November 7, 1996 10:22 AMList Headers•Using a header node often simplifies list manipulationsstruct intlist {struct node *head;struct node *tail;};• Important boundary conditionsstruct intlist alist;alist.head = alist.tail = NULL;creates an empty listso does struct intlist alist = { NULL, NULL };struct node *p = emalloc(sizeof (struct node));p->value = 1;p->link = NULL;alist.head = alist.tail = p;creates a one-node list• List headers can be allocated, too, if you need an arbitrary number of lists (as opposed to a list of arbitrary length)struct intlist *mylist = emalloc(sizeof (struct intlist));NULL64 5linkvaluetailheadNULLNULLalistalistNULL1Copyright 1996 David R. Hanson Computer Science 126, Fall 1996 15-4November 7, 1996 10:22 AMA Simple List Module•The interface defines the list types and list-manipulation functions/* Lists of ints */struct intnode {int value;struct intnode *link;};struct intlist {struct intnode *head;struct intnode *tail;};extern void intlist_addhead(struct intlist *list, int value);/* adds a new node holding value at the beginning of list */extern void intlist_addtail(struct intlist *list, int value);/* Adds a new node holding value at the end of list */extern int intlist_remhead(struct intlist *list);/* Removes the node at the beginning of a non-empty listand returns the value from that node */This interface appears in intlist.h• This kind of interface is an abstract data type because it defines a type and the operations on values of that typeCopyright 1996 David R. Hanson Computer Science 126, Fall 1996 15-5November 7, 1996 10:22 AMImplementing the List Module•The implementation defines the functions specified in the interface/* Implementation of lists of ints */#include <stdlib.h>#include "intlist.h"#include "misc.h"void intlist_addhead(struct intlist *list, int value) { … }void intlist_addtail(struct intlist *list, int value) { … }extern int intlist_remhead(struct intlist *list) { … }This implementation appears in intlist.c• Adding a new node at the head of an intlist — beware boundary conditionsvoid intlist_addhead(struct intlist *list, int value) {struct intnode *p = emalloc(sizeof (struct intnode));p->value = value;if (list->head == NULL) {p->link = NULL;list->head = list->tail = p;} else {p->link = list->head;list->head = p;}}NULLCopyright 1996 David R. Hanson Computer Science 126, Fall 1996 15-6November 7, 1996 10:22 AMImplementing the List Module, cont’dvoid intlist_addtail(struct intlist *list, int value) {struct intnode *p = emalloc(sizeof (struct intnode));p->value = value;p->link = NULL;if (list->tail == NULL)list->head = list->tail = p;else {list->tail->link = p;list->tail = p;}}• When a node is deleted, it is also deallocatedint intlist_remhead(struct intlist *list) {int value;struct intnode *p = list->head;if (list->head == list->tail)list->head = list->tail = NULL;elselist->head = p->link;value = p->value; free(p);free(p); return p->value;Wrong! Why?return value;}NULLNULLCopyright 1996 David R. Hanson Computer Science 126, Fall 1996 15-7November 7, 1996 10:22 AMSorting Revisited•Another way to sort an arbitrary number of integers1. Read them into an intlist, thus determining the number of integers2. Allocate an array3. Pour the integers in the list into the array4. Sort it and print it#include <stdio.h>#include "quicksort.h"#include "intlist.h"#include "misc.h"int main(void) {int i, n, *ptr, x;struct intlist input = { NULL, NULL };for (n = 0; scanf("%d", &x) == 1; n++)intlist_addtail(&input, x);ptr = emalloc(n*sizeof (int));for (i = 0; i < n; i++)ptr[i] = intlist_remhead(&input);quicksort(ptr, 0, n - 1);for (i = 0; i < n; i++)printf("%d\n", ptr[i]);return 0;}Copyright 1996 David R. Hanson Computer Science 126, Fall 1996 15-8November 7, 1996 10:22 AMOther Kinds of Lists•Stacks: Add/remove nodes at only one endpush intlist_addheadpop intlist_remhead• Queues: Add nodes at the tail, remove nodes from the headput intlist_addtailget intlist_remhead• What about intlist_remtail? Need a doubly linked list for efficient removal• Deques: Add/remove nodes at either endpush intlist_addhead put intlist_addtailget intlist_remhead pull
View Full Document