Professional Documents
Culture Documents
Table of contents
1 Introduction.............................................................................................................................................3
1.1 Notation...........................................................................................................................................4
2 Tree..........................................................................................................................................................4
References............................................................................................................................................4
2.1 Abstract concept..............................................................................................................................4
2.1.1 [R] Definition..........................................................................................................................4
2.1.2 [R] Informal recursive definition.............................................................................................5
2.1.3 Tree-related terms....................................................................................................................6
2.1.4 Formal definition.....................................................................................................................9
2.1.5 Abstract properties.................................................................................................................10
2.1.6 Operations..............................................................................................................................10
2.2 Design specification......................................................................................................................11
2.2.1 Overview................................................................................................................................11
2.2.2 Recursive bottom-up design..................................................................................................12
2.2.3 Recursive top-down design....................................................................................................15
2.3 Implementation..............................................................................................................................19
2.4 [0] Reasoning................................................................................................................................19
2.4.1 Structural induction...............................................................................................................19
2.5 Application examples....................................................................................................................19
2.5.1 A bottom-up tree....................................................................................................................19
2.5.2 A top-down tree.....................................................................................................................20
2.6 [R] Exercises.................................................................................................................................21
References......................................................................................................................................21
3 List........................................................................................................................................................24
3.1 Abstract concept............................................................................................................................24
References......................................................................................................................................24
3.1.1 [R] Definition........................................................................................................................24
3.1.2 List-related terms...................................................................................................................25
3.1.3 List as a tree...........................................................................................................................27
3.1.4 Recursive definition...............................................................................................................27
3.1.5 Abstract properties.................................................................................................................27
3.1.6 Operations..............................................................................................................................28
3.2 Design specification......................................................................................................................29
3.2.1 Overview................................................................................................................................29
3.2.2 Recursive list.........................................................................................................................29
3.2.3 Linked list..............................................................................................................................34
3.2.4 [0] Array-based design...........................................................................................................37
3.3 Implementation..............................................................................................................................38
3.3.1 Recursive list.........................................................................................................................38
3.3.2 Linked list..............................................................................................................................38
3.4 Other designs.................................................................................................................................38
3.5 [0] Reasoning................................................................................................................................39
3.6 Application examples....................................................................................................................39
3.7 [R] Exercises.................................................................................................................................41
FIT325 PPL
Page 1
Duc M. L. 2014
References......................................................................................................................................41
4 References.............................................................................................................................................43
FIT325 PPL
Page 2
Duc M. L. 2014
1 Introduction
In this topic, we will discuss the design, implementation and reasoning of two fundamental data types:
tree and list. These are important data abstractions that are frequently used in practice.
For example, Figure 1 below illustrates the tree and list abstractions of this document. One or the other
abstraction applies depending on how one views the document. When one skims through the document,
it appears as a list of section headers, one after another in sequence. However, when one reads the
document thoroughly, it appears as a hierarchical structure of headers: the level-1 section headers, the
level-2 sub-section headers appearing underneath each level-1 header, the level-3 sub-sub-section
headers appearing underneath each level-2 header, and so on. This hierarchical structure is called a tree.
At the top level of the tree in the figure (a.k.a level 0) is a node labelled d, which represents the
document. This is the root node of the tree and is also the only node at this level. This node is linked to
four level-1 nodes that are labelled 1, 2, 3, and 4. These represent the four level-1 section headers of the
document. Each level-1 node is in turn linked to one or more level-2 nodes and so on.
[1,2,3,4]
List
1.1
level-0: root
2.1
3.1
level-1
level-2
Tree
Figure 1: An illustration of the list and tree abstractions of this document
FIT325 PPL
Page 3
Duc M. L. 2014
1.1 Notation
Table 1 below explains the meaning of some special symbols that are used in the section headers.
Symbols
Meaning
2 Tree
References
Chapter 5 [1]
FIT325 PPL
Page 4
Duc M. L. 2014
FIT325 PPL
Page 5
Duc M. L. 2014
FIT325 PPL
Page 6
Duc M. L. 2014
For example, In Figure 2, n1, n2, n6 is a path of length 2 from the root n 1 to the node n6; n1 is a path of
length zero from n1 to itself.
Subtree
In a tree T, a node n, together with all of its proper descendants, if any, is called a subtree of T. Node n
is the root of this subtree.
Notice that a subtree satisfies the three conditions for being a tree: it has a root, all other nodes in the
subtree have a unique parent in the subtree, and by following parents from any node in the subtree, we
eventually reach the root of the subtree.
Example
Referring again to Figure 2, node n3 by itself is a subtree, since n3 has no descendants other than itself.
As another example, nodes n2, n5, and n6 form a subtree, with root n2, since these nodes are exactly the
descendants of n2. However, the two nodes n2 and n6 by themselves do not form a subtree without node
n5. Finally, the entire tree of Figure 2 is a subtree of itself, with root n1.
Leaf and interior nodes
A leaf is a node of a tree that has no children. An interior node is a node that has one or more children.
Thus, every node of a tree is either a leaf or an interior node, but not both. The root of a tree is normally
an interior node, but if the tree consists of only one node, then that node is both the root and a leaf.
Example
In Figure 2, the leaves are n5, n6, n3, and n7. The nodes n1, n2, and n4 are interior.
Height and Depth
In a tree, the height of a node n is the length of a longest path from n to a leaf. The height of the tree is
the height of the root. The depth, or level, of a node n is the length of the path from the root to n.
Example
In Figure 2, node n1 has height 2, n2 has height 1, and leaf n3 has height 0. In fact, any leaf has height 0.
The tree in Figure 2 has height 2. The depth of n1 is 0, the depth of n2 is 1, and the depth of n5 is 2.
[0] Ordered tree
Optionally, we can assign a left-to-right order to the children of any node. For example, the order of the
children of n1 in Figure 2 is n2 leftmost, then n3 , then n4. This left-to-right ordering can be extended to
order all the nodes in a tree. If m and n are siblings and m is to the left of n, then all of ms descendants
are to the left of all of ns descendants.
Example
In Figure 2, the nodes of the subtree rooted at n2 that is, n2, n5, and n6 are all to the left of the
nodes of the subtrees rooted at n3 and n4. Thus, n2, n5, and n6 are all to the left of n3, n4, and n7.
FIT325 PPL
Page 7
Duc M. L. 2014
Arithmetic expressions are representable by labeled trees, and it is often quite helpful to visualize
expressions as trees. In fact, expression trees, as they are sometimes called, specify the association of
an expressions operands and its operators in a uniform way, regardless of whether the association is
required by the placement of parentheses in the expression or by the precedence and associativity rules
for the operators involved.
The general idea is that each time we form a larger expression by applying an operator to smaller
expressions, we create a new node, labelled by that operator. The new node becomes the root of the tree
for the large expression, and its children are the roots of the trees for the smaller expressions.
FIT325 PPL
Page 8
Duc M. L. 2014
edge(p,n) is an edge that connects the parent node p to the child node n.
Page 9
Duc M. L. 2014
Basis
For any node r, T = <r,{r},{}> is a tree.
Induction
For all node n and tree T', and for some node p in T':
n is not in T' T = <T'.root, T'.nodes+{n}, T'.edges+{edge(p,n)}> is a tree.
2.1.6 Operations
2.1.6.1 Overview
Since tree is recursive in nature, the operations that may be performed on tree are inherently recursive.
The design logic of such operations is consisted of two parts. The first part is a recursion and the
second part is the actual computation that is performed against the recursion.
The first part is typically applied at a specific node of the tree. This node is the root node if the
computation is to be performed over the whole tree. Otherwise, it is an internal or leaf node. The basis
case of the recursion is applied at the leaf nodes while the induction is applied at the internal ones.
The second part depends on the applications. This is a list of some computations, adapted from [1], that
are common to all trees:
We will describe below the recursive definitions of operations count and toString. Details of the
other operations are given in [1].
FIT325 PPL
Page 10
Duc M. L. 2014
count
Suppose child(c,n) = true if c is a child of n, false if otherwise. We have:
count(n) =
1 if n is leaf
1+ count(c i ) if n is not leaf
child (c i ,n)
toString
Suppose NIL is the empty string, NL is the next line character, and | is the vertical bar character. We
have:
nodeLine(n ,l ) if n is leaf
toString (n ,l ) = nodeLine(n ,l )+ toString(c 1 ,l +1)++ toString(c k , l +1)
if n is not leaf, child(c i ,n) i =1k
nodeLine(n , l) = bol (l ) + spaceMarkers (l ) + n. toString
bol(l ) = NIL if l = 0
NL+ "|" if l > 0
spaceMarkers (l ) = NIL if l = 0
"--" if l > 0
tree is connected
The first property can be verified using the nodes and edges sets. The second property can be verified
using the operation count. If the result of this count is smaller than the cardinality of the nodes set then
we know that the tree is not connected.
FIT325 PPL
Page 11
Duc M. L. 2014
Page 12
Duc M. L. 2014
repOK
As usual, this operation validates a Tree object against the rep invariant. It is used to test the
implementation of the Tree class.
2.2.2.2 Specification
Tree
- root: Object
- nodes: Vector
- edges: Vector
+
+
+
+
+
Tree(Object)
Tree(Object, Tree...)
count(Object)
toString()
toString(StringBuffer, Object, int)
repOK()
package t9.tree.bottomup;
import java.util.Vector;
import userlib.DomainConstraint;
/**
* @overview A tree is a set of nodes that are connected to to each other by
*
edges such that one node, called the root, is connected to some nodes,
*
each of these nodes is connected to some other nodes that have not been
*
connected, and so on.
*
*
<p>The following is a bottom-up recursive tree design that
*
incrementally builds a new tree by adding roots.
*
* @attributes
*
root
Object
*
nodes
Set<Object>
Vector<Object>
*
edges
Set<(Object,Object)>
Vector<[Object,Object]>
*
* @object A typical tree T is the tuple <r,N,E>, where
*
root(r), nodes(N), and edges(E).
*
*
<p>Trees are defined recursively as follows:
*
Basis
*
For any node r, T = <r,{r},{}> is a tree.
*
Induction
*
For all natural number k >= 1 and k trees T1, T2,...,Tk
*
and for all node r:
*
r is not in T1,...,Tk ->
*
T = <r,
*
T1.nodes+...+Tk.nodes+{r},
*
{edge(r,T1.root),...,edge(r,Tk.root)} +T1.edges+...+Tk.edges> is a tree
*
FIT325 PPL
Page 13
Duc M. L. 2014
* @abstract_properties <pre>
*
mutable(root)=false /\ optional(root)=false /\
*
mutable(nodes)=true /\ optional(nodes)=false /\
*
mutable(edges)=true /\ optional(edges)=true /\
*
root in nodes /\
*
for all n in nodes.
*
(exists p in nodes. parent(n)=p /\
*
for all p, q in nodes. (parent(n)=p /\ parent(n)=q -> p=q)) /\
*
for all n in nodes.
*
(n != root -> exists a sequence of edges from root to n)
* </pre>
*
* @author dmle
*/
public class Tree {
@DomainConstraint(type="Object",mutable=false,optional=false)
private Object root;
@DomainConstraint(type="Vector",mutable=true,optional=false)
private Vector nodes;
@DomainConstraint(type="Vector",mutable=true,optional=true)
private Vector edges;
// constructors
/**
* @requires r != null
* @effects initialise this as <r,{r},{}>
*/
public Tree(Object r)
/**
* @requires r != null /\ trees.length >= 1 /\
*
for all t in trees. r not in t.nodes
*
* @effects initialise this as a tree T =
*
<r,
*
T1.nodes+...+Tk.nodes+{r},
*
{edge(r,T1.root),...,edge(r,Tk.root)} +T1.edges+...+Tk.edges>,
*
where Tis are in trees
*/
public Tree(Object r, Tree...trees)
/**
* A recursive procedure to count the number of nodes in a subtree
* rooted at n.
*
* @effects
* if n is a leaf
*
return 1
* else
*
return the number of nodes in the sub-tree rooted at n
*/
public int count(Object n)
@Override
public String toString()
FIT325 PPL
Page 14
Duc M. L. 2014
/**
* @effects
* update sb with a string representation of the sub-tree
* rooted at n.
*/
private void toString(StringBuffer sb, int level, Object n)
/**
* @effects
* if this satisfies abstract properties
* return true
* else
* return false
*/
public boolean repOK()
} // end Tree
FIT325 PPL
Page 15
Duc M. L. 2014
/**
* @requires t != null /\ n is in t.nodes /\ trees.length >= 1 /\
*
for all t' in trees. (t.nodes t'.nodes = t.nodes)
*
* @effects initialise this as a tree T =
*
<t.root,
*
t.nodes+t1.nodes+...+tk.nodes,
*
{edge(n,t1.root),...,edge(n,tk.root)}+t1.edges+...+tk.edges>,
*
where tis are in trees
*/
public Tree(Tree t, Object n, Tree...trees)
Listing 2: Design specification of a constructor that implements the general form of the inductive rule
of the top-down design
The above design is replaced by a simpler design shown in Listing 3 below. This design uses a public
operation, addNode, to add one new node to the tree. Compared to the general design in Listing 2, this
design basically treats the current tree object as the first parameter, parameter parent as the second
parameter, and a single node, n, instead of the array Tree[] as the third parameter.
/**
* @requires n != null /\ parent != null
* @effects
* if parent is in nodes
*
add n as a child of parent, i.e. edge(parent,n)
*
return true
* else
*
return false
*/
public boolean addNode(Object parent, Object n)
Tree(Object)
addNode(Object, Object)
count(Object)
toString()
toString(StringBuffer, Object, int)
repOK()
/**
* @overview A tree is a set of nodes that are connected to to each other by
*
edges such that one node, called the root, is connected to some nodes,
*
each of these nodes is connected to some other nodes that have not been
FIT325 PPL
Page 16
Duc M. L. 2014
*
connected, and so on.
*
*
<p>The following is a top-down recursive design that incrementally
*
build a tree by adding leaf nodes.
*
* @attributes
*
root
Object
*
nodes
Set<Object>
Vector<Object>
*
edges
Set<(Object,Object)>
Vector<[Object,Object]>
*
* @object A typical tree T is the tuple <r,N,E>, where
*
root(r), nodes(N), and edges(E).
*
*
<p>Trees are defined recursively as follows:
*
Basis
*
For any node r, T = <r,{r},{}> is a tree.
*
Induction
*
For all node n and tree T' and for some node p in T':
*
n is not in T' ->
*
T = <T'.root, T'.nodes+{n}, T'.edges+{edge(p,n)}> is a tree
*
* @abstract_properties <pre>
*
mutable(root)=false /\ optional(root)=false /\
*
mutable(nodes)=true /\ optional(nodes)=false /\
*
mutable(edges)=true /\ optional(edges)=true /\
*
root in nodes /\
*
for all n in nodes.
*
(exists p in nodes. parent(n)=p /\
*
for all p, q in nodes. (parent(n)=p /\ parent(n)=q -> p=q)) /\
*
for all n in nodes.d
*
(n != root -> exists a sequence of edges from root to n)
* </pre>
* @author dmle
*/
public class Tree {
@DomainConstraint(type="Object",mutable=false,optional=false)
private Object root;
@DomainConstraint(type="Vector",mutable=true,optional=false)
private Vector nodes;
@DomainConstraint(type="Vector",mutable=true,optional=true)
private Vector edges;
// constructors
/**
* @requires r != null
* @effects initialise this as <r,{r},{}>
*/
public Tree(Object r)
/**
* @requires n != null /\ parent != null
* @effects
* if parent is in nodes
*
add n as a child of parent, i.e. edge(parent,n)
*
return true
FIT325 PPL
Page 17
Duc M. L. 2014
* else
*
return false
*/
public boolean addNode(Object parent, Object n)
/**
* A recursive procedure to count the number of nodes in a subtree
* rooted at n.
*
* @effects
* if n is a leaf
*
return 1
* else
*
return the number of nodes in the sub-tree rooted at n
*/
public int count(Object n)
@Override
public String toString()
/**
* @requires n != null
* return the string representation of the sub-tree rooted at n
*/
public String toString(Object n)
/**
* @effects
* update sb with the string representation of the sub-tree
* rooted at n.
*/
private void toString(StringBuffer sb, int level, Object n)
/**
* @effects
* if this satisfies abstract properties
* return true
* else
* return false
*/
public boolean repOK()
} // end Tree
2.3 Implementation
Refer to the attached Java source code for details.
Exercise
1. Implement another version of the private operation toString which produces a horizontal
representation of the tree. The following is an example of the tree shown in Listing 6:
FIT325 PPL
Page 18
Duc M. L. 2014
t4
t5
t8
t9
t7
=
=
=
=
=
new
new
new
new
new
Tree(4);
Tree(5);
Tree(8);
Tree(9);
Tree(7,t8,t9);
t3
t6
t2
t1
=
=
=
=
new
new
new
new
Tree(3,t4,t5);
Tree(6,t7);
Tree(2, t3, t6);
Tree(1, t2,t10);
Listing 5: A code example that shows how to create a Tree object of the bottom-up Tree class
FIT325 PPL
Page 19
Duc M. L. 2014
1
|-2
|--3
|---4
|---5
|--6
|---7
|----8
|----9
|-10
|--11
|--12
valid: true
Listing 6: The console output of the code example in Listing 5. The tree is printed as a hierarchical
structure.
Listing 7: A code example that shows how to create a Tree object of the top-down Tree class
FIT325 PPL
Page 20
Duc M. L. 2014
[1]
Page 21
Duc M. L. 2014
Hint: To show that a tree according the nonrecursive definition is a tree according the recursive
definition, use induction on the number of nodes in the tree. In the opposite direction, use induction on
the number of rounds used in the recursive definition.
[0] 5.2.5: Suppose we have a graph consisting of four nodes, r, a, b, and c. Node r is an isolated node
and has no edges connecting it. The remaining three nodes form a cycle; that is, we have an edge
connecting a and b, an edge connecting b and c, and an edge connecting c and a. Why is this graph not
a tree?
[0] 5.2.8: Show that if x and y are two distinct nodes in an ordered tree, then exactly one of the
following conditions must hold:
a) x is a proper ancestor of y
b) x is a proper descendant of y
c) x is to the left of y
d) x is to the right of y
5.3.6: In a tree, a node c is the lowest common ancestor of nodes x and y if c is an ancestor of both x
and y, and no proper descendant of c is an ancestor of x and y. Write a program that will find the lowest
common ancestor of any pair of nodes in a given tree. What is a good design specification for trees in
such a program?
[0] 5.4.1 Write a recursive program to count the number of nodes in a tree that is represented by
leftmost-child and right-sibling pointers.
5.4.2: Write a recursive program to find the maximum label of the nodes of a tree. Assume that a node's
label is the string representation of its state.
[!] 5.4.4*: Write a recursive program that computes for a tree, represented by leftmost- child and rightsibling pointers, the number of left-right pairs, that is, pairs of nodes n and m such that n is to the left of
node m. For example, in Figure 5, node 5 is to the left of the nodes labeled , , 10, 3, and 2; node 10 is
to the left of nodes 3 and 2; and node is to the left of node 2. Thus, the answer for this tree is eight
pairs.
Hint : Let your recursive function return two pieces of information when called on a node n: the
number of left-right pairs in the subtree rooted at n, and also the number of nodes in the subtree rooted
at n.
FIT325 PPL
Page 22
Duc M. L. 2014
FIT325 PPL
Page 23
Duc M. L. 2014
3 List
3.1 Abstract concept
References
Chapter 6 [1]
FIT325 PPL
Page 24
Duc M. L. 2014
Example 6.2. A line of text is another example of a list. The individual characters making up the line
are the elements of this list, so the list is a character string. This character string usually includes
several occurrences of the blank character, and normally the last character in a line of text is the
newline character.
As another example, a document can be viewed as a list. Here the elements of the list are the lines of
text. Thus a document is a list whose elements that are themselves lists, character strings in particular.
Example 6.3. A point in n-dimensional space can be represented by a list of n real numbers. For
example, the vertices of the unit cube can be represented by the triples shown in Fig. 6.1. The three
elements on each list represent the coordinates of a point that is one of the eight corners (or vertices)
of the cube. The first component represents the x-coordinate (horizontal), the second represents the ycoordinate (into the page), and the third represents the z-coordinate (vertical).
FIT325 PPL
Page 25
Duc M. L. 2014
Page 26
Duc M. L. 2014
The number of positions on a list equals the length of the list. It is possible for the same element to
appear at two or more positions. Thus it is important not to confuse a position with the element at that
position. For instance, list (3) in Example 6.1 has twelve positions, seven of which hold 31 namely,
positions 1, 3, 5, 7, 8, 10, and 12.
and so on until the last tail sub-list which contains one element
For example, the list of prime numbers less than 20 is shown in below.
Page 27
Duc M. L. 2014
3.1.6 Operations
The followings are definitions of the operations on list adapted from [1].
insert
To insert an element x into a list (a1,...,an). The element can appear anywhere in the list and duplicates
are allowed. A special case is to push x into the first position of the list to become the new head, hence
creating a new list (x,a1,...,an).
remove
To remove an occurrence of an element x from a list. The behaviour needs to be defined for the case in
which the element is found in more than one positions (e.g. delete the first occurrence). If x is not in the
list, the method should have no effect. A special case is to delete the head of the list. This operation is
called pop.
lookup
To return true or false depending on whether or not an element x is in the list.
add
To add an element to the end of the list.
concatenate
We concatenate two lists L and M by forming the list that begins with the elements of L and then
continues with the elements of M . That is, if L = (a 1,a2,...,an) and M = (b1,b2,...,bk), then LM, the
concatenation of L and M, is the list
(a1,a2,...,an,b1,b2,...,bk)
Note that the empty list is the identity for concatenation. That is, for any list L, we have L = L = L.
head
To return the head of the list.
tail
To return the remainder of the list.
retrieve
To return an element at a given position of the list.
length
To return the length of the list.
FIT325 PPL
Page 28
Duc M. L. 2014
isEmpty
To return true or false depending on whether or not the list is empty.
Page 29
Duc M. L. 2014
/**
* @overview Represents a (possibly empty) list of elements of arbitrary types.
*
* @attributes
*
head
Object
*
tail
List
*
* @object
*
A typical list is c = (x1,...,xn), where head(x1) and tail(x2,...,xn) are
elements.
*
*
<p>Recursive definition:
*
Basis
*
() is a list
*
Induction
*
for all object x and for all list L. (x,L.elements) is a list
*
* @abstract_properties
* mutable(head)=false /\ optional(head)=true /\
* mutable(tail)=true /\ optional(tail)=true /\
* isEmpty(tail)=false -> head is initialised
*
* @author dmle
*/
public class List
FIT325 PPL
Page 30
Duc M. L. 2014
Constructors
As shown in Listing 9, class List has three constructors: one public and two private. The public
constructor implements the basis rule of the recursive definition. The one-argument private constructor
together with the operation push implements the inductive rule of the definition. The two-argument
private constructor is used by the operation clone to copy the list tail before returning it.
Other operations
length()
This operation returns the value of the derived attribute length, instead of computing it using
recursion.
tail()
This operation does not return tail directly. Instead it makes a copy of the List object that is
referenced by this attribute and returns a reference to it. This helps protect this attribute from
modifications outside of class. However, this also slows down program execution.
clone()
This operation returns a copy of the current list object. It is used by the tail() operation mentioned
above. The copy is another List object that has the same content as the current object.
3.2.2.5 Specification
Below is the complete specification of the List class.
import userlib.DomainConstraint;
/**
* ...omitted (as above)...
*/
public class List {
@DomainConstraint(type="Object",mutable=false,optional=true)
private Object head;
@DomainConstraint(type="List",mutable=true,optional=true)
private List tail;
// derived attribute
@DomainConstraint(type="Integer",mutable=false,optional=true)
private int length;
/**
* This constructor implements the basis rule.
*
* @effects initialises this to be ()
*/
public List()
/**
* This constructor implements the inductive rule.
*
* @requires x != null
FIT325 PPL
Page 31
Duc M. L. 2014
FIT325 PPL
Page 32
Duc M. L. 2014
*
return tail as a new list
*/
public List tail()
/**
* @requires index >= 0
* @effects
*
if this is empty or index is out of range
*
return null
*
else
*
return the element at the position index
*/
public Object retrieve(int index)
/**
* @effects
* return the number of occurrences of the elements of this
*/
public int length()
/**
* @effects
* if this is empty
*
return true
* else
*
return false
*/
public boolean isEmpty()
@Override
public String toString()
/**
* @effects
* return a copy of this
*/
@Override
public List clone()
/**
* @effects
* if this satisfies abstract properties
*
return true
* else
*
return false
*/
public boolean repOK()
}
FIT325 PPL
Page 33
Duc M. L. 2014
typical object and abstraction function is defined in terms of cell.head and cell.tail
the rep invariant regarding head and tail is moved to class Cell
import userlib.DomainConstraint;
/**
* @overview Represents a (possibly empty) list of elements of arbitrary types.
*
* @attributes
*
cell
Cell
*
* @object
*
A typical list is c = (x1,...,xn), where cell.head(x1) and
*
cell.tail(x2,...,xn) are elements.
*
*
<p>Recursive definition:
*
Basis
*
() is a list
*
Induction
*
for all object x and for all list L, a new list is formed by inserting x
*
into the first position of L to become a head, thereby making the
FIT325 PPL
Page 34
Duc M. L. 2014
*
existing elements of L become the tail of the new list.
*
* @abstract_properties
* mutable(cell)=true /\ optional(cell)=true /\
* P_Cell
*
*
* @author dmle
*/
public class LinkedList {
@DomainConstraint(type="Cell",mutable=true,optional=true)
private Cell cell;
// derived attribute
@DomainConstraint(type="Integer",mutable=false,optional=true)
private int length;
// constructors
/**
* This constructor implements the basis rule.
*
* @effects initialises this to be ()
*/
public LinkedList()
/**
* @requires n != null
* @effects initialises this to be a list (n.head)
*/
private LinkedList(Cell n)
...
/**
* @overview Represents a linked cell that contains a head value of the
*
current list and a nullable reference pointer to another cell
*
representing the tail of the current list.
*
* @attributes
*
head
Object
*
tail
Cell
*
* @object
*
A typical cell is <v,r>, where head(v) and tail(r).
*
* @abstract_properties
* mutable(head)=false /\ optional(head)=false /\
* mutable(tail)=false /\ optional(tail)=true
*
* @author dmle
*/
private class Cell {
private Object head;
private Cell tail;
FIT325 PPL
Page 35
Duc M. L. 2014
// constructors
/**
* @requires v != null
* @effects
* initialise this to be <v,r>
*/
public Cell(Object v, Cell r)
/**
* @requires v != null
* @effects
* initialise this to be <v,null>
*/
public Cell(Object v)
/**
* @effects
* return a deep copy of this
*/
@Override
public Cell clone()
/**
* @effects
* if this satisfies abstract properties
*
return true
* else
*
return false
*/
public boolean repOK()
} // end Cell
} // end LinkedList
fixed size:
This has two implications. First is the waste of space. The array size needs to be initialised up to
a maximum value, even though the elements may not fill up. Second is performance overhead
in adding more elements than an array can hold. This requires creating a new array and copying
all the elements over.
FIT325 PPL
Page 36
Duc M. L. 2014
rep invariant ensures that elements is initialised and that length is within the limit of the
number of initialised slots in elements
3.3 Implementation
In this section, we will first give the Java implementations of the two basic class designs: recursive and
compositional. To be consistent with the literature, we will use the name linked list to refer to the these
two implementations. We will leave the implementations of the doubly-linked list and array based list
as exercises.
Page 37
Duc M. L. 2014
FIT325 PPL
Page 38
Duc M. L. 2014
// look up
System.out.println("lookup:\n=====================");
boolean tf;
for (Object o : objs) {
tf = l.lookUp(o);
System.out.printf("lookUp(%s) -> %b%n", o,tf);
}
for (Object o : nonMembers) {
tf = l.lookUp(o);
System.out.printf("lookUp(%s) -> %b%n", o,tf);
}
// retrieve
System.out.println("retrieve:\n=====================");
int length = l.length();
for (int i = 0; i < length; i++) {
Object o = l.retrieve(i);
System.out.printf("retrieve(%d) -> %s%n", i,o);
}
index = 5;
a = l.retrieve(index);
System.out.printf("retrieve(%d) -> %s%n", index,a);
// remove
System.out.println("remove:\n=====================");
for (Object o : objs) {
l.remove(o);
System.out.printf("remove(%s) -> %s%n", o,l);
}
System.out.printf("after: %s%n", l);
FIT325 PPL
Page 39
Duc M. L. 2014
[1]
6.2.1: Answer the following questions about the list (2, 7, 1, 8, 2).
a) What is the length?
b) [0] What are all the prefixes?
c) [0] What are all the suffixes?
FIT325 PPL
Page 40
Duc M. L. 2014
FIT325 PPL
Page 41
Duc M. L. 2014
4 References
1: Aho A. V and Ullman J. D., Foundations of Computer Science: C Edition, W. H. Freeman, 1994
2: Broda K., et al., Reasoned Programming, Prentice Hall Trade, 1994
FIT325 PPL
Page 42
Duc M. L. 2014