Download Data Structures and Other Objects Using C++

Document related concepts

Lattice model (finance) wikipedia , lookup

Red–black tree wikipedia , lookup

Quadtree wikipedia , lookup

Interval tree wikipedia , lookup

Binary tree wikipedia , lookup

Binary search tree wikipedia , lookup

B-tree wikipedia , lookup

Linked list wikipedia , lookup

Transcript
Linked Lists in Action
 This chapter introduces
linked lists.
 This presentation shows how
to implement the most
common operations on linked
lists.
LINKED LISTS
Collection Classes - LINKED LIST
 The Java 2 platform contains a Collections API
 This group of classes represent various data
structures that store and manage objects
 It includes classes such as ArrayList and LinkedList
2
Abstract Data Types – A Review
 An abstract data type (ADT) is :
 an organized collection of information containing
 a set of operations used to manage that information
 The set of operations includes methods such as add,
delete , find etc..
 The set of operations/methods define the interface to
the ADT
3
Abstract Data Types
 A List ADT, for instance would define the operations that
be used with the list, such as add, delete.
 We have looked an array implementation of a list, now
we will look at a Linked List.
4
Static vs. Dynamic Structures
 A static data structure has a fixed size
 Arrays are static; once you define the number of
elements it can hold, it doesn’t change.
5
DRAWBACKS OF ARRAYS
 The array implementation of our collection
has one serious drawback:
 you must know the maximum number of
items in your collection when you create it.
6
Linked Lists
 WHAT IF YOU DON’T KNOW THE NUMBER OF ITEMS
BEFOREHAND?????
 WHAT IF THE NUMBER OF ITEMS WILL VARY OVER
TIME?
 We need a dynamic data structure that grows and
shrinks as necessary
7
Array Limitations
 Arrays
 Simple, Fast
but
 Must specify size at construction time
 WHICH GIVES RISE TO “Murphy’s law”
 Construct an array with space for n
 n = twice your estimate of largest collection
 Tomorrow you’ll need n+1
8
Linked Lists - it is never full
A linked list is a very flexible,
 dynamic data structure:
 no preset size required

items may be added to it or deleted from it at will.
 No need to increase capacity when full  it is never full
9
Object References
 Recall that an object reference is a variable that stores the
address of an object in memory.
 A reference can also be called a pointer (to an object in
memory)
 and they are often depicted graphically:
student
John Smith
40725
3.57
10
References as Links
 Object references can be used to create links
between objects
 Suppose a Person class contains a reference to
another Person object

John Smith
40725
3.57
Person Jane
Jane Jones
58821
3.72
11
Self-Referential Objects
 A Person object, for instance, could contain a reference
variable to another Person object:
public class Person
{
private String name;
private String address;
private Person next; // a link to another Person object
// whatever else
}
12
Intermediate Nodes
 Problem:
 Objects should not have to deal with the
 details of the structure in which they are stored
 E.g., the person class stored a link to the next person
object in the list
13
Linked Lists
 Instead, we can use a separate node class that :
holds a reference to the stored object and
a link to the next node in the list
 This type of reference can be used to form a Linked List.
14
A Linked List of Persons
 So by having a separate structure to contain
the list of persons:
 One object(object 1) is not dependent for its
existence on another object (object 2)
 And removing object2 would not require
removing object1.
15
Object References - ListNode class
 Consider an object that contains a reference to another
object of the same type:
class ListNode<T>
{
T data; // object stored in data– e.g. Client object
ListNode next; // reference to the next node
}
data = Client
next = refers to next listnode
16
 Two objects of this class can be instantiated and chained
together.
 The next reference of one Node object
refers to the next node in the list.
 The second object’s next reference refers to a third Node
object, and so on,

creating a linked list of Node objects.
Client 1
next
Client2
next
17
NODE S IN THE LIST
 Each node will contain some data as specified
by the programmer.
 This constitutes a linked list
18
Linked Nodes
 In a linked list, each item is allocated space as it is
added to the list. (called dynamically)
 A link (next) is kept within each item to the next
Client in the list.
Client 1
next
Client2
next
19
Each node of the list has two elements :
1. the object being stored in the list, e.g. a client and
2. a reference to the next node in the list (next)
 The next reference in the last node in the list contains
