250 likes | 334 Views
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
E N D
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
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
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)