APS105 Lists Structures Textbook Chapters 10.1, 10.3, 10.4, 10.6 2 Structures Arrays allow a collection of elements All of the same type How to collect elements of different types? Structures; in C: struct General form: struct <variable declarations> <identifier list>; Example A struct of stock items at a store: struct int itemnumber, quantity; char size; double price; x, y; // x and y are both structs called members, fields, components // they each contain all components 3 1
Declaring Structure Variables Declaring Structure Variables Two structure variables that store information about parts in a warehouse: struct int number; char name[name_len+1]; int on_hand; part1, part2; The members of a structure are stored in memory in the order in which they re declared. Appearance of part1 Assumptions: part1 is located at address 2000. Integers occupy four bytes. NAME_LEN has the value 25. There are no gaps between the members. 5 6 Declaring Structure Variables Each structure represents a new scope. Any names declared in that scope won t conflict with other names in a program. In C terminology, each structure has a separate name space for its members. Declaring Structure Variables For example, the following declarations can appear in the same program: struct int number; char name[name_len+1]; int on_hand; part1, part2; struct char name[name_len+1]; int number; char sex; employee1, employee2; 7 8 2
Initializing Structure Variables A structure declaration may include an initializer: struct int number; char name[name_len+1]; int on_hand; part1 = 528, "Disk drive", 10, part2 = 914, "Printer cable", 5; Appearance of part1 after initialization: Separate Definition from Declaration struct stockitem int itemnumber, quantity; char size; double price; ; struct stockitem x, y; 9 Operations on Structures To access a member within a structure, we write the name of the structure first, then a period, then the name of the member. Statements that display the values of part1 s members: printf("part number: %d\n", part1.number); printf("part name: %s\n", part1.name); printf("quantity on hand: %d\n", part1.on_hand); Operations on Structures Members of structures can appear on the left side of an assignment or as the operand in an increment or decrement expression: part1.number = 258; /* changes part1's part number */ part1.on_hand++; /* increments part1's quantity on hand */ 11 12 3
Structure Types Suppose that a program needs to declare several structure variables with identical members. We need a name that represents a type of structure, not a particular structure variable. Ways to name a structure: Declare a structure tag Use typedef to define a type name Declaring a Structure Tag A structure tag is a name used to identify a particular kind of structure. The declaration of a structure tag named part: struct part int number; char name[name_len+1]; int on_hand; ; Note that a semicolon must follow the right brace. 13 14 Declaring a Structure Tag The part tag can be used to declare variables: struct part part1, part2; We can t drop the word struct: part part1, part2; /*** WRONG ***/ part isn t a type name; without the word struct, it is meaningless. Since structure tags aren t recognized unless preceded by the word struct, they don t conflict with other names used in a program. 15 Declaring a Structure Tag The declaration of a structure tag can be combined with the declaration of structure variables: struct part int number; char name[name_len+1]; int on_hand; part1, part2; 16 4
Declaring a Structure Tag All structures declared to have type struct part are compatible with one another: struct part part1 = 528, "Disk drive", 10; struct part part2; part2 = part1; /* legal; both parts have the same type */ 17 Defining a Structure Type As an alternative to declaring a structure tag, we can use typedef to define a genuine type name. A definition of a type named Part: typedef struct int number; char name[name_len+1]; int on_hand; Part; Part can be used in the same way as the built-in types: Part part1, part2; 18 Defining a Structure Type When it comes time to name a structure, we can usually choose either to declare a structure tag or to use typedef. However, declaring a structure tag is mandatory when the structure is to be used in a linked list (coming up...) More on typedef Can define your own types using typedef! General form: typedef <type> <yourtypename>; Examples: typedef double Real; typedef char * CharPointer; typedef struct stockitem StockItem; StockItem x, y; 19 5
Doing typedef and definition at once: typedef struct stockitem int itemnumber, quantity; char size; double price; StockItem; StockItem x, y; Referencing Struct Members // initialize (optional): StockItem x = 10,1000, M,59.99; // accessing members: x.itemnumber = 11; x.price = 69.99; printf( %d items\n,x.quantity); Structs and Pointers StockItem x; StockItem *p; p = &x; // p points to x // ways to set quantity to 500: x.quantity = 500; (*p).quantity = 500; p->quantity = 500; // p-> is short for (*p). // read this as p s quantity Malloc a Struct (StockItem) StockItem *p = (StockItem *) malloc(sizeof(stockitem)); // set quantity member to 500 p->quantity = 500; 6
Lists 25 Intro A list is a sequence of items can implement lists different ways: a group of variables an array using pointers (as we will see) Typical list operations start a new, empty list insert a new element into the list find an item with a certain value in the list delete an item from the list print the list Abstract Data Type (ADT) A list is an example of an ADT An ADT is a concept there are multiple ways to implement an ADT 26 The Problem with Arrays Insert an item into the middle of the list: 5 3 1 6 2 6 7 0 9 5 3 1 9 6 2 6 7 0 Delete an item from the middle of the list: 5 3 1 6 2 6 7 0 X 5 3 6 2 6 7 0 What if the array isn t big enough? 5 3 1 6 2 6 7 3 8 0 9 Flexible List: Linked List 5 3 1 6 2 6 7 Insert an item into the middle of the list: 5 3 1 6 2 6 7 9 5 3 1 9 6 2 6 7 Delete an item from the middle of the list: 5 3 1 6 2 6 7 X 5 3 6 2 6 7 7
Implementing a Linked List of ints typedef struct node int info; struct node *link; //link to next Node; - Two members: - An int (with information) - A pointer to a type struct node - That is, to another node... Creating a Node As we construct a linked list, we ll create nodes one by one, adding each to the list. Steps involved in creating a node: 1. Allocate memory for the node. 2. Store data in the node. 3. Insert the node into the list. We ll concentrate on the first two steps for now. 30 Creating a Node When we create a node, we ll need a variable that can point to the node temporarily: Node *newnode; We ll use malloc to allocate memory for the new node, saving the return value in a pointer to Node : Node *p = (Node *)malloc(sizeof(node)); newnode now points to a block of memory just large enough to hold a Node structure: 31 Allocating a new Node a function to allocate & initialize a (single) node Node *newnode (int i, Node *np) Node *p = (Node *)malloc(sizeof(node)); if (p == NULL) printf( Error: out of mem!\n ); else p->info = i; //points to member info and p->link = np; // points to member link return p; //with the new values assigned 8
Creating a List: Appending Node * = NULL; Inserting a Node at the Beginning of a Linked List = newnode(5,null); ->link = newnode(3,null); ->link->link =newnode(1,null); It works, but NOT THE WAY TO DO IT!!! Inconvenient One of the advantages of a linked list is that nodes can be added at any point in the list. However, the beginning of a list is the easiest place to insert a node. Suppose that newnode is pointing to the node to be inserted, and MyList is pointing to the first node in the linked list. 34 Creating a List: Adding to the front Node * = NULL; = newnode(1,null); = newnode(3,); = newnode(5,); Create a list with user inputs A function that uses newnode to create a linked list containing numbers entered by the user: Node *read_numbers(void) Node * = NULL; int n; printf("enter a series of integers (0 to terminate): "); for (;;) scanf("%d", &n); if (n == 0) return first; = newnode(n, ); The numbers will be in reverse order within the list. 36 9
Function to Print a List Searching a Linked List void printlist(node *head) Node *current = head; while (current!= NULL) printf( %d\n,current->info); current = current->link; //this increments // printlist() to print Although a while loop can be used to search a list, the for statement is often superior. A loop that visits the nodes in a linked list, using a pointer variable p to keep track of the current node: for (p = first; p!= NULL; p = p->next) A loop of this form can be used in a function that searches a list for an integer n. 38 Searching a Linked List If it finds n, the function will return a pointer to the node containing n; otherwise, it will return a null pointer. An initial version of the function: Node *search_list(node *mylist, int n) struct node *p; for (p = mylist; p!= NULL; p = p->link) if (p->info == n) return p; return NULL; Searching a Linked List There are many other ways to write search_list. One alternative is to eliminate the p variable, instead using list itself to keep track of the current node: struct node *search_list(struct node *, int n) for (;!= NULL; = ->link) if (->info == n) return ; return NULL; Since is a copy of the original list pointer, there s no harm in changing it within the function. 39 40 10
Searching a Linked List Another alternative: Node *search_list(node *, int n) for (;!= NULL && ->info!= n; = ->link) ; return ; Since list is NULL if we reach the end of the list, returning is correct even if we don t find n. Searching a Linked List This version of search_list might be a bit clearer if we used a while statement: struct node *search_list(struct node *, int n) while (!= NULL && ->info!= n) = ->link; return ; 41 42 Function to return true if an item found bool contains(node *head, int item) Node *current = head; bool found = false; while (current &&!found) if (current->info == item) found = true; else current = current->link; return found; Deleting a Node from a Linked List A big advantage of storing data in a linked list is that we can easily delete nodes. Deleting a node involves three steps: 1. Locate the node to be deleted. 2. Alter the previous node so that it bypasses the deleted node. 3. Call free to reclaim the space occupied by the deleted node. Step 1 is harder than it looks, because step 2 requires changing the previous node. There are various solutions to this problem. 44 11
Deleting the First Node of a List Deleting a Node from a Linked List The trailing pointer technique involves keeping a pointer to the previous node (prev) as well as a pointer to the current node (cur). Assume that points to the list to be searched and n is the integer to be deleted. A loop that implements step 1: for (cur =, prev = NULL; cur!= NULL && cur->info!= n; prev = cur, cur = cur->link) ; When the loop terminates, cur points to the node to be deleted and prev points to the previous node. 46 Function to Delete first Node Delete first Node: return new head Careful here. You can t do this! returning void means you re just deleting the head! void deletefirst(node *head) if (head == NULL) printf( Error: deleting empty list\n ); else Node *temp = head; head = head->link; free(temp); // doesn t work! can t modify head Node *deletefirst(node *head) if (head == NULL) printf( Error: del empty list\n ); else Node *temp = head->link; free(head); return temp; // this is a pointer to Node // = deletefirst() now points to what used to be the second node. 12
Function to Delete Entire List Node *deleteall(node *head) while (head) Node *temp = head; head = head->link; free(temp); //delete head means wasted mem!! return NULL; // = deleteall(); Deleting the Last Node of a List Highlight that you have to stop at the second last node, to modify it s link pointer (this pointer always points to the next node; no way to look backwards.) Function to Delete Last Element Node *deletelast(node *head) if (head == NULL) return NULL; if (head->link == NULL) free(head); return NULL; Node *current = head; while (current->link->link) current = current->link; free(current->link); current->link = NULL; return head; // = deletelast(); Inserting into an Ordered List 4 info: 4 Highlight that you have to stop one node early (just like deletelast) OR: maintain a pointer to the previous node have to handle empty and one-node lists 13
Function to Insert into Ordered List Node *insert(node *head, int item) if (head == NULL item < head->info) return newnode(item, head); Node *current = head; while (current->link && (item > current->link->info)) current = current->link; current->link = newnode(item, current->link); return head; // = insert(,4); delete 1 : Deleting first Occurrence delete 3 : info: 4 info: 4 Function to Delete First Occurrence Node *delete(int item, Node *head) if (head == NULL) return NULL; if (head->info == item) // if the first node is to be deleted Node *temp = head->link; free(head); return temp; Node *current = head; bool found = false; while (!found && current->link) if (current->link->info == item) found = true; else current = current->link; if (current->link) // if there exists a node to be deleted Node *temp = current->link; current->link = current->link->link; free(temp); return head; delete 1 : Deleting all Occurrences 14
Function to Delete all Occurrences Node *deleteallmatches (int item, Node *head) while (head && head->info == item) Node *temp = head; head = head->link; free(temp); if (head) Node *current = head; while (current->link) if (current->link->info == item) Node * temp = current->link; current->link = current->link->link; free(temp); else // only advance if no deletion happens current = current->link; return head; Using Recursion on Lists 58 Printing a List using Recursion can think of a list recursively as: a head node plus a list void printlist(node *head) if (head) printf( %d\n,head->info); printlist(head->link); Finding an Item using Recursion bool contains(node *head, int item) if (head == NULL) return false; if (head->info == item) return true; return contains(head->link,item); // printlist(); 15
Compare 2 Lists: true if identical bool identical(node *head1, Node *head2) if ((head1 == NULL) && (head2 == NULL)) return true; if ((head1 == NULL) (head2 == NULL)) return false; if (head1->info!= head2->info) return false; return identical(head1->link,head2->link); Insert into an Ordered List Node *insert(int item, Node *head) if ((head == NULL) (item < head->info)) return newnode(item,head); else return insert(item,head->link); 16