Linked List Introduction

Download Report

Transcript Linked List Introduction

CS 261 - Winter 2009
Linked List Introduction
Characteristics of Linked Lists
• Elements are held in objects termed Links
• Links are 1-1 with elements, allocated and
released as necessary.
• Each link points to next link in sequence,
sometimes to previous link.
• Lots of variations on a simple idea
A typical Link Structure
struct link {
EleType value;
struct link * next;
};
Some variations in Linked lists
• List have header (special value to point to
start)
• Use null as terminator, or special value for
end
• Use single or double links?
• Pointer to first element, or pointer to first
and last
Simplest Example, List Stack
• List stack is the simplest data structure that
can be implemented using linked list idea
• Keep pointer to first element (null if empty)
• Elements are added or removed from front
• can only access first element
Picture of list stack
Code for list stack
struct ListStack {
struct link * firstLink; /* initialize routine sets to zero */
};
void listStackPush (struct listStack *stk, double val) {
struct link * newLink = (struct link *)
malloc(sizeof(struct link));
assert(newLink != 0);
newLink->next = firstLink;
newLink->value = val;
stk->firstLink = newLink;
}
How fast is List Stack?
• Compare to dyArrayStack
• push - list O(1) always, dyArray(1)
expected
• pop - list O(1) always, dyArray same
• top - list O(1) always, dyArray same
• In practice dyArray is slightly faster in real
timinings.
But what about queues?
• An array queue is hard to do, because you
can't add to the beginning without sliding
things up.
• With lists it is easy. Just keep a pointer to
both the front AND the back.
• Elements added to the back, removed from
front
Picture of list queue
Class Structure for List Queue
struct listQueue {
struct link * firstLink;
struct link * lastLink;
};
void listQueueAddBack (struct listQueue *lst,
EleType val);
void listQueueAddFront (struct listQueue *
lst, EleType val);
Elements are Added to end
void listQueueAddLast (struct listQueue *lst,
EleType val) {
struct link * newLink = (struct link)
malloc(sizeof(struct link));
assert (newLink != 0);
newLink->value = val;
newLink->next = lst->lastLink;
lst->lastLink = newLink;
if (firstLink == 0) firstLink = newLink;
}
Empty test - just see if link is null
Int listQueueIsEmpty (struct listQueue *lst)
{
return lst->firstLink == 0;
}
Elements Removed from Front
void listQueueRemoveFirst (struct listQueue *lst) {
struct link * lnk = lst->firstLink;
assert (! listQueueIsEmpty(lst));
lst->firstLink = lnk->next;
free(lnk);
if (lst->firstLink == 0) /* ie, removing last*/
lst->lastLink = 0;
}
What about a deque?
• What if we want to add and remove
elements from both front and back?
• Need to use links going both forward and
backwards
• Makes adding a new link harder, as must
maintain both forward and backward links.
• Will do that in tomarrows lesson
What about a Bag?
• Contains is easy - just a loop
• Add is easy - can either add to front or to
back
• Remove is the tricky one. How to patch up
links after removing an element.
• Two solutions, double links or previous
pointers (will do double links tomarrow)
Previous Pointers
• As you loop over the links looking for value to
remove, keep pointer to previous element
link prevLink = null;
for (Link current = firstLink; current != null;
current = current->link) {
if (EQ(current.value, testValue)) {
// do what needs to be done
return;
}
prevLink = current;
}
Your turn
• See if you can do stack (should be trivial)
• See if you can do queue (only slightly
harder)
• See if you can do bag (requires a little more
thought)