Download Linked list

Survey
yes no Was this document useful for you?
   Thank you for your participation!

* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project

Document related concepts

Java ConcurrentMap wikipedia , lookup

Array data structure wikipedia , lookup

B-tree wikipedia , lookup

Linked list wikipedia , lookup

Transcript
CSCI 3333 Data Structures
Linked Lists
by
Dr. Bun Yue
Professor of Computer Science
[email protected]
http://sce.uhcl.edu/yue/
2013
Acknowledgement




Mr. Charles Moen
Dr. Wei Ding
Ms. Krishani Abeysekera
Dr. Michael Goodrich
Static Data Structures


The size of static data structures do
not change.
Example: array. During runtime, if
there are more elements to be
stored in an array:




A new array needs to be created.
The old array may be deleted.
Elements are copied.
Expensive!
Dynamic Data Structures


The size of a dynamic data structure
can change during runtime.
Many applications need to use
dynamic data structures.
Linked List ADT


A linked list is a sequence of nodes linked
in a chain.
Some operations:








Create
Delete
Traverse
Insert a node
Delete a node
Insert a linked list
Delete a linked list
…
Linked Lists vs. Arrays

Advantages:



Dynamic: size changes on demand.
Insertion and deletion of nodes: can be
faster in some situations.
Disadvantages:


May not be randomly accessible
efficiently.
Options:
Programmers needs to manage memory.
 Automatic garbage collection may bring
performance issues.

Linked List ADT



There are many kinds of linked lists
implemented by different
languages.
They are different ADTs.
We can study the ADTs to use them
without knowing how they are
implemented.
Example: C++ STL list

Some methods:






begin: returns an iterator addressing the first
element in a list.
pop_back:deletes the element at the end of a
list.
pop_front: deletes the element at the
beginning of a list.
push_back: adds an element to the end of a
list.
push_front: adds an element to the beginning
of a list.
…
Example Program
#include <list>
#include <iostream>
using namespace std ;
typedef list<int> INT_LIST;
int main()
{
INT_LIST ilist;
ilist.push_back(1);
ilist.push_front(2);
ilist.push_front(3);
ilist.push_front(4);
ilist.push_back(5);
cout << ilist.front() << endl;
cout << ilist.back() << endl;
Example Program (cont)
INT_LIST::iterator i;
cout << "Int list content:";
for (i = ilist.begin(); i != ilist.end(); ++i)
cout << " " << *i; // Note *
cout << endl;
for (i = ilist.begin(); i != ilist.end(); ++i)
(*i)++;
cout << "Int list content:";
for (i = ilist.begin(); i != ilist.end(); ++i)
cout << " " << *i; // Note *
cout << endl;
}
ilist.pop_front();
ilist.pop_back();
cout << "Int list content:";
for (i = ilist.begin(); i != ilist.end(); ++i)
cout << " " << *i; // Note *
cout << endl;
Output 1
ilist.push_back(1);
ilist.push_front(2);
ilist.push_front(3);
ilist.push_front(4);
ilist.push_back(5);
cout << ilist.front() << endl;
cout << ilist.back() << endl;
Output:
4
5
Output 2
INT_LIST::iterator i;
cout << "Int list content:";
for (i = ilist.begin(); i != ilist.end(); ++i)
cout << " " << *i;
// Note *
cout << endl;
for (i = ilist.begin(); i != ilist.end(); ++i)
(*i)++;
cout << "Int list content:";
for (i = ilist.begin(); i != ilist.end(); ++i)
cout << " " << *i;
// Note *
cout << endl;
Output:
Int list content: 4 3 2 1 5
Int list content: 5 4 3 2 6
Output 3
ilist.pop_front();
ilist.pop_back();
cout << "Int list content:";
for (i = ilist.begin(); i != ilist.end(); ++i)
cout << " " << *i;
cout << endl;
Output:
Int list content: 4 3 2
Perl Example




In Perl, an array is also a list.
It is built into the language. (You
can see the importance of lists
here.)
Array/List variables start with the
symbol @, e.g. @a.
List elements are scalar (which
starts with the symbol $), e.g.
$a[1], $a[12], etc.
Perl’s List Examples
@num[1,2] = (3,4); # $num[1] = 3; $num[2] = 4;
@num[1,2] = @num[2,1];
# swap $num[1] and $num[2];
@num[1,2] = @num[3,3];
# $num[1] = $num[3]; $num[2] = $num[3];
($num[1], $num[2]) = ($num[2], $num[1]);
# swap $num[1] and $num[2];
@num = (1,2,3,4,5)[3,2,1]; # @num = (4,3,2);
($first, @num) = @num;
# remove the first element of @num into $first
(@num, $last) = @num;
# pop the last element to $last
Java’s List Interface ADT


Java has a List interface for ordered collection
(sequence).
Super-interface:



Some known implementation classes:






Collection
Iterable
AbstractList
LinkedList
ArrayList
Vector
…
Practical APIs are much richer than those found in
some textbooks!
Interable Interface
Target of a for each statement.
 One method only
Iterator<T>iterator(): returns an
iterator over a set of elements of
type T.
 Iterator<T> interface’s methods:




hasNext()
next()
remove()
Collection Interface



Group of objects, possibly with duplicates.
Super-interface: iterable.
Some methods:








add(E e)
addAll(Collection<? extends E> c)
contains(Object o)
remove(Object o)
removeAll(Collection<?> c)
size()
toArray()
…
List Interface

New required methods added:

Random access:
E get(int index)
 E remove(int index)


Searching:
int indexOf(Object o)
 int lastIndexOf(Object o)


List Iterator:

ListIterator<E> listIterator()
Concrete Class LinkedList<E>

Interface implemented:





Serializable
Cloneable
Iterable<E> Collection<E> 
Queue<E>  Deque<E>
Iterable<E>  Collection<E> 
List<E>
<E>: Actual E should be a class
(not int, float, etc)
LinkedList Methods

From implementing Dequeue:







void addFirst(E e)
void addLast(E e)
E removeFirst()
E removeLast()
E offerFirst(): retrieve, not remove,
exception version for empty Dequeue.
E peekFirst(): retrieve, not remove,
return null version for empty Dequeue.
…
LinkedList Methods

From implementing List:





add(E e)
E get(int index)
E remove(int index)
remove(Object o)
int indexOf(Object o)
Finding the Right Structures




APIs are usually feature rich.
Study purposes of classes and
interfaces.
Study hierarchical class and
interface structures.
Study methods available.
Examples

Good to critically read program
code.


http://www.javasamples.com/showtutorial.php?tutoriali
d=347
http://www.idevelopment.info/data/Pro
gramming/java/collections/LinkedListEx
ample.java
Implementation Issues


You do not need to know how classes are
implemented to use them!
However, knowing the implementations:



May deepen understanding of the classes for
better usages.
May help selecting the best class for the
application.
May transfer this knowledge when you need to
implement custom-designed classes yourself.
Example Implementation in C++

Singly linked list of float




Each node has only one pointer to its
successor.
The list stores a head pointer to the
head of the list.
If the list is empty, the head pointer is
null.
For simplicity, each node stores an
float.
Implementation issues

Data members:





Value of float
head pointer
tail pointer: for efficiency
size of the list: for efficiency.
Tips: ensure all data members
properly updated in operations.
Node

class FloatList{
private:
// Declare a structure for the list.
// Simliar to nested classes in Java
struct ListNode
{
float value;
struct ListNode *next; };
ListNode *head, *tail;
// head and tail pointers
int _size;
Method Prototypes
public:
FloatList() // Constructor
{
head = tail = NULL;
_size = 0;
}
~FloatList(); // Destructor

Tips: always include constructors and
destructors.
Method Prototypes
void appendTailNode(float);
// insert node at the tail.
bool deleteHeadNode();
// delete node at the head.
bool deleteNode(float);
// delete the first occurrence of the float
// list.
void displayList();
int size() { return _size; }
bool isEmpty() { return _size == 0; }
};
Method Implementations
void FloatList::appendTailNode(float num)
{ ListNode *newNode;
// Allocate a new node & store num
newNode = new ListNode;
newNode->value = num;
newNode->next = NULL;
}
if (head==NULL)
{
// empty list
head = tail = newNode;
}
else
{
tail->next = newNode;
tail = tail-> next;
}
_size++;
Discussion



Maintenance of data members.
Trade off of using _size and tail:
faster for some operations and
slower for others.
Definition of newNode as class
instead of struct: use of
constructors.
deleteHeadNode
bool FloatList::deleteHeadNode() {
if (head == NULL)
return false;
else
{ ListNode *temp = head;
head = head-> next;
if (head == NULL) tail = NULL;
delete temp;
_size--;
return true;
}
}
Discussion

Other possible methods:


deleteTailNode
May change prototype:
deleteNode(float f)
bool FloatList::deleteNode(float f) {
if (head == NULL)
return false;
else
{ ListNode *curr = head;
ListNode *prev = NULL;
while (curr != NULL && curr->value != f)
{
prev = curr;
curr = curr-> next;
}
}
if (curr == NULL) // do not find the number to be
deleted.
return false;
else // to be continued.
}
else part
{
if (prev == NULL)
{
// the head node contains the number.
head = curr-> next;
}
if (curr == tail)
{
// the tail node will be deleted.
tail = prev;
}
// link the prev node to skip the curr node.
prev->next = curr->next;
}
delete curr;
_size--;
return true;
Discussion

Other possible methods.

deleteLastNode.
displayList
void FloatList::displayList()
{
ListNode *nodePtr;
nodePtr = head;
while (nodePtr)
{
cout << nodePtr->value << " ";
nodePtr = nodePtr->next;
}
cout << endl;
}
Discussion


Not flexible.
Need an ‘iterator’.
Destructor
FloatList::~FloatList(){
ListNode *curr, *next;
curr = head;
while (curr != NULL){
next = curr->next;
delete curr;
curr = next;
}
}
Test Program
FloatList list;
list.appendTailNode(2.2);
list.appendTailNode(3.4);
list.appendTailNode(2.2);
list.appendTailNode(1.8);
list.appendTailNode(2.2);
list.displayList();
cout << "size: " << list.size() << endl;
Output:
2.2 3.4 2.2 1.8 2.2
size: 5

Test Program
list.deleteHeadNode();
list.displayList();
cout << "size: " << list.size() << endl;
list.deleteNode(2.2);
list.displayList();
cout << "size: " << list.size() << endl;
list.deleteNode(2.2);
list.displayList();
cout << "size: " << list.size() << endl;
Outpit:
3.4 2.2 1.8 2.2
size: 4
3.4 1.8 2.2
size: 3
3.4 1.8
size: 2

Test Program
list.deleteHeadNode();
list.deleteHeadNode();
list.displayList();
cout << "size: " << list.size() << endl;

Output:
size: 0
Discussion

Other possible methods:




getHeadNodeValue()
getTailNodeValue()
deleteTailNode()
…
Discussion

Some operations, deleteTailNode
may take longer time, O(N), where
N is the number of nodes in the list.



May use a doubly linked list.
Need to have a way to analyze
performance.
List only works for float

May use template.
Questions and Comments?