a NULL pointer to indicate that it is the end or tail of the
list.
Client 1
next
Client2
next = null
20
Linked Lists
 As items are added to a list,
 memory for a node is dynamically allocated.
(Allocated as needed)
 Thus the number of items that may be added to a list
 is limited only by the amount of memory available.
head
client
21
HEAD OF THE LIST
 The variable (or handle) which holds on to the list is
simply a pointer(reference) to the node at the
head of the list.
Client
next = null
 It is called head
 Head holds the memory address of the first node
22
 Linked List -Flexible space use
 Dynamically allocate space for each element as
needed
 Includes a pointer to the next item
 Linked list
 Each ListNode of the list contains
 the data item (e.g. a Client)
 next - a reference to the next node
Data
Next
object
23
Linked Lists - WHAT IS HEAD?
 Let’s implement a Collection structure – a linked list
 which has a reference to the first node called
HEAD
 Head is initially NULL
Head = null
24
Linked Lists
 The Linked List structure has a reference to the list:

head which is initially NULL
 TO Add first item to the head of the list




Allocate memory for the ListNode
Set its data reference to some object
Set next to NULL
Set head to reference the new node
Head
ListNode
Data
Next
object
25
 Add second item to the head of the list
Allocate memory for the node - NewNode
Set its data reference to some object (object2)
Set new node .next to point to the node Head is pointing
to
Set Head to point to (reference) the new node
Head
NewNode
Data
Next
object2
FIRST node
Data
Next
object1
26
Linked Lists
 Add second item to the head of the list
