chapter 3 – lists a list is just what the name implies, a finite, ordered sequence of items. order...
TRANSCRIPT
Chapter 3 – Lists A list is just what the name implies, a finite,
ordered sequence of items. Order indicates each item has a position. A list of size 0 is the empty list. The first element is element 1 and the last
element is element N in a list of size N. Operations can include: insert, remove,
findKth, find, next, previous. Must consider special cases, no previous, no
next, not found …
Generic List Functionsvoid clear(); // reinitialize the list
bool insert(const Elem &); //insert an item into the list before the current item. Return false if the list is full.
bool append(const Elem &); //insert an item after the last.
bool remove(Elem &); //remove the item at the current. Return false if current is empty.
void setStart(); //set current to the beginning.
void setEnd(); // set current to the last.
void prev(); // set current to the previous item. No change if current is at the first.
void next(); // set current to the next item. No change if current is at the end.
More List Functions
int leftLength(); // the size of the list before the current
int rightLength(); // the size of the list after and including the current.
bool setPos(int); // set current to the position indicated by the argument. Return false if there are not enough in the list.
bool getValue (Elem &); // return the value of the current item in the argument. Return false if there is no current item.
void print(); // print out the items in the list.
Array Implementation
Can use an array to implement a list. Fixed size. FindKth very fast. Insert and remove will cause lots of
movement. Find is linear unless the list is ordered.
Array Based List Implementation
template <class E>class List{private:
int maxSize;int listSize;int curr;Elem * listArray;
public:methods discussed
};
Some Array Based List Functions Constructor
List(int size=DEFAULTSIZE) {maxSize=size;listSize=curr=0;listArray=new Elem[size]; }
void setStart() {curr=0}; bool append(const Elem & item) {
if (listSize==maxSize) return false;listArray[listSize++]=item; }
Linked List
Allows dynamic memory. Each node has a link to the next item in
the list. (extra memory). Last item’s next points to NULL. Insert and remove take constant time. FindKth is now linear.
Programming Trick To insert or remove at the beginning is a
special case (must change the head pointer). Instead, create a “header node” that contains
no data. This node will never be deleted. The head pointer will always point to the
header node. Created in the constructor. Called node 0.
Iterator and Container Classes
A container class is designed to hold collections of objects (list, stack, queue, tree, …).
This class provides services such as insertion, deletion, searching, sorting, find,…
It is common to associate iterator objects with container classes.
Being friends is appropriate.
Iterator Classes
An iterator is an object that returns an item of a container. This is much like using pointers.
We do not want the user to get indiscriminate use of a pointer (then they can change the data in a private area).
Use iterator classes to handle these pointers for the user.
This way, the user can keep “pointers” to multiple locations in a container.
Iterators (cont.) You can think of an iterator as a
bookmark within the container. Easily allows multiple bookmarks in one
container. The container class can use iterator
objects. Package both classes in same .h
and .cxx files. Need to give an incomplete class
declaration since both classes need both classes.
List Implementation
Now a list should have 3 classes associated with it.– ListNode – Holds the data of 1 element in
the list (many times implemented as a struct)
– List – Holds a pointer to the first item.– ListItr – keeps track of a position in the List.
Package them all together, friends will be o.k.
Doubly Linked List One of the operations was to give the
previous. This is fine and can be done with one extra pointer as long as we will just use the previous function once in a row.
To allow unlimited backing up, need a previous pointer in each node.
Uses more memory, but will not be significantly slower. Now no need for a separate previous pointer for insertion and deletion.
Circular Linked List
Instead of having the last node’s next point to NULL, have it point to the first.
This is useful in circular applications, when the first follows the last.
Polynomial Application
Many high level polynomials have many terms with a 0 coefficient.
Would need to store them if using an array.
Use a linked list to not take memory for items with a 0 coefficient.
Big Numbers
To allow for arbitrary large numbers, use a linked list where each holds one digit.– This is good conceptually, but for
efficiency, we can use an int to hold several digits per node.
Similarly, we can use a linked list for a string of arbitrary length.
MultiLists Sometimes we have one set of data, but want
to process it in different orders.– DMV info, may want to go in name order or
driver’s license order, or in tag order. Rather than having the data duplicated
several times for several lists, use multiple pointers.– Having duplicated data makes the update process
difficult and error prone. Each pointer is the next for a particular list.
– Nextname, nextlic, nexttag– Now insertions are really inserting into 3 lists.
Freelists The system new and delete are very slow. When your program does a free, do not give it
back to the system. Instead, keep it around in another list to be
used to give back the next time the program does a new.
If your freelist is empty, then the class will actually need to do a new.
Can accomplish this by overloading the system new and free operations. (Can still access the system new and free).
Freelist ImplementationClass ListNode{public:
ELEM element;ListNode * next;static Listnode * freelist;ListNode(const ELEM & elemval, link * nextval=NULL) {element=elemval; next=nextval;}ListNode(ListNode * nextval=NULL) {next=nextval;}~ListNode() {}void * operator new(size_t);void operator delete(void *);};
ListNode * ListNode::freelist=NULL;void * ListNode::operator new(size_t){
if (freelist==NULL) return ::new ListNode;ListNode * temp=freelist;freelist=freelist->next;return temp; }
void ListNode::operator delete(void* ptr) {((ListNode *) ptr)->next=freelist;freelist = (ListNode*) ptr;}
Array Implementation
Can have array based lists or Array based linked lists. Array based lists are simple but have a
lot of data movement for insertions and deletions.
Array based linked list will have essentially 2 linked lists in one array, one for the free items and one for the actual data.
Array Linked Lists
Use and extra field for a next pointer. This pointer will be an integer that
points to a position in the array (via a subscript).
NULL will need to be –1 rather than 0. Need a head pointer to tell which item is
first.
Array Linked List Example
Jim -1
Jack 2
Jill 0
Beth 5
-1
Bob 1
Head is 3
Free is 4
Array Linked List Initialization The initial linked list will have Head =
NULL = -1 The initial free list will be 0 and Next[i]=i+1
and Next[last]=NULL To accomplish a new, we remove the front
of the free list {newptr=free; free=next[free];}
To accomplish a remove we add the node to the front of the free list {next[deleted]=free; free=deleted;}
Need to use subscripts instead of pointers (->)
Stacks
LIFO: Last In, First Out. Restricted form of a list.
– Insert only at the front.– Remove from the front.
Notation– Insert: PUSH– Remove: POP– The accessible element is called TOP.
Queues
FIFO: First In, First Out. Restricted form of a list.
– Insert at one end.– Remove from the other end.
Notation– Insert: Enqueue.– Delete: Dequeue.– First Element: FRONT.– Last Element: REAR.
Queue Implementations Linked Queue
– Very easy and intuititive.– Always add at the rear (trivial with a rear pointer).– Always delete at the front (trivial with pointer to front).
Array based Queue– Have an int to tell where the rear is (start at 0, increment
when add).– Have int to tell where front is (start at 0, increment when
delete).– Front chases the Rear.– No data movement.– May get to end and think queue is full when there are empty
spots.– Make circular. When Front and Rear get to end of array
reset them to the beginning of the array.– If rear “passes” front during insertion then full.– If front “passes” rear during a deletion, then empty.