Upload
natalie-dean
View
218
Download
1
Embed Size (px)
Citation preview
1
Objectives of these slides:
to describe linked lists in C
6 – Lists6 – Lists
22
Overview
1. List Data Structures and Operations
2. List Implementations
3. Dynamically Created Lists
4. Converting a String to a List
5. List Functions
33
1. List Data Structures and Operations
Some possible operations:
• create/destroy a list
• test to see if a list is empty
• return the tail of the list
• insert/delete elements
• print a list
• calculate the length of a list
44
2. List implementations
Version 1:
#define N 1000 /* the size of the list */
typedef char LIST[N];
LIST lt; /* same as char lt[N] */
55
Version 2
struct listnode { char data; struct listnode *nextptr;};
typedef struct listnode LISTNODE;
LISTNODE elem;
elem
data nextptr
66
Use
LISTNODE a, b, c;
a.data = 'a';b.data = 'c';c.data = 'e';
a.nextptr = b.nextptr = c.nextptr = NULL;
continued
a b c
77
a.nextptr = &b;b.nextptr = &c;
printf("%c", a.nextptr->data);/* 'c' printed */
printf("%c", a.nextptr->nextptr->data);/* 'e' printed */
a b c
NULL‘a’ ‘c’ ‘e’
88
3. Dynamically Created Lists
/* list implementation as before */typedef LISTNODE *LNP;
LNP head = NULL;head = malloc(sizeof(LISTNODE));head->data = 'n';head->nextptr = NULL;
Function prototype in stdlib.h: void *malloc(size_t size);
head ‘n’ NULL
99
Add a second element
head->nextptr = malloc(sizeof(LISTNODE));
head->nextptr->data = 'e';
head->nextptr->nextptr = NULL;
head ‘n’ ‘e’ NULL
1010
Add a third element
head->nextptr->nextptr = malloc(sizeof(LISTNODE));
head->nextptr->nextptr->data = 'w';
head->nextptr->nextptr->nextptr = NULL;
head ‘n’ ‘e’ ‘w’ NULL
1111
4. Converting a String to a List
#include <stdio.h>#include <stdlib.h>/* list type implementation */
LNP string_to_list(char []);
int main(){ LNP h = NULL; h = string_to_list("AB"); return 0;}
/* implementation of string_to_list() */
1212
LNP string_to_list(char s[]){ LNP head = NULL, tail; int i; if (s[0] != '\0') { head = malloc(sizeof(LISTNODE)); head->data = s[0]; tail = head; for (i=1; s[i] != '\0'; i++){ tail->nextptr =
malloc(sizeof(LISTNODE)); tail = tail->nextptr; tail->data = s[i]; } tail->nextptr = NULL; /* list end */ } return head;}
1313
string_to_list("AB")
head = malloc(sizeof(LISTNODE));
head->data = s[0];
tail = head;
head
‘A’tail
‘?’
1414
tail->nextptr = malloc(sizeof(LISTNODE));
head
‘A’tail
‘?’‘?’
1515
tail = tail->nextptr;
tail->data = s[i]; /* i = 1 here */
head
‘A’
tail
‘?’‘B’
1616
s[2] = '\0‘;/* so end of list is assigned NULL */
head
‘A’
tail
NULL‘B’
1717
5. List Functions
5.1. Empty Lists
5.2. Return the First Element of a List
5.3. Produce the Tail of a List
5.4. Put an Element on the Front of a List
5.5. Insertion
continued
1818
5.6. Deletion
5.7. List Membership
5.8. Print a List
5.9. List Length
5.10. Concatenate Two Lists
1919
5.1. Empty Lists
Make an empty list:
LNP h1;h1 = NULL;
Test for emptiness:
int isempty(LNP sptr){ return (sptr == NULL);}
2020
5.2. Return the First Element of a List
char first(LNP cptr){ if (isempty(cptr)) return '\0‘; else return cptr->data;}
2121
Use
LNP head;char c;
head = string_to_list("new");c = first(head);
/* c is 'n'; head is not altered */
2222
5.3. Produce the tail of a list
void tail(LNP *cptr){ LNP temp; if (isempty(*cptr)) printf("The list is empty.\n\n"); else { temp = *cptr; *cptr = (*cptr)->nextptr; free(temp); }}
cptr is the address of a pointer, so that the pointer can be modified using "call by reference".
2323
Use
LNP head;
head = string_to_list("new"); :tail(&head);
/* head is now the list version of “ew” */
2424
5.4. Put an Element on the List Front
LNP cons(char c, LNP cptr){ LNP temp; temp = malloc(sizeof(LISTNODE)); temp->data = c; temp->nextptr = cptr; return temp;}
2525
Use
LNP h1, h2;
h1 = string_to_list("ew");
h2 = cons('n', h1);
Before the cons() call:
h1‘e’ ‘w’ NULL
2626
After:
h2‘n’ ‘e’ ‘w’ NULL
h1
2727
5.5. Insertion
Before:
head‘n’ ‘w’
previousptr currentptr
NULL
newptr
‘o’ NULL
2828
head‘n’ ‘o’ ‘w’ NULL
After:
2929
Code
void insert(LNP *sptr, char value){ LNP newptr, previousptr, currentptr;
newptr = malloc(sizeof(LISTNODE)); if (newptr) { newptr->data = value; newptr->nextptr = NULL;
previousptr = NULL; currentptr = *sptr;
continued
3030
while ((currentptr != NULL) && (value > currentptr->data)) {
previousptr = currentptr; currentptr = currentptr->nextptr; } if (previousptr == NULL) { newptr->nextptr = *sptr; *sptr = newptr; } else { previousptr->nextptr = newptr; newptr->nextptr = currentptr; } } else printf("No memory available.\n");}
3131
Note
The use of a pointer address (sptr) as an argument to insert() is to allow the head pointer to the list to be altered if the character is inserted as the first node.
3232
Use
LNP h1;
h1 = string_to_list("nw");
insert(&hl, 'o');
Dangers:LNP h1, h2;
h1 = string_to_list("nw");
h2 = h1;
insert(&hl, 'o');
3333
5.6. Deletion
LNP head;
head = string_to_list("new");
c = delete(&head, 'e');
head‘n’
previousptr currentptr
‘e’ ‘w’ NULL
3434
head‘n’
previousptr currentptr
‘e’ ‘w’ NULL
tempptr
3535
Code
char delete(LNP *sptr, char value){ LNP previousptr, currentptr, tempptr;
if (value == (*sptr)->data) { tempptr = *sptr; *sptr = (*sptr)->nextptr; free(tempptr); return value; } else { previousptr = *sptr; currentptr = (*sptr)->nextptr;
continued
3636
while ((currentptr != NULL) && (currentptr->data != value)) {
previousptr = currentptr; currentptr = currentptr->nextptr; }
if (currentptr) { tempptr = currentptr; previousptr->nextptr = currentptr->nextptr; free(tempptr); return value; } } return '\0';}
3737
Some Comments
The use of a pointer address (sptr) as an argument to
delete() is to allow the head pointer to the list to be alt
ered if the first character in the list is being deleted.
3838
delete() can stop when:
1. It has found the character.
2. It has reached the end of the list (the character isn't there).
3. It has reached a character lexically bigger than the one being sought. Not used in this code.
3939
Dangers
LNP h1, h2;char c;h1 = string_to_list("all");h2 = h1;c = delete(&h1, 'l');
h2 wouldbepointingatnothing if the f irstnodeofh1 wasdeleted
h1‘a’ ‘l’ NULL
h2
4040
5.7. List Membership
int member(char c, LNP cptr){ if (isempty(cptr)) return 0; else { if (c == first(cptr)) return 1; else return member(c, cptr->nextptr); }}
4141
5.8. Print a List (iteratively)
void printList(LNP cptr){ if (!cptr) printf("List is empty.\n\n"); else { printf("The list is:\n"); while (cptr) { printf("%c --> ", cptr->data); cptr = cptr->nextptr; } printf("NULL\n\n"); }}
4242
Use
LNP head;
head = string_to_list("old");
printList(head);
The list is:o --> l --> d --> NULL
4343
Print a List (recursively)
void printList(LNP cptr){ if (isempty(cptr)) printf("NULL"); else { printf("%c --> ", first(cptr)); printList(cptr->nextptr); }}
4444
5.9. List Length
int length(LNP cptr){ if (isempty(cptr)) return 0; else return (1 + length(cptr->nextptr));}
4545
5.10. Concatenate Two Lists
void concat(LNP a, LNP b){ if (a->nextptr == NULL) a->nextptr = b; else concat(a->nextptr, b);}
4646
Use
LNP h1, h2;
h1 = string_to_list("new");h2 = string_to_list("ton");
concat(h1, h2); /* h1 altered */print_list(h1);
The list is:n --> e --> w --> t --> o --> n --> NULL
4747
Dangers
LNP h1, h2;
h1 = string_to_list("ab");h2 = string_to_list("cd");
concat(h1, h2); /* h1 is list "abcd" */
h2->data = 'o';
h1‘a’ ‘o’ ‘d’ NULL‘b’
h2
4848
5.11 Doubly Linked Lists
A node in a doubly-linked list contain two references that point to the next node and the previous node.
ex. struct listnode { char data; struct listnode *next; struct listnode *prev;
};
front points to the first node in the list
back points at the last node in the list
4949
A doubly-linked list can be scanned in both directions: a forward scan starts at 'front' and ends
when the link is to the same object as 'back' a backward scan starts at 'back' and ends
when the link is to the same object as 'front'
5050
Like a singly-linked list, a doubly linked list is a sequential structure.
To move forward or backward, use the node links 'next' and 'prev'.
Unlike a singly linked list, the insert and delete operations only need a single reference to the node.
5151
Insert a list into double linked list
Insertion into a doubly linked list requires four reference assignments.
prevNode = curr.prev;newNode.prev = prevNode; // 1prevNode.next = newNode; // 2curr.prev = newNode; // 3newNode.next = curr; // 4
5252
Delete a list from double linked list
To delete a node curr, link the predecessor (curr.prev) of 'curr' to the successor of 'curr' (curr.next).
prevNode = curr.prev;succNode = curr.next;succNode.prev = prevNode; // 1prevNode.next = succNode; // 2curr.prev = null;curr.next = null;