Download Chapter 19 Java Data Structures

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

Bloom filter wikipedia , lookup

Lattice model (finance) wikipedia , lookup

Red–black tree wikipedia , lookup

Quadtree wikipedia , lookup

Interval tree wikipedia , lookup

Binary search tree wikipedia , lookup

Array data structure wikipedia , lookup

B-tree wikipedia , lookup

Linked list wikipedia , lookup

Transcript
Chapter 24
Lists
Stacks
and
Queues
1
Objectives
To design list with interface and abstract class
(§24.2).
 To design and implement a dynamic list using an
array (§24.3).
 To design and implement a dynamic list using a
linked structure (§24.4).
 To design and implement a stack using an array list
(§24.5).
 To design and implement a queue using a linked
list (§24.6).
 To evaluate expressions using stacks (§24.7).

2
What is a Data Structure?
A collection
of data organized in some fashion
– Stores data
– Supports the operations for manipulating data in the
structure

array is a data structure
–
–
–
–
–
–
–
holds a collection of data in sequential order
can find the size of the array
store,
retrieve,
modify data in the array
Array is simple and easy to use
has two limitations:
3
Limitations of arrays


Once an array is created, its size cannot be
altered
Array provides inadequate support for:
–
–
–
–
inserting,
deleting,
sorting,
searching operations
4
Object-Oriented Data Structure
In
object-oriented thinking:
– A data structure:


is an object that stores other objects referred to as data or elements
So some people refer a data structure as:
–
–
–
–
a container object
a collection object
To define a data structure is essentially to declare a class
The class for a data structure:
• should use data fields to store data
• provide methods to support operations such as insertion and deletion
– To create a data structure is therefore to create an instance from the class
– You can then apply the methods on the instance to manipulate the data
structure such as inserting an element to the data structure or deleting an
element from the data structure.
5
Four Classic Data Structures

Introduce four classic dynamic data structures:
– Lists:
A list is a collection of data stored sequentially
 It supports insertion and deletion anywhere in the list

– Stacks:
Can be perceived as a special type of the list
 Insertions and deletions take place only at the one end
 referred to as the top of a stack

– Queues:
Represents a waiting list
 Insertions take place at the back, also referred to as the tail of a queue
 Deletions take place from the front, also referred to as head of a queue

– binary trees:

A binary tree is a data structure to support:
– searching, sorting, inserting, and deleting data efficiently
6
Lists
A data
–
–
–
–
–
–
structure to store data in sequential order
list of students
list of available rooms
a list of cities
a list of books
can be stored using lists
The common operations on a list are usually the following:
Retrieve an element from this list
 Insert a new element to this list
 Delete an element from this list
 Find how many elements are in this list
 Find if an element is in this list
 Find if this list is empty

7
Two Ways to Implement Lists

Use an array to store the elements
–
–
–
–

array is dynamically created
If the capacity of the array is exceeded
create a new larger array
copy all the elements from current array to new array
Use a linked structure
– A linked structure consists of nodes
– Each node is dynamically created to hold an element
– All the nodes are linked together to form a list
8
Design of ArrayList and LinkedList
For
–
–
–
–
–
–
–
–
convenience, let’s name these two classes:
MyArrayList
MyLinkedList
These two classes have common operations, but different data fields
Common operations can be generalized in an interface or an abstract class
A good strategy is to combine the virtues of interfaces and abstract classes
Provide both interface and abstract class in the design
User can use interface or abstract class whichever is convenient
Such an abstract class is known as a convenience class
MyArrayList
MyList
MyAbstractList
MyLinkedList
9
MyList Interface and MyAbstractList Class
«interface»
MyList<E>
+add(e: E) : void
Appends a new element at the end of this list.
+add(index: int, e: E) : void
Adds a new element at the specified index in this list.
+clear(): void
Removes all the elements from this list.
+contains(e: E): boolean
Returns true if this list contains the element.
+get(index: int) : E
Returns the element from this list at the specified index.
+indexOf(e: E) : int
Returns the index of the first matching element in this list.
+isEmpty(): boolean
Returns true if this list contains no elements.
+lastIndexOf(e: E) : int
Returns the index of the last matching element in this list.
+remove(e: E): boolean
Removes the element from this list.
+size(): int
Returns the number of elements in this list.
+remove(index: int) : E
Removes the element at the specified index and returns the
removed element.
+set(index: int, e: E) : E
Sets the element at the specified index and returns the
element you are replacing.
MyAbstractList<E>
#size: int
The size of the list.
#MyAbstractList()
Creates a default list.
#MyAbstractList(objects: E[])
Creates a list from an array of objects.
+add(e: E) : void
Implements the add method.
+isEmpty(): boolean
Implements the isEmpty method.
+size(): int
Implements the size method.
+remove(e: E): boolean
Implements the remove method.
MyList
MyAbstractList
10
Array Lists
 Array
is a fixed-size data structure
 Once an array is created, its size cannot be changed
 you can use array to implement dynamic data structures
 trick is to create a new larger array to replace the current
array if the current array cannot hold new elements in the
list
 Initially, an array, say data of Object[] type, is created
with a default size
 When inserting a new element into the array, first ensure
there is enough room in the array
 If not, create a new array with the size as twice as the
current one
Copy the elements from the current array to the new array
 new array now becomes the current array
11
Insertion
 Before inserting a new element at a specified index
shift all the elements after the index to the right and
increase the list size by 1

Before inserting
e at insertion point i
0
e0 e1
e
After inserting
e at insertion point i,
list size is
incremented by 1
1
…
i
… ei-1 ei
i+1 …
k-1 k
…
ek-1 ek
ei+1
Insertion point
0
1
e0 e 1
…
i
… ei-1 e
data.length -1
…shift…
i+1 i+2 …
ei
e inserted here
ei+1
…
k
k+1
ek-1 ek
data.length -1
12
Deletion
To remove an element at a specified index
 Shift all the elements after the index to the left by one
position and decrease the list size by 1.

Before deleting the
element at index i
0
1
e0 e1
…
i
… ei-1 ei
Delete this element
After deleting the
element, list size is
decremented by 1
0
1
e0 e 1
…
i
… ei-1 ei+1
i+1 …
k-1 k
…
ek-1 ek
ei+1
…shift…
…
…
data.length -1
k-2 k-1
ek-1 ek
data.length -1
13
Implementing MyArrayList
MyAbstractList<E>
MyArrayList<E>
-data: E[]
+MyArrayList()
Creates a default array list.
+MyArrayList(objects: E[])
Creates an array list from an array of objects.
-ensureCapacity(): void
Doubles the current array size if needed.
MyArrayList
TestList
Run
14
Linked Lists

MyArrayList –
– is implemented using an array
– get (int index)

accessing array elements
– set (int index, Object o)

modifying an element through an index
– add (Object o)

adding an element at the end of the list are efficient
– methods
add(int index, Object o)
 remove(int index) are inefficient
 it requires shifting potentially a large number of elements
 You can use a linked structure to implement a list to improve efficiency
for adding and removing an element anywhere in a list

15
Nodes in Linked Lists
A linked
list consists of nodes
 Each node contains an element
 each node is linked to its next neighbor
 a node can be defined as a class, as follows:
head
Node 1
Node 2
element
element
next
next
Node n
…
element
tail
null
class Node<E> {
E element;
Node next;
public Node(E o) {
element = o;
16
Adding Three Nodes
variable head refers to the first node in the list
 variable tail refers to the last node in the list
 If the list is empty, both are null
 can create three nodes to store three strings in a
list, as follows:

Step 1: Declare head and tail:
Node<String> head = null;
Node<String> tail = null;
The list is empty now
17
Adding Three Nodes
Step 2: Create the first node and insert it to the list:
head = new Node<String>("Chicago");
tail = head;
After the first node is inserted
inserted
"Chicago"
head
tail
next: null
18
Adding Three Nodes

Step 3:
– Create the second node and insert it to the list:
tail
tail.next = new Node<String>("Denver");
head
"Chicago"
"Denver"
next
next: null
tail
tail = tail.next;
head
"Chicago"
"Denver"
next
next: null
19
Adding Three Nodes
Step
4:
– Create the third node and insert it to the list:
tail
tail.next =
new Node<String>("Dallas");
head
"Chicago"
"Denver"
"Dallas"
next
next
next: null
tail
tail = tail.next;
head
"Chicago"
"Denver"
"Dallas"
next
next
next: null
20
Traversing All Elements in the List
Each
node –
– contains the element and a data field named next
– next points to the next element
– If the node is the last in the list, its pointer data field
next contains the value null
– You can use this property to detect the last node
– For example, you may write the following loop to
traverse all the nodes in the list
Node<E> current = head;
while (current != null) {
System.out.println(current.element);
current = current.next;
}
21
MyLinkedList
MyAbstractList<E>
Node<E>
element: E
next: Node<E>
m
1
MyLinkedList<E>
-head: Node<E>
-tail: Node<E>
1
Link
+MyLinkedList()
Creates a default linked list.
+MyLinkedList(objects: E[])
Creates a linked list from an array of objects.
+addFirst(e: E): void
Adds the object to the head of the list.
+addLast(e: E): void
Adds the object to the tail of the list.
+getFirst(): E
Returns the first object in the list.
+getLast(): E
Returns the last object in the list.
+removeFirst(): E
Removes the first object from the list.
+removeLast(): E
Removes the last object from the list.
MyLinkedList
22
Implementing addFirst(E o)
public void addFirst(E o) {
Node<E> newNode = new Node<E>(o);
newNode.next = head;
head = newNode;
size++;
if (tail == null)
tail = head;
head
}
e0
tail
…
next
A new node
to be inserted
element
here
next
ei
ei+1
next
next
…
ek
null
(a) Before a new node is inserted.
head
tail
element
e0
next
next
New node inserted here
…
ei
ei+1
next
next
…
ek
null
(b) After a new node is inserted.
23
Implementing addLast(E o)
public void addLast(E o) {
if (tail == null) {
head = tail = new Node<E>(element);
}
else {
tail.next = new Node(element);
tail = tail.next;
}
head
size++;
}
e0
tail
…
next
ei
ei+1
next
next
…
ek
null
A new node
to be inserted
here
(a) Before a new node is inserted.
o
null
head
e0
next
tail
…
ei
ei+1
next
next
(b) After a new node is inserted.
…
ek
o
next
null
New node inserted here
24
Implementing add(int index, E o)
public void add(int index, E o) {
if (index == 0) addFirst(o);
else if (index >= size) addLast(o);
else {
Node<E> current = head;
for (int i = 1; i < index; i++)
current = current.next;
Node<E> temp = current.next;
current.next = new Node<E>(o);
(current.next).next = temp;
size++;
}
}
head
…
e0
next
current
temp
ei
ei+1
next
next
A new node
to be inserted
here
e
tail
…
ek
null
(a) Before a new node is inserted.
null
head
e0
current
temp
ei
ei+1
next
next
…
next
A new node
is inserted in
the list
e
tail
…
ek
null
(b) After a new node is inserted.
next
25
Implementing removeFirst()
public E removeFirst() {
if (size == 0) return null;
else {
Node<E> temp = head;
head = head.next;
size--;
if (head == null) tail = null;
return temp.element;
}
}
tail
head
e0
e1
next
next
…
Delete this node
ei
ei+1
next
next
…
null
(a) Before the node is deleted.
head
e1
next
ek
tail
…
ei
ei+1
next
next
…
ek
null
(b) After the first node is deleted
26
public E removeLast() {
if (size == 0) return null;
else if (size == 1)
{
Node<E> temp = head;
head = tail = null;
size = 0;
return temp.element;
}
else
{
Node<E> current = head;
for (int i = 0; i < size - 2; i++)
current = current.next;
Node temp = tail;
tail = current;
tail.next = null;
size--;
return temp.element;
}
}
Implementing
removeLast()
tail
current
head
…
e0
e1
next
next
ek-2
ek-1
ek
next
next
null
(a) Before the node is deleted.
Delete this node
tail
head
…
e0
e1
next
next
ek-2
ek-1
next
null
(b) After the last node is deleted
27
Implementing remove(int index)
public E remove(int index) {
if (index < 0 || index >= size) return null;
else if (index == 0) return removeFirst();
else if (index == size - 1) return removeLast();
else {
Node<E> previous = head;
for (int i = 1; i < index; i++) {
head
previous = previous.next;
…
element
}
Node<E> current = previous.next;next
previous.next = current.next;
size--;
return current.element;
head
}
}
…
element
next
previous
current
current.next
element
element
element
next
next
next
tail
…
element
null
Node to be deleted
(a) Before the node is deleted.
previous
current.next
element
element
next
next
tail
…
element
null
(b) After the node is deleted.
28
Circular Linked Lists

A circular, singly linked list is like a singly
linked list, except that the pointer of the last node
points back to the first node.
head
Node 1
Node 2
element
element
next
next
Node n
…
element
tail
next
29
Doubly Linked Lists

A doubly linked list –
– contains the nodes with two pointers
– One points to the next node and the other points to the
previous node
– these two pointers are conveniently called a forward pointer
and a backward pointer
– So, a doubly linked list can be traversed forward and
backward
head
Node 1
Node 2
element
element
next
next
null
null
previous
previous
Node n
…
element
tail
30
Circular Doubly Linked Lists

A circular, doubly linked list is doubly linked
list, except that the forward pointer of the last
node points to the first node and the backward
pointer of the first pointer points to the last node
head
Node 1
Node 2
element
element
next
next
next
previous
previous
previous
Node n
…
element
tail
31
Stacks
A stack
– can be viewed as a special type of list
– elements are accessed, inserted, and deleted only
from the end, called the top, of the stack
Data1
Data2
Data3
Data2
Data1
Data1
Data3
Data2
Data2
Data1
Data3
Data2
Data1
Data1
Data1
32
Queues
A queue
–
–
–
–
–
represents a waiting list
can be viewed as a special type of list
elements are inserted into the end (tail) of the queue
Elements are accessed/deleted from beginning of queue (head)
Data1
Data2
Data3
Data2
Data1
Data1
Data3
Data2
Data1
Data3
Data3
Data2
Data1
Data2
Data3
33
Implementing Stacks and Queues
Using
an array list to implement Stack
Use a linked list to implement Queue
 Insertion and deletion operations on a stack are made
only at the end of the stack
– using an array list to implement a stack is more efficient than a
linked list

deletions are made at the beginning of queue
– it is more efficient to implement a queue using a linked list
than an array list

Implement:
– a stack class using an array list
– a queue using a linked list
34
Design of the Stack and Queue Classes
There are two ways to design the stack and queue classes:
– Using inheritance:

MyArrayList
You can declare the stack class by extending the array list class, and
the queue class by extending the linked list class.
MyStack
MyLinkedList
MyQueue
– Using composition:

You can declare an array list as a data field in the stack class, and a
linked list as a data field in the queue class.
MyStack
MyArrayList
MyQueue
MyLinkedList
35
Composition is Better

Both designs are fine –
– using composition is better because it enables you to declare
a complete new stack class and queue class without
inheriting the unnecessary and inappropriate methods from
the array list and linked list
36
MyStack and MyQueue
MyStack
MyStack
-list: MyArrayList
+isEmpty(): boolean
Returns true if this stack is empty.
+getSize(): int
Returns the number of elements in this stack.
+peek(): Object
Returns the top element in this stack.
+pop(): Object
Returns and removes the top element in this stack.
+push(o: Object): Object
Adds a new element to the top of this stack.
+search(o: Object): int
Returns the position of the specified element in this stack.
MyQueue<E>
MyQueue
-list: MyLinkedList<E>
+enqueue(e: E): void
Adds an element to this queue.
+dequeue(): E
Removes an element from this queue.
+getSize(): int
Returns the number of elements from this queue.
37
Example: Using Stacks and Queues
Write a program that creates a stack using MyStack and a
queue using MyQueue. It then uses the push (enqueu)
method to add strings to the stack (queue) and the pop
(dequeue) method to remove strings from the stack
(queue).
TestStackQueue
Run
38