Linked List Introduction

Download Report

Transcript Linked List Introduction

CS 261 - Winter 2011
Linked List Introduction
Problem with Array and
Dynamic Array
• The problem with an array is that elements
are kept in a single large block of memory
• Can often use more memory than necessary
if collection grows and shrinks repeatedly
• Linked list is a good alternative, as the
memory use is always proportional to the
number of elements in the collection
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
FirstLink =
Value: 2
Next:
Va lue: 4
Next:
Va lue: 5
Next: null
Code for list stack
struct ListStack {
struct link * firstLink; /* initialize sets to zero */
};
void listStackPush (struct listStack *stk, double val)
{
stk->firstLink = _newLink(val, stk->firstLink);
}
Internal utility routine
struct link * _newLink (EleType v, struct link * n) {
struct link * lnk = (struct link *)
malloc(sizeof(struct link));
assert (lnk != 0);
lnk->value = v;
lnk->next = n;
return lnk;
}
Think about how to write Top,
push, isEmpty
• What are the steps involved in returning top
of stack?
• Removing top of stack?
• Returning true (1) if stack is empty, and
false (0) if it is not empty
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
FirstLink =
LastLink =
2
4
3
7
5
Why add to back, remove fron
front?
• Think about the issues
• Why not other way around?
• Container where you can add to back or
front, but remove from front only, is
sometimes called a Scroll.
Sentinels get rid of special cases
• Notice in discussing pop we needed to treat
removing last element as special case.
• Can avoid this by using a Sentinel
• A sentinel is just a link without a value,
never removed, sits at front or back of the
collection.
• Don’t need to check for removing last val
Picture of Sentinel
Front ptr
Back ptr
Sentinel
3
9
7
4
Class Structure for List Queue
struct listQueue {
struct link * firstLink;
struct link * lastLink;
};
void listQueueAddBack (struct listQueue *lst,
EleType val);
Init makes the sentinel
void ListQueueInit (struct listQueue *q) {
struct slink *lnk = (struct slink *)
malloc(sizeof(struct slink));
assert(lnk != 0); /* lnk is the sentinel */
lnk->next = 0;
q->firstLink = q->lastLink = lnk;
}
Elements are Added to end
void listQueueAddLast (struct listQueue *q,
EleType val) {
q->lastLink->next = _newLink(val, 0);
q->lastLink = q->lastLink->next;
}
Are there any special cases?
Return the front element
• How do you return the front element? Are
there any special cases?
• How do you remove the front element?
Again, are there special cases?
• How do you tell if the list is empty?
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
Struct link prevLink = q->firstLink;
Struct link current;
for (current = prev->next ; current != 0; current = current>link) {
if (EQ(current->value, testValue)) {
// do what needs to be done
return;
}
prevLink = current;
}
When you find it
• When you find the element to be deleted,
what does prev point to?
• What if the element to be deleted is at the
front of the list? Does this matter?
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)