0% found this document useful (0 votes)
92 views63 pages

Linked Lists: CS221N, Data Structures

The document provides an overview of linked lists as a data structure. It discusses the advantages and disadvantages of linked lists compared to arrays, including faster insertion and deletion but slower access. Key points about linked lists include that they are made up of links containing data and a reference to the next link; common operations like insertion, deletion, and searching have linear time complexity; and they can be implemented as double-linked lists or sorted lists to support additional operations.

Uploaded by

Bandar Abdallat
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
92 views63 pages

Linked Lists: CS221N, Data Structures

The document provides an overview of linked lists as a data structure. It discusses the advantages and disadvantages of linked lists compared to arrays, including faster insertion and deletion but slower access. Key points about linked lists include that they are made up of links containing data and a reference to the next link; common operations like insertion, deletion, and searching have linear time complexity; and they can be implemented as double-linked lists or sorted lists to support additional operations.

Uploaded by

Bandar Abdallat
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
You are on page 1/ 63

Linked Lists

CS221N, Data Structures

1
Recall Arrays
Advantages
Access is fast – O(1)
Insertion is fast in an unordered array O(1)
Searching is fast in an ordered array – O(log n)
Because we can apply the binary search
Disadvantages
Deletion is slow – O(n)
Searching is slow in an unordered array – O(n)
2 Insertion is slow in an ordered array – O(n)
Recall stacks and queues
Not generally used for real-world data
storage
Why?

Operations on the top of the stack are all


fast:
3
Access – O(1)
A versatile data structure
The linked
list
Second most commonly used behind arrays

Used for real-world data storage

We also saw last week that for stacks and queues, you could use arrays as an
underlying data structure
You also can use linked lists!

Good in situations where structure will be frequently modified


Bad in situations with frequent accesses (we’ll see why)

4
Several Types
Simple
Double-ended
Sorted
Doubly-linked
Lists with iterators

5
A Link
Data in linked lists are embedded in links
Each link consists of:
The data itself
A reference to the next link in the list,
which is null for the last item

6
The Link class
It makes sense to make Link its own class,
since a list can then just be a collection of
Link objects:
This is sometimes called a self-
referential class. Any theories why?

