Download COSC 2006 Data Structures I

Document related concepts

Quadtree wikipedia , lookup

Red–black tree wikipedia , lookup

Lattice model (finance) wikipedia , lookup

Interval tree wikipedia , lookup

Binary tree wikipedia , lookup

Binary search tree wikipedia , lookup

B-tree wikipedia , lookup

Linked list wikipedia , lookup

Transcript
COSC 2006: Data Structures I
Low Level List Processing
5/24/2017
BGA
1
Arrays and linked structures (1)
Array and Linked structures can both be used to
represent a sequence of elements.
An array, through its index, can also provide
random access to its elements so locating an
element is an O(1) operation.
A linked structure consists of elements (nodes)
having a data part and a link (reference) to the
the next node so locating an element at a given
position is an O(n) operation (traversal).
5/24/2017
BGA
2
Arrays and linked structures (2)
Arrays are not dynamic: their size is fixed
To extend the size of an array dynamically it is
necessary to



create a bigger array
copy existing elements to it
delete the original array
This can be inefficient in cases where the storage
needed grows or shrinks with time.
Linked structures are dynamic and can easily
grow and shrink automatically with time.
5/24/2017
BGA
3
Arrays and linked structures (3)
Inserting and removing elements from an array
are both O(n) operations.
For a linked list they are O(1) operations.
Linked lists are more efficient than arrays in case
there are a lot of insertions and deletions to be
made over time and the processing required is
mostly sequential rather than random access.
5/24/2017
BGA
4
Picture of a node
A node consists of a data part which is normally a
reference to an object and a link part which
contains a reference to the next node in the list.
References are denoted by arrows (box and
arrow notation):
objec
t
e
primitive type
5/24/2017
object type
BGA
To save space in
diagrams we often
use the primitive
type notation in
the object case and
interpret d as a
reference.
5
Picture of a linked structure
A linked list structure is obtained by linking some
nodes together sequentially. The last node in the
list is indicated by a null reference and the head
or first element of the list is indicated by a
reference to the first node:
Here e0,e1,... are either primitive values or
references to objects.
e0
e1
e2
e3
head
5/24/2017
BGA
6
Low level linked list operations
A linked list structure or sequence can be used at
a high-level.
We do this later by writing a LinkedList class.
It can also be viewed at a low level by
manipulating links and nodes directly to add and
remove nodes and traverse the structure.
It is useful to understand this approach if we
want to write linked implementations of other
data types such as stacks and queues.
5/24/2017
BGA
7
Low-level testing example
We will illustrate low-level operations using a
Book class and a generic node class.
To experiment with the low-level operations we
write a tester class called
LowLevelListTester that has the generic
node class as an inner class
Then we can write methods in the outer class to



5/24/2017
construct lists,
add and remove elements at various positions
write list traversals
BGA
8
LowLevelListTester structure
The LowLevelListTester class consists of an inner Node class
and test methods that illustrate and test low level list operations
public class LowLevelListTester
{
public void doTest01(String title) {...}
public void doTest02(String title) {...}
// ...
public static void main(String[] args)
{ LowLevelListTester tester =
new LowLevelListTester();
tester.doTest01("description");
// ...
}
private static class Node<E> {...}
}
5/24/2017
BGA
9
Inner Node class (1)
Node is a generic class for nodes of any object type. Each node
has a data field and a next field
private static class Node<E>
{
private E data;
private Node<E> next;
// constructor with given data and next link
public Node(E data, Node<E> next)
{
this.data = data;
thus.next = next;
}
// continued on next slide
5/24/2017
BGA
10
Inner Node class (2)
Default constructor can call the general one.
We also provide a toString method that can be used to display a
list beginning at this node
public Node()
{
this(null, null);
}
Don't need get
and set methods
since this is an
inner class
// toString on next slide
5/24/2017
BGA
11
Inner Node class (3)
The toString method uses a list traversal beginning at "this"
public String toString()
{ StringBuilder s = new StringBuilder();
s.append("[");
Node<E> cursor = this; // start at head of list
while (cursor != null)
{ if (cursor.next != null) // second last node
{ s.append(cursor.data.toString());
s.append(",\n");
}
else
s.append(cursor.data.toString());
cursor = cursor.next; // advance to next node
}
s.append("]");
return s.toString();
}
5/24/2017
BGA
12
Book class (1)
It can be used for testing low-level operations.
Other classes could also be used.
public class Book implements Comparable<Book>
{
private String title;
private String author;
private double price;
private int inStock; // number available
public Book(String title, String author,
double price, int inStock)
{
this.title = title; this.author = author;
this.price = price; this.inStock = inStock;
}
5/24/2017
BGA
13
Book class (2)
Get methods for returning data fields
public String getTitle()
{ return title;
}
public String getAuthor()
{ return author;
}
public double getPrice()
{ return price;
}
public int getInStock()
{ return inStock;
}
5/24/2017
BGA
14
Book class (3)
compareTo implements the Comparable<Book> interface.
Here we use only the title to compare books.
public String toString()
{
return "Book[" + title
+ "," + author + "," + price
+ "," + inStock + "]";
}
// use String class compareTo
public int compareTo(Book b)
{
return title.compareTo(b.title);
}
5/24/2017
BGA
15
Book class (4)
The equals method compares only the title of the books. Here we
try out the getClass() method which returns the class name of the
object instead of using instance of which cannot distinguish
different classes in an inheritance hierarchy (returns true for all
the subclasses)
public boolean equals(Object obj)
{
if (obj == null) ||
getClass() != obj.getClass())
return false;
return title.equals( ((Book) obj).title);
}
} // end of Book class
5/24/2017
BGA
16
Constructing Nodes
Node<Book> node = new Node<Book>(null,null);
Node<Book> node =
new Node<Book>(null, anotherNode);
Book b = new Book(...);
Node<Book> node =
new Node<Book(b, null);
objec
t
Book b = new Book(...);
Node<Book> node =
new Node<Book>(b, anotherNode);
objec
t
5/24/2017
BGA
17
Constructing a linked list (1)
b0
list
To save space we have
not shown the objects
referenced by b0,b1,b2
and b3
b0
b1
list
New elements are
added to the end of
the list
b0
b1
b2
b0
b1
b2
(a)
(b)
(c)
list
(d)
b3
list
5/24/2017
BGA
18
Constructing a linked list (2)
Construct some book objects
Book
Book
Book
Book
b0
b1
b2
b3
=
=
=
=
new
new
new
new
Book("Title
Book("Title
Book("Title
Book("Title
0","Author
1","Author
2","Author
3","Author
0",39.95,10);
1",67.50,50);
2",23.49,12);
3",15.60,17);
Link them together by adding new books at tail end
Node<book> head = new Node<Book>(b0, null);
head.next = new Node<Book>(b1, null);
head.next.next = new Node<Book>(b2, null);
head.next.next.next = new Node<Book>(b3, null);
5/24/2017
BGA
19
Constructing a linked list (3)
Can do it in one step
Node<Book> list =
new Node<Book>(b0, new Node<Book>(b1,
new Node<Book>(b2, new Node<Book>(b3, null))));
5/24/2017
BGA
20
Inserting at head of list (1)
b0
b1
b2
b3
head
b0
b1
b2
b3
head
b
head = new Node<Book>(b, head);
5/24/2017
BGA
21
Inserting at head of list (2)
public void doTest03(String title)
{
System.out.println();
System.out.println(title);
Book b = new Book("New Title", "New Author",
39.95, 10);
Node<Book> head =
new Node<Book>(b0, new Node<Book>(b1,
new Node<Book>(b2, new Node<Book>(b3,null))));
head = new Node<Book>(b, head);
System.out.println(head);
}
5/24/2017
BGA
22
Inserting after first node (1)
current
b0
b1
b2
b3
head
newNode
current
b0
b1
b2
b3
head
b
step 2
5/24/2017
step 1
BGA
23
Inserting after first node (2)
Inserting b after first node:
[b0, b1, b2, b3] becomes [b0, b, b1, b2, b3]
Node<Book> current = head;
Node<Book> newNode = new Node<Book>(b, current.next);
current.next = newNode;
This can be done more directly using
Node<book> current = head;
current.next = new Node<Book>(b, current.next);
5/24/2017
BGA
24
Inserting b after 2nd node (1)
current
b0
b1
b2
b3
head
newNode
current
b0
b1
b2
b3
head
b
Step 2
Step 1
5/24/2017
BGA
25
Inserting b after 2nd node (2)
Inserting b after second node:
[b0, b1, b2, b3] becomes [b0, b1, b, b2, b3]
Node<Book> current = head.next;
Node<Book> newNode = new Node<Book>(b, current.next);
current.next = newNode;
This can be done more directly using
Node<Book> current = head.next;
current.next = new Node<Book>(b, current.next);
5/24/2017
BGA
26
Inserting b at end of list (1)
current
b0
b1
b2
b3
head
newNode
b0
b1
b2
b3
b
head
5/24/2017
BGA
current
27
Inserting b at end of list (2)
Inserting b at end of list:
[b0, b1, b2, b3] becomes [b0, b1, b2, b3, b]
Node<Book> current = head.next.next.next;
Node<Book> newNode = new Node<Book>(b, null);
current.next = newNode;
This can be done more directly using
Node<Book> current = head.next.next.next;
current.next = new Node<Book>(b, null);
5/24/2017
BGA
28
Delete the first node (1)
b0
b1
b2
b3
head
head
orpha
n
b0
5/24/2017
b1
BGA
b2
b3
29
Delete the first node (2)
Delete the first node of the list:
[b0, b1, b2, b3] becomes [b1, b2, b3]
This is easy: just skip over the first node so that head references
the second node
head = head.next;
5/24/2017
BGA
30
Delete the second node (1)
previous
current
b0
b1
b2
b3
head
orpha
n
previous
b0
b1
current
b2
b3
head
5/24/2017
BGA
31
Delete the second node (2)
Delete the second node of the list:
[b0, b1, b2, b3] becomes [b0, b2, b3]
Get references to node previous to b1, and to b1
Node<Book> previous = head; // node before b1
Node<Book> current = head.next; // b1
Skip over b1.
Make b2 the new current node
previous.next = current.next; // skip over b1
current = current.next;
5/24/2017
BGA
32
Delete the last node (1)
previous
b0
b1
b2
b3
head
orpha
n
b0
b1
b2
b3
head
5/24/2017
BGA
33
Delete the last node (2)
Delete the last node of the list:
[b0, b1, b2, b3] becomes [b0, b1, b2]
This is easy only if we have a reference to the previous
node, otherwise a traversal is needed.
head.next.next.next = null;
Given previous it is we can just make the assigment
previous.next = null;
5/24/2017
BGA
34
Traversals
Processing a collection such as a linked structure
from the first element (head) to the last element
(tail) in sequence is called a traversal.
While and for loops can be used to traverse a list
Lists are ordered structures so the traversal visits
them in order one element at a time
Unordered collections such as a set or a bag can
also be traversed in some arbitrary order.
5/24/2017
BGA
35
Simple list traversal model
Assume that list is a reference to the first node in a list.
The following while loop can be used to traverse the list
current = head;
while (current != null)
{
// process the list element here
current = current.next;// move to next element
}
5/24/2017
BGA
36
Simple list traversal model (1)
each time through the loop current
references the next node in the list
current
e0
e1
e2
e3
head
5/24/2017
BGA
37
Simple list traversal model (2)
each time through the loop current
references the next node in the list
current
e0
e1
e2
e3
head
5/24/2017
BGA
38
Simple list traversal model (3)
each time through the loop current
references the next node in the list
current
e0
e1
e2
e3
head
5/24/2017
BGA
39
Simple list traversal model (4)
each time through the loop current
references the next node in the list
current
e0
e1
e2
e3
head
5/24/2017
BGA
40
toString in Node class
The toString method in the Node<E> class is a list traversal
public String toString()
{ StringBuilder s = new StringBuilder();
s.append("[");
Node<E> cursor = this; // head of "this" list
while (cursor != null)
{ if (cursor.next != null) // second last element
{ s.append(cursor.data.toString());
s.append(",\n");
}
else
s.append(cursor.data.toString());
cursor = cursor.next;
}
s.append("]");
return s.toString();
}
5/24/2017
BGA
41
Print a list
Print a list one item per line (similar to toString) . Here we are in
the outer class LowLevelListTester
Node<Book> cursor = head;
while (cursor != null)
{
System.out.println(cursor.data);
cursor = cursor.next;
}
5/24/2017
BGA
42
Finding data in a list (1)
A method to search a given list for a given element
private static <E> boolean find(E element,
Node<E> head)
{
Node<E> cursor = head;
while (cursor != null &&
! element.equals(cursor.data))
cursor = cursor.next;
return cursor != null;
}
The node could also be returned here with null indicating that
the element was not found in the list.
5/24/2017
BGA
43
Finding data in a list (2)
A method to search a given list for a book given its 0-based
position k in the range 0,1,2,3,... (could also return the node)
private static <E> E find(int k, Node<E> head)
{ // Here we assume index k is in range
int position = k;
Node<E> cursor = head;
while (position > 0)
{
cursor = cursor.next;
position--;
}
return cursor.data; // (inner class)
}
5/24/2017
BGA
44
Insert at end of list
This is the general case of insertion at end of list. Unless the head
is null it is necessary to traverse the list to find the tail reference
private static <E> Node<E> insertAtEnd(
Node<E> list, E element)
{ Node<E> head = list;
Node<E> newNode = new Node<E>(element, null);
if (head == null)
head = newNode
else // find a reference to the tail node
{ Node<E> cursor = head;
while (cursor.next != null)
cursor = cursor.next;
cursor.next = newNode;
}
return head;
}
5/24/2017
BGA
45
Delete tail of list (1a)
General case of deleting the tail of the list.
We return the new list with the tail deleted.
private static <E> Node<E> removeTail(Node<E> list)
{ // Assume that the list is not empty
Node<E> head = list;
if (head.next == null) // one-element list
{ head = null; // remove element from one-element list
}
else
{ Node<E> previous = null; Node<E> current = head;
while (current.next != null)
{ previous = current; current = current.next;
}
previous.next = null; // remove the tail
}
return head;
}
5/24/2017
BGA
46
Delete tail of list (1b)
General case of deleting the tail of the list.
This version doesn't use the current reference, only previous
private static <E> Node<E> removeTail2(Node<E> list)
{ // Assume that the list is not empty
Node<E> head = list;
if (head.next == null) // one-element list
{ head = null; // remove element from one-element list
}
else // find second last node
{ Node<E> previous = head;
while (previous.next.next != null)
{ previous = previous.next;
}
previous.next = null; // remove the tail
}
return head;
}
5/24/2017
BGA
47
Delete tail of list (2)
previous
current
e0
e1
e2
e3
head
5/24/2017
BGA
48
Delete tail of list (3)
previous
current
e0
e1
e2
e3
head
5/24/2017
BGA
49
Delete tail of list (4)
previous
current
e0
e1
e2
e3
head
5/24/2017
BGA
50
Delete tail of list (5)
previous
current
e0
e1
e2
e3
head
5/24/2017
BGA
51
Delete tail of list (6)
previous
current
e0
e1
e2
e3
head
5/24/2017
BGA
52
Delete tail of list (7)
orpha
n
e0
e1
e2
e3
head
5/24/2017
BGA
53
Delete tail of list (8)
General case of deleting the tail of the list.
This version doesn't use the current reference, only previous
private static <E> Node<E> removeTail2(Node<E> list)
{ // Assume that the list is not empty
Node<E> head = list;
if (head.next == null) // one-element list
{ head = null; // remove element from one-element list
}
else // find second last node
{ Node<E> previous = head;
while (previous.next.next != null)
{ previous = previous.next;
}
previous.next = null; // remove the tail
}
return head;
}
5/24/2017
BGA
54
Insert at given index
Given an index k (0,1,2,...) insert a new node at position k.
Element previously at index k is now at position k + 1
private static <E> Node<E> insert(Node<E> list,
E element, int k)
{ Node<E> head = list; int index = k;
if (head == null || index <= 0) // insert at head
head = new Node<E>(element, head);
else
{ Node<E> cursor = head;
while (index > 1 && cursor.next != null)
{ cursor = cursor.next;
index--;
}
cursor.next = new Node<E>(element, cursor.next);
}
return head;
}
5/24/2017
BGA
55
Delete at given index (1)
Given an index k (0,1,2,...) delete the node at position k. Element
previously at index k+1 is now at position k
private static <E> Node<E> remove(Node<E> list, int k)
{ Node<E> head = list; int index = k;
if (index <= 0)
{ head = head.next; // remove first node
}
else
{ Node<E> previous = null; Node<E> current = head;
while (index > 0 && current.next != null)
{ previous = current; current = current.next;
index--;
}
previous.next = current.next;
}
return head;
}
5/24/2017
BGA
56
Delete at given index (2)
This version of remove does not use the current reference
private static <E> Node<E> remove2(Node<E> list, int k)
{ Node<E> head = list;
int index = k;
if (index <= 0)
{ head = head.next; // remove first node
}
else
{ Node<E> previous = head;
while (index > 1 && previous.next.next != null)
{ previous = previous.next;
index--;
}
previous.next = previous.next.next;
}
return head;
}
5/24/2017
BGA
57
length of a list
Use standard traversal and count the number of elements
traversed
private static <E> int length(Node<E> list)
{
Node<E> head = list;
int count = 0;
while (current != null)
{
count++;
current = current.next;
}
return count;
}
5/24/2017
BGA
58
Total value of all books
Write a method that computes the total value of
all books in a list
Prototype is

5/24/2017
private static double
totalValue(Node<Book> list)
BGA
59
Delete books not in stock (1)
Write a low-level method with prototype

private static Node<Book> deleteBooks(
Node<Book> list)
The method should delete from the list all books
whose inStock value is 0
Put your method in the LowLevelListTester
class. It shouldn't use any of the other static
methods in this class
5/24/2017
BGA
60
Delete books not in stock (2)
Basic structure (finish it yourself)
private static Node<Book> deleteBooks(Node<Book> list)
{ Node<Book> first = list;
Node<Book> current = first;
Node<Book> previous = null;
while (current != null)
{
if (current.data.getInstock() == 0)
{ // delete this node
}
else
{ // move to next node in the list
}
}
return first; // reference to the list
}
5/24/2017
BGA
61
Append two lists
Write a method with prototype

private static <E> Node<E> append(
Node<E> list1, Node<E> list2)
The method returns a list obtained by putting
list2 on the end of list1 (concatenation)
Put your method in LowLevelListTester
5/24/2017
BGA
62
Reverse a list
Write a low-level method with prototype

private static <E> Node<E> reverse(
Node<E> list)
The method should return a list that is the
reverse of list.
Put your method in the LowLevelListTester
class.
5/24/2017
BGA
63
Replace operation (1)
Write a low-level method that replaces the first
occurrence of an object in a list with a new
object.
Prototype is

5/24/2017
private static <E> Node<E> replace(
Node<E> list, E element,
E newElement)
BGA
64
Replace operation (2)
Write a low-level method that replaces the object
at index i (0,1,...) with a new object.
Prototype is

5/24/2017
private static <E> Node<E> replace(
Node<E> list, int k,
E newElement)
BGA
65
Code slide
Use box like this for comment
Put code here
5/24/2017
BGA
66