Allocate memory for the node
Set its data pointer to an object
Set new node next to point to the node Head is
pointing to
Set Head to point to new node
Head
New node
Data
Next
object2
node
Data
Next
object1
27
Constructors of a ListNode
class ListNode
{amine the constructor for the class.
// This is one of the constructors
in the ListNode class
public ListNode(T initialData)
{
data = initialData; // data for the node
next = null; // reference to next node
}
where :
data - is the initial data of a new node e.g. a client ,
next - a reference to the next node in the list.
28
How to start the linked list
 Declare a head node to point to the first node in the
list .
 To create the first node
ListNode head = null; // initialize head
// now create the first node
head = new ListNode (“dan”);
Head now refers to a one-node linked list.
The data is “dan” and next is equal to null. See previous
slide constructor
29
Declarations for linked Lists

We will use Strings as data .
// Constructor ListNode
public class ListNode
{
private String data;
private ListNode next;
// constructors
}
Create the first Node:
Head
ListNode
dan
null
head = new ListNode (“dan”);
data
next
30
Declarations for linked Lists
 For this example, each node in the
linked list is an object of the class
ListNode, as shown here with String
data
jay
Head
public class ListNode
{
private String data;
private ListNode next;
...
// Constructor sets next to
null initally
}
data
next
dan
data
next
nat
data
null
next
31
Declarations for linked Lists
 Each ListNode also contains a next reference
which refers to the next ListNode in the list.
Head
public class ListNode
{
private String data;
private ListNode next;
...
}
jay
data
next
dan
data
next
nat
data
null
32
 A program keeps track of the FIRST node by
STORING ITS ADDRESS IN HEAD.
52 is the address of the
second node
 Head is a reference to a ListNode.
 It holds the address of the first node.
 Head and next both refer to list nodes
 They store the address of the next node
52
jay
next =60
next
50
Head
head
50
50 is the address of the
50
first node
dan
data
next =52
data
60
nat
data
next
null
33
NEXT holds an address
 In the previous slide, the head node holds the
address of the first node which is 50
 The second node’ next reference holds the address
of the next node which is 52.
 The third node’ next reference holds the address of
the next node which is 60.
34
Declarations for Linked Lists
 We represent the empty list by storing
 null in the head reference.
 ListNode head = null;
head
null
35
The null reference
 The null reference is a special JAVA constant.
 It means the reference has no address
 so it does not refer to anything.

36
Null references
 Null references are used in several instances.
 When a object is declared but not instantiated.
Client client;
Client is initially null
 For the next part of the final node in a linked list.
 When we have an empty list, the head and tail reference
variables are null.
37
Null Pointer Exceptions
 When a reference variable is null,
 you cannot call any of the methods associated with
variables’s class. E.g.;
ListNode head = null; // head is a null referemce
head.next;
// error - no next reference yet exists.
 The second line will result in a
NullPointerException.
38
Inserting Nodes at the front of the list.
To add to front of list,
we create a reference to the head node and call
it head.
 Remember head is initially null.
 The code to create the head node is:

ListNode head = null;
39
Inserting an Node at the Front
We could use this code if the list is initially empty:
ListNode head = null;
// create the node -- uses constructor
ListNode newnode = new ListNode(data1, null);
head = newnode; //Point head to it
OR
Below is a shorter version of the previous two lines:
ListNode head = new ListNode(data1, null)
head
data1
null
40
INSERTING A NODE
This is a constructor IN THE Linkedlist class:
public ListNode ( T data, ListNode nxt)
{
data = initialData;
next = nxt;
}
Does the constructor work
correctly for the first
node on a new list ?
head = new ListNode(data1, null);
//Where head is initially null
41
Creating the first node in a list - Review
 head = new ListNode( data1, null)
 creates a new node with data1 as the data
and null is stored in next.
 Head now holds the address
 of the node with data1 :
Head = 50
50
data1
null
42
Inserting an Node at the Front
 Create a new node…red boxes
are addresses of nodes.
A new node
 Head holds the address of the
first node - 50
head
50
data1
null
50
Let’s add another node to the front of the list
43
Inserting an Node at the Front
We want to add a new entry, data2,
to the front of the linked list shown here.
New
node
head
50
50
data1
null
44
Inserting an Node at the Front
 Create a new node...
 Place the data in the new
node's data field – this is data2.
Create the new node:
ListNode newnode = new ListNode( data2, null)
newnode
head
data2
Next = null
50
50
data1
null
45
Inserting an Node at the Front of the list, reassign head to it
Connect the next (50) reference of
newnode to the node head is
currently pointing to.
newnode
So now head and newnode.next
point to the same node
data2
newnode.next
next = 50
head
50
ListNode newnode = new ListNode( data2, null)
newnode.next = head
50
data1
null
newnode.next refers to the same node
as head
46
Inserting an Node at the Front
ListNode newnode = new Listnode(data2, null)
newnode.next = head;
head = newnode ; // we store address 84 in head
data2 is now the new first node of the linked list –
its address is 84
Newnode’s
address is 84
Finally, we point head to the
newnode
head = newnode;
Head holds address of the
newnode - 84
head
84
84
data2
NEXT = 50
50
data1
null
47
The brute force way to insert the node at the head of the list would
be:
public void insertFirst(T data)
{
// create a node
ListNode newnode = new ListNode(data, null);
if(isEmpty()) // is the list is empty
head = newnode; // point head to the new node
else // list is not empty
{ // set the next pointer of newnode to what head is
pointing to
newnode.next = head ;
head = newnode // point head to newnode
}
}
48
CHALLENGE
 For homework, extra credit pts on
your quiz if you can do the
insertion code in the previous slide
in one line of code.
 You may assume that head has
been set to null.
49
Adding to a list
 This strategy is fast and efficient, but each item is
added to the head of the list.
 An alternative is a list which contains both head and
tail pointers:
 The code for Add is modified to make a list in which
new nodes are added to the list at the end.
50
Caution!
 Always make sure
that your linked list
methods work
correctly with an
empty list.
EMPTY LIST
Linked Lists
 Add time
 Constant - independent of n – no loops
 Search time
 Worst case - n
Collection
Head
node
node
Data
Next
object2
Data
Next
object
52
Pseudocode for Inserting ListNodes
 Nodes are often inserted at places other than the
front of a linked list.
 There is a general pseudocode that you can follow for
any insertion function. . .
 First determine if the node is the first node , if so,
call method insertFirst(data)
53
Pseudocode for Inserting Nodes
 Otherwise (if the new node will not be first):
 then a reference named current must be
placed on the list
 This special node is called the selected
node and the new node is inserted right
after the selected node.
54
Pseudocode for Inserting ListNodes
 Otherwise (if the new node will not be first):
 Start by setting a reference named current to refer to the
node before the new node.
THE NEW NODE WILL BE
INSERTED AFTER THE NODE
CURRENT IS POINTING TO
current
jay
dan
next
head
nat
null
55
Pseudocode for Inserting ListNodes
 Otherwise (if the new node will not be first):
 Start by setting a reference named current to refer to the
node just before the new node's position.
atlink(next)
the link which
LookLook
at the
in the
node is
is which
in the is
node
current
pointingprevious
to
current
jay
dan
next
head
nat
null
What is the name of this link?
56
Pseudocode for Inserting ListNodes
 Otherwise (if the new node will not be first):
 Start by setting a reference named current to refer
to the node which is just before the new node's
position
current
What is the name of this link ?
jay
This link is called current.next
Or current.getNext()
dan
next
head
nat
null
57
Pseudocode for Inserting Nodes
 Otherwise (if the new node will not be first):
 Start by setting a reference named current to refer to the
node which is just before the new node's position
current
Current refers to the head
of a small linked
list, with jay and nat
jay
dan
next
head
nat
null
58
Pseudocode for Inserting ListNodes
 Otherwise (if the new node will not be first):
Let’s insert a new node
after the node
containing dan
jay
next
current
current
10
next
dan
next
head
nat
null
59
These are the contructors for the Listnode
public ListNode() // NO PARAMETERS
{
data = null; // data for the node
next = null; // reference to next node
}
///************************************************************
public ListNode(T initialData) // with THE DATA PARAMETER
{
data = initialData; // data for the node
next = null; // reference to next node
}
///************************************************************
public ListNode(T initialData, Listnode nextnode) // both paramters
{
data = initialData; // data for the node
next = nextNode; // reference to next node
}
60
InsertAfter
Let create the new node and put Fred in it
NEWNODE
current
fred
next
jay
next
dan
head
next
ListNode newnode = new ListNode();
newnode.data = “Fred”;
newnode.next = current.next;
current.next = newnode;
nat
next
sam
null
61
61
InsertAfter
We use constructor with one parameter
public void insertAfter(T newData)
{ // where newData = “Fred”
ListNode newnode = new ListNode();
newnode.data = newData;
// Now we have to attach newnode.next to the list
newnode.next = current.next;
current.next = newnode;
}
62
Then : Store the address in current.next into
newnode.next so they both refer to ‘jay’
NEWNODE
current
fred
next
jay
next
dan
head
next
nat
next
pvoid insertAfter(String newData)
{
ListNode newnode = new ListNode();
sam
null
newnode.data = newData;
newnode.next = current.next;
current.next = newnode;
}
63
Now, point current.next to newnode
NEWNODE
current
fred
next
jay
next
dan
head
next
nat
next
pvoid insertAfter(String newData)
{
ListNode newnode = new ListNode();
sam
null
newnode.data = newData;
newnode.next = current.next;
current.next = newnode;
}
64
64
Reduce number of lines
 public void insertAfter(String newData)
 {

ListNode newnode = new ListNode();

newnode.data = newData;
newnode.next = current.next;
current.next = newnode;


 }
 Can we reduce the first three lines of code
 in this method to one line?
65
InsertAfter

Then : Reduce the first three lines to one line
current
current
dan
head
head
jay
NEWNODE
fred
next
next
nat
next
next
20
public void insertAfter(String newData)
{ // first three lines in one line
sam
null
ListNode newnode = new ListNode(newData, current.next)
current.next = newnode;
}
66
InsertAfter - a shorter version
Then : Set the current.next to refer to the new node

current
current
dan
head
head
jay
NEWNODE
fred
next
next
nat
next
next
// Let’s compact the code all to one line:
public void insertAfter(String newData)
sam
null
{
ListNode newnode = new ListNode(newData, current.next)
current.next = newnode;
}
67
Pseudocode for Removing ListNodes
 Nodes often need to be removed from a linked list.
 As with insertion, we can
 remove a node from the front of a list,
 remove a node from elsewhere.
 We’ll look at the technique for removing a node from
the front of a linked list.
68
Removing the Head Node
head = head.next;
head
dan
next
Draw the change that this
statement will make to
the linked list.
fred
next
nat
next
sam
null
69
Removing the Head Node
head = head.next;
This points head to node after the first Node
dan
head
next
fred
next
nat
next
sam
null
70
Removing the Head Node
head = head.next; or
head = head.getNext();// if node class is separate
Now the node is deleted from the head of the list.
fred
head
nat
sam
null
dan
71
Summary
 It is easy to insert or remove a node at the front of a
list.
 You also need a technique for inserting or
removing a node elsewhere.
 We will now provide an implementation that will
 delete at the head node and also
 elsewhere on the list.
72
Deleting a node not at the head
 Deleting a node not at the head is similar to adding a
node to the middle of the list.
 current will point to the node to be deleted.
 WE also need another reference to the node that is
just before current.
 This reference is called previous :
73
Deleting from the middle calls find(target) method first
Previous refers to the node before the one to be
deleted - Current refers to node to be deleted
deleteNode()
current
previous
head
dan
fred
next
This arrow is previous.next
sam
jay
next
null
This arrow is
current.next
74
Deleting a Node
 The method remove{T data} requires that
current refer to the node to be deleted.
 Remove calls Find(T data) which assigns current
to refer to the node to be deleted.
 It also places previous on the node behind
current
75
Deleting Anywhere on the List
We call the method with: Remove(T data)
previous.next points to the node current refers
to. current.next points to the node after the node
to be deleted (“sam”).
previous
head
dan
current
fred
nat
next
next
This arrow is previous. next
sam
null
This arrow is current.next
76
Deleting from the middle
The next portion of previous now
points(refers) to the node after current.
We must also advance current to the next
node
previous
head
dan
next
fred
next
current.
nat
next
sam
null
previous.next = current.next;
current = current.next;
77
Deleting anywhere on the list
 1) previous.next now contains the address of the node (Sam) .
 2) Current is advanced to refer to the node which contains
“Sam”
NOW previous.next and current refer to same node
current.
previous
nat
fred
next
sam
next
null
previous.next = current.next;
current = current.next;
78
Removing a node The Find method puts previous and current on the
list where the node is to be deleted
public void remove(T data)
{ // remove first calls the find method
find(data);
if(current != null && previous != null)
{
previous.next = current.next;
current = current.next;
} }
79
Remove()
 The remove(T data) method works even if the
node is a tail node.
 In this case, the next of the previous node will
be assigned the null value.
80
Deleting from the list at the tail
The next portion of previous now points
to what current.next points, and current
points to null.
head
previous
dan
fred
nat
next
current
sam
null
null
previous.next = current.next;
current = current.next;
81
Pseudo-code for Removing a node
public void remove()
{
// if current and previous are not null
// point previous.next to what current.next is pointing to
// Point current to what current.next is pointing to
// else if at the head node – point head to what
//current.next is pointing to and set current
// equal to head
Always check for the Empty List FIRST
}
82
Traversing a Linked List

 To traverse a linked list, we must first assign a next
variable - such as cur - to some node.
 To traverse the list, we move cur to the next node by
using the code:
cur = cur.next // advance cur to the next node
 This assignment says
 “move cur to point to what cur.next points to” - which
advances cur to next node. Or we can use:
cur = cur.getNext{} // uses getter method for ‘next’
83
Searching a linked list
 To find a particular node in a list,
we create a method that returns the node that contains the
element. The method:
public ListNode Find(T target) { }
 searches for a node containing the target (the data)
 It returns a reference to the first node that contains the
target data.
 To call the method , use:
ListNode node = Find(target)
84
onList()
 Because Find( target) returns a ListNode, we need to
write another method that will return a boolean.
 Our application class should not have to deal with
ListNodes.
 Our methods should be implementation independent.
 The user does not have to know if we used an ArrayList
of Linked List
 So returning a boolean can be done in any class
85
 The Find (target ) method returns a ListNode
public ListNode find (target)
 This is necessary for some methods that use it.
 However, outside classes will not know what a
Listnode is. SO
 We write another Find method for the outside
classes that returns a boolean
public boolean find (target)
86
Searching / traversing a list.
public boolean Find(T target)
{
// this is how you traverse a linked list
boolean found = false;
ListNode curr; // declare variable to traverse the list
for(curr = head; curr!= null; curr= curr.getNext())
{
// put in code to find target and return true if found
} // close loop
return found ;
}// close method
87
Doubly Linked Lists
 Doubly linked lists have a pointer to the preceding
item as well as one to the next.
 They permit scanning or searching of the list in both
directions.
 (To go backwards in a simple list, it is necessary to go
back to the start and scan forwards.)
 Many applications require searching backwards and
forwards through sections of a list:
88
Linked Lists - Doubly linked
 Doubly linked lists
 Can be scanned in both directions
public ListNode(T initialData,)
{
data = initialData;
Listnode previous, next;
}
head
prev next
prev
prev
tail
89
Doubly Linked Lists

 In this case, the node structure is altered to have two
links:
class ListNode
{
T data;
ListNode previous, next; // link to node before
}
// and after
90
Circularly Linked Lists
 By ensuring that the tail of the list is always
pointing to the head,
 we can build a circularly linked list.
 A circularly linked list would more likely be used in
an application which required "round-robin"
scheduling or processing.
91
Analysis of Linked Operations
 Since the order is irrelevant, and there is no
capacity to expand
 adding an element to the List is O(1)
 Removing a particular element, because it must
be found, is O(n)
 Removing any item, can be done at the
head or tail and thus is O(1);
92
Linked List
 The linked list implementation has exchanged
flexibility for efficiency –
 On some systems, the need to allocate memory can
be relatively expensive.
 Pre-allocation in the array-based implementation is
generally more efficient.
 BUT, there are circumstances where Linked List is
needed.
93
LINKED LIST VS ARRAY
 However, there are many situations where a linked
list is more efficient e.g.
 Applications that are unsorted - WHY?
 Applications where the size is relatively small .
WHY?
 More examples of such trade-offs will be found
later.
94
Free Memory
 Memory is just an array of data.
 Each entry has an address and a value
 After a series of memory allocations and
de-allocations, there are blocks of free memory
scattered throughout the available heap space.
95
Memory allocation
 In order to be able to re-use this memory,
 memory allocators will link freed blocks
together in a free memory list
 The computer keeps references to blocks of
free memory
96
Free Memory
 An external pointer(head) points to the first block in
the free list.
 When a new block of memory is requested,
 the allocator scans the free list looking for a suitable
block
 It will delete the block from the free list
 (re-linking the free list around the deleted block).
97
Free Memory
 Many variations of memory allocators have
been proposed:
 Refer to a text on operating systems or
implementation of functional languages for
more details.
 The entry in the index under garbage collection
will address it.
98
Abstract Data Types
 An abstract data type defines a type of
structure that stores data ( e.g. an array)
 It stores the data in a class along with the
operations that can be performed on that data
 e.g. An ArrayList, A LinkedList, a Stack, A Graph
etc.
99
Abstract Data TYPE
 The Abstract Data Type lists a set of abstract
methods
 Each class that implements the ADT must
implement all these methods.
 E.g. in the List interface has methods like:

add, delete etc.
100
Cohesion
 Well- designed ADT’s have strong relationships
between the parts of a class so
 Cohesion is a goal that you should seek in
designing your ADT’s
101
Well-designed ADT’s have little or no coupling
 To create our Abstract Data Type we need to be sure
that the methods are cohesive.
 Coupling measures the strength of the relationship
between two components.
 It represents the glue that holds two separate
components together.
 This should be minimal in an object-
oriented program
102
Coupling and Cohesion
 We want to minimize
the degree of coupling
between any two classes of our system
 so they can operate as
independently as possible.
 Thus any changes we make will only effect a small
portion of the program.
 ALL the methods for the Linked List should be in the
Linked List class.
103
CLASS INDEPENDENCE FROM OTHER CLASsES
 This makes errors easier to track
 and less likely to affect
 another part of our system.
104
Coupling and Cohesion
 We want to maximize the cohesion in a class
 Cohesion means that the more tightly related the
parts of an item are
 the more logical its operations are.
 Coupling means that an object depends on another
class for some of its operations or data
 This creates systems that are very difficult to debug
105
ADT’s
 Cohesion is the strength of the relationships
among the parts of one component
 so that the parts of the component can be
thought of as one piece.
 E.g. in a Client class, we would have a firstname
and lastname etc. but not have a reference to
another client defined inside it.
106
Objectives
 Your goals are:
1. a method should only accomplish one logical
function
2. an object should represent a single concept or
entity. A Student , A Client
An ADT by its definition minimizes the coupling between
objects.
107