7
class Link {
References
Remember in Java, all objects are references
That means that the variable ‘next’, for each link just contains an integer for a memory
address
A ‘magic number’ which tells us where the object is
They are always the same size (so no problem)

Initially, whenever a link object is created its reference is null


Until we actually say:
mylink.next = new Link();
Even then, next does not contain an object.
It is still an address!
It just now is the address of an actual object, as opposed to null

8
Memory
How would this look in memory then?
Let’s draw it on the board.

9
Recall the implication!
Access for linked lists is slow compared to
arrays
Arrays are like rows of houses
They are arranged sequentially
So it’s easy to just find, for example, the
third house
With linked lists, you have to follow links
10
Links of Records
We can have a link of personnel records:

class Link{
public String name;
public String address;
public int ssn;
public Link next;
}

We can also have a class for PersonnelRecords, and a linked list of those. Let’s
do that together!

11
Operations
Insertion
At the beginning (fast)
In the middle (slower, although still
better than arrays)
Deletion
At the beginning (fast)
In the middle (slower, although still
12
LinkedList class
Start with:
A private Link to the first element
A constructor which sets this reference to
null
A method isEmpty() which returns true if
the list is empty
13
insertFirst(): O(1)
Accept a new integer (p. 188)
Create a new link
Change the new link’s next reference to
the current first
Change first to reference the new link
We could not execute these last two in

14
reverse. Why?
deleteFirst(): O(1)
Remove the first integer in the list (p. 188)
Just reset the first reference to first.next

15
displayList() – p. 189 O(n)
Use a reference current to iterate through
the elements
Print the value
Set current to current.next
Stop when current becomes null
Before setting current to current.next:

16
main() function
LinkedList theList = new LinkedList();
theList.insertFirst(22);
theList.insertFirst(44);
theList.insertFirst(66);
theList.insertFirst(88);

theList.displayList();

while (!theList.isEmpty())
theList.deleteFirst();

theList.displayList();

17
find() – p. 194 O(n)
Essentially the same idea as displayList()
Linearly iterate through the elements
with a reference current
Repeatedly set current to current.next
Except this time, stop when you find the
item!
Before setting current to current.next:
18
delete() – p. 194 O(n)
Pass a value stored in the list, and remove
it
First we have to find it, at that point it will
be in current
Set the previous element’s next reference
to current.next
When we find the value:
19
main() function - #2
LinkedList theList = new LinkedList();
theList.insertFirst(22);
theList.insertFirst(44);
theList.insertFirst(66);
theList.insertFirst(88);

theList.displayList();

Link f = theList.find(44);

theList.delete(66);

theList.displayList();

20
Double-Ended Lists
Just like a regular linked list, except there
are now two references kept
One to the beginning (first)
And one to the end (last)
Enables easy insertion at both ends
You still cannot delete the last element

21
any easier. Why?
insertLast() – p. 199 O(1)
What does this look like now? Let’s see:
Create the new link with the new value
(next=null)
Set last.next to reference the new link
Set last to reference the new link
Might we also have to set first? When?

22
main() function - #3
LinkedList theList = new LinkedList();
theList.insertFirst(22);
theList.insertFirst(44);
theList.insertFirst(66);

theList.insertLast(11);
theList.insertLast(33);
theList.insertLast(55);

theList.displayList();

// Inserting items at the beginning reverses their order


// Inserting items at the end, preserves their order!

23
Double-Ended Lists
Would we also have to modify delete()?
When? Let’s do it.

24
Efficiency: Summary
Fast insertion/deletion at ends: O(1)
Searching: O(n)
Deleting a specific item: O(n)
BUT, faster than arrays
You have equal O(n) for the search
But then an array requires an O(n) shift,
25
where a list requires reference copies –
Memory: Summary
A linked list uses (more or less) memory
than an array? Why?

A linked list uses memory more efficiently


than an array.
Size is flexible
Never have to ‘overcompensate’
26
Abstract Data Types (ADT)
A central feature of the Java programming
language
Let’s review
What is a datatype?
What do we mean by abstraction?
What is an interface?

27
Data Types
Examples of data types: int, float double
These are called primitive data types
When we refer to a datatype:
Characteristics of the data
Operations which you can perform on
that data
Object-oriented programming defines
28
Abstraction
Abstract: Considered apart from detailed
specifications or implementation.
Let’s ponder the following questions:
What is an analogy of abstraction in the
English language?
How does abstraction equate to datatypes

29
and operations?

Abstract Data Types (ADTs)
Idea: Represent a Data Structure by
focusing on what it does and ignoring how
it does it.
We’ve seen this already with stacks and
queues
Internally, they stored data as an array
But the user didn’t know this! All they
30
Revisiting the stack….
LIFO structure
Items are inserted, removed
and accessed from the top

31
Revisiting the queue…
FIFO structure
Items are inserted from the rear and removed from the front

Four operations: insert(), remove(), front() and rear()


Let’s look at the implementation with arrays, p.138
Change it to use linked lists

32
When to use which?
List is clearly the better choice when you
(know or do not know?) the number of
elements that the stack or queue will hold
Analyze: what are the tradeoffs
In the case of the queue, a linked list saves
us the concern of wraparound
Keeping track of two references, front
33
Summary: ADTs
In Software Engineering
It’s always important to consider the operations you want before you determine
details, like:
Memory
Implementation of functions
For example, the operations you desire will strongly determine the data structure
you use
First item? Last item? Item in a certain position?

This is called decoupling specification and implementation.


Use this on an interview and they’ll smile! 
What rewards can this have in terms of client code and portability?

34
Sorted Lists
Linked list where the data is maintained in
sorted order
Useful in some applications
Same applications where you’d use a
sorted array
But, insertion will be faster!
And, memory will be used more
35
insert() p. 214 O(n)
We haven’t looked at inserting
in the middle. Let’s see how it
will be done:

36
main() function - #4
LinkedList theList = new LinkedList();
theList.insert(20);
theList.insert(40);

theList.displayList();

theList.insert(10);
theList.insert(30);
theList.insert(50);

theList.displayList();

theList.remove();

37 theList.displayList();
Sorted Linked List: Efficiency
Insertion and deletion are O(n)
for the search worst case
Cannot do a binary search on
a sorted linked list, like we
could with arrays! Why not?
Minimum value can be found
in O(1) time
38

Limitation: Previous element
Numerous times, we found the inability to access the previous element inconvenient
Double-ended list and deleting the last element
Could not search from both ends

Doubly linked lists solve this problem


Allows your to traverse backward and forward
Each link contains references to previous and next
Nice!
But remember, there’s always a catch
Memory
Also, straightforward algorithms become slower (guess as to why?)

39
Our new Link class
class Link
{
public int iData;
public Link previous;
public Link next;
}

next and iData were there before, previous is new


For the first element, previous is null
For the last element, next is null

40
Pictorally…
Single-ended (‘L’ references the List)

Double-ended (usually done)


‘F’ references the First element, ‘L’ the
41
Last
Reverse Traversal O(n)
Forward traversal is the same as before
Use current to reference a Link, and
repeatedly set it to current.next
Backward traversal is new
It can only be done conveniently if the
list is double-ended
Now we repeatedly set current to
42
Java Implementation, p. 226
Methods
isEmpty(), check if empty
insertFirst(), insert at beginning
insertLast(), insert at end
insertAfter(), insert in the middle
deleteFirst(), delete at beginning
deleteLast(), delete at end
43
isEmpty() O(1)
Simple function
Returns true if first is null.

44
insertFirst() O(1)
Steps
Create a new link
Set its next reference to first
Set first’s previous reference to the new
link
Set first (and last if empty) to reference

45
the new link
insertLast() O(1)
Steps
Create a new link
Set it previous reference to last
Set last’s next reference to the new link
Set last (and first if empty) to reference
the new link
Before
46
insertAfter() O(n)
Steps
Find the element in the list to insert after
(current)
Set current.next’s previous reference to
the new link
Set link’s next reference to current.next
Set current.next to the new link
47
deleteFirst() O(1)
Steps
Set first.next’s previous reference to null
Remember first.next could be null!!
Set first to first.next

Before
48
deleteLast() O(1)
Steps
Set last.previous’ next reference to null
Remember last.previous could be null!!
Set last to last.previous

Before
49
deleteKey() O(n)
Steps
Find the key, call it current
Set current.previous’ next
reference to current.next
Set current.next’s previous
reference to current.previous
Be sure to handle the case when
50
either is null!! This would be
displayForward() O(n)
Use a reference current to iterate through
the elements
Initially equal to first, print the value
Set current to current.next
Stop when current becomes null
Before setting current to current.next:

51
displayBackward() O(n)
Use a reference current to iterate through
the elements
Initially equal to last, print the value
Set current to current.previous
Stop when current becomes null
Before setting current to current.previous:

52
Iterators
What have we seen?
Ability to linearly traverse a
list and find an item
What have we been missing?
Control over the items we
traverse
53
Idea
Provide a class which:
Contains a reference to some element in
the list
Can easily increment itself to reference
the next element

54 class ListIterator() {
main() function - #4
LinkedList theList = new
LinkedList();
ListIterator iter = new
ListIterator(theList.getFirst());

// This increments every value in


55
the LinkedList
Pictorally…
I can create multiple instances of
ListIterators, and have their member
current reference various points in the list

56
Bidirectional Iterators
If we have a doubly-linked list, it’s easy.
Let’s add two methods to our previous
iterator class:
One to access the previous Link
prevLink()

If we have a singly-linked list, it’s more


57
Encapsulation
Let’s connect the components for LinkedList and ListIterator
I want to be able to construct a LinkedList, and return a
ListIterator referencing itself, through a function
getIterator(), i.e.:

LinkedList myList = new LinkedList();


ListIterator itr = myList.getIterator();
// itr now references the first element of myList

Why would this help?


Middle insertion and deletion could be done through the
iterator
58
Looking at LinkedList…
class LinkedList {
private Link first;
public LinkedList() {first=null;}
public Link getFirst() {return first;}
public Link setFirst(Link l) {first = l;}
public boolean isEmpty() {return (first == null);}
public ListIterator getIterator() {return new
ListIterator(this); }
}

// Do we remember what ‘this’ does?

59
ListIterator: p. 237
Let’s now change the ListIterator
Make it bidirectional
Contain a reference to the list, as opposed to a single link
Methods
ListIterator(): Pass a LinkedList reference, and set
reset(): Reset iterator to the beginning of the list
atEnd(): Check if we are at the end
nextLink(): Move to the next link
getCurrent(): Return the current link
insertAfter(): Insert a link after the link referenced
insertBefore(): Insert a link before the element referenced
deleteCurrent(): Delete the currently referenced link

60
deleteCurrent(): Notes
If we delete an item, where should the
iterator now point?
We’ve deleted the item it was pointed to!
We don’t want to move it to the
beginning
Concept of ‘locality’
Can’t move it to the previous item
61

atEnd(): Notes
Our implementation checks if the iterator
points to the last element. Tradeoffs:
Looping becomes awkward
Iterator is always pointing at a valid link,
which is good for reliability
Must be careful with iteration
Let’s say we used a loop to display data
62
Another example
Deleting all links that contain values with
multiples of three. How can we use the
iterator to do this?

63

You might also like