You are on page 1of 60

Assignment 1 - Data Structure

& Algorithms - PASS


Computer Science
FPT University (FPTU)
59 pag.

Document shared on www.docsity.com


Downloaded by: thanhngan202 (vothithanhngann@gmail.com)
ASSIGNMENT 1 FRONT SHEET

Qualification BTEC Level 5 HND Diploma in Computing

Unit number and title Unit 19: Data Structures and Algorithms

Submission date 11/12/2022 Date Received 1st submission

Re-submission Date 22/12/2022 Date Received 2nd submission

Student Name Huynh Minh Huy Student ID GCD210173

Class GCD1001 Assessor name Ho Van Phi

Student declaration

I certify that the assignment submission is entirely my own work and I fully understand the consequences of plagiarism. I understand
that making a false declaration is a form of malpractice.

Student’s signature Huy


Grading grid

P1 P2 P3 M1 M2 M3 D1 D2

Document shared on www.docsity.com


Downloaded by: thanhngan202 (vothithanhngann@gmail.com)
 Summative Feedback:  Resubmission Feedback:
2.1

Grade: Assessor Signature: Date:


Internal Verifier’s Comments:

IV Signature:

Document shared on www.docsity.com


Downloaded by: thanhngan202 (vothithanhngann@gmail.com)
Table of Contents
Introduction ............................................................................................................................................................. 7

Chapter 1: Create a design specification for data structures explaining the valid operations
that can be carried out on the structures. (P1) ........................................................................................... 8

I. Abstract Data Type. ...................................................................................................................................................8

1. Definition. .................................................................................................................................................................8

2. Examples. ..................................................................................................................................................................8

II. VDM Specification Language. .............................................................................................................................. 22

III. Queue Data Structure. ....................................................................................................................................... 23

IV. Queue Operations. .............................................................................................................................................. 25

Chapter 2: Determine the operations of a memory stack and how it is used to implement
function calls in a computer. (P2) ................................................................................................................. 32

I. How stack in computer’s memory is organized. ......................................................................................... 32

II. Recursion in memory stack. ................................................................................................................................ 34

Chapter 3: Using an imperative definition, specify the abstract data type for a software stack.
(P3)........................................................................................................................................................................... 37

I. Stack Data Type........................................................................................................................................................ 37

II. Stack’s operations. .................................................................................................................................................. 38

III. ADT Application. ................................................................................................................................................. 45

Conclusion ............................................................................................................................................................. 55

References ............................................................................................................................................................. 56

Document shared on www.docsity.com


Downloaded by: thanhngan202 (vothithanhngann@gmail.com)
Table of Figures
Figure 1: Abstract Data Type. .............................................................................................................................................8
Figure 2: Doubly Linked List Representation...............................................................................................................9
Figure 3: New node. ............................................................................................................................................................. 10
Figure 4: Reorganize the pointers (changes are denoted by purple arrows). .............................................. 10
Figure 5: Reorganize the pointers. ................................................................................................................................ 11
Figure 6: Insertion at the Beginning. ............................................................................................................................ 11
Figure 7: New node. ............................................................................................................................................................. 12
Figure 8: Reorganize the pointers. ................................................................................................................................ 12
Figure 9: Reorganize the pointers. ................................................................................................................................ 12
Figure 10: Final list. ............................................................................................................................................................. 13
Figure 11: Insertion in between two Nodes............................................................................................................... 13
Figure 12: New node. .......................................................................................................................................................... 14
Figure 13: Reorganize the pointers. .............................................................................................................................. 14
Figure 14: The final list. ..................................................................................................................................................... 14
Figure 15: Insertion at the End. ...................................................................................................................................... 15
Figure 16: Original doubly linked list. .......................................................................................................................... 16
Figure 17: Reorganize the pointers. .............................................................................................................................. 16
Figure 18: Final list. ............................................................................................................................................................. 16
Figure 19: Reorganize the pointers. .............................................................................................................................. 17
Figure 20: Final list. ............................................................................................................................................................. 17
Figure 21: Reorganize the pointers. .............................................................................................................................. 17
Figure 22: Final list. ............................................................................................................................................................. 18
Figure 23: Deletion from a Doubly Linked List. ........................................................................................................ 18
Figure 24: Full source code for Doubly Linked List. ............................................................................................... 22
Figure 25: Result. .................................................................................................................................................................. 22
Figure 26: VDM Specification Language. .....................................................................................................................
Document shared on www.docsity.com 23
Downloaded by: thanhngan202 (vothithanhngann@gmail.com)

Figure 27: Queue Data Structure. ................................................................................................................................... 23


Figure 28: Queue Example. ............................................................................................................................................... 24
Figure 29: Queue Enqueue................................................................................................................................................ 25
Figure 30: Enqueue in Java. .............................................................................................................................................. 26
Figure 31: Queue Dequeue. .............................................................................................................................................. 26
Figure 32: Dequeue in Java. .............................................................................................................................................. 27
Figure 33: Peek. ..................................................................................................................................................................... 27
Figure 34: Peek in Java. ...................................................................................................................................................... 28
Figure 35: isFull in Java. ..................................................................................................................................................... 28
Figure 36: isEmpty in Java. ............................................................................................................................................... 28
Figure 37: Full code for queue in Java. ......................................................................................................................... 30
Figure 38: Program Result. ............................................................................................................................................... 31
Figure 39: Stack Frames. ................................................................................................................................................... 32
Figure 40: Stack in memory. ............................................................................................................................................ 33
Figure 41: Recursion. .......................................................................................................................................................... 34
Figure 42: Tower Of Hanoi code for recursion's example. ................................................................................... 35
Figure 43: Result. .................................................................................................................................................................. 35
Figure 44: Function Calling. ............................................................................................................................................. 36
Figure 45: Function Return. ............................................................................................................................................. 36
Figure 46: Stack Data Structure. ..................................................................................................................................... 37
Figure 47: Example for element in Stack. ................................................................................................................... 37
Figure 48: Push operation in Stack................................................................................................................................ 39
Figure 49: Push in Java. ...................................................................................................................................................... 39
Figure 50: Pop operation in Stack. ................................................................................................................................. 40
Figure 51: Pop in Java. ........................................................................................................................................................ 40
Figure 52: Peek operation in Stack. ............................................................................................................................... 41
Figure 53: Peek in Java. ...................................................................................................................................................... 41
Figure 54: isFull in Java. ..................................................................................................................................................... 41
Figure 55: isEmpty in Java. ............................................................................................................................................... 42
Figure 56: Main function. ..................................................................................................................................................
Document shared on www.docsity.com
42
Downloaded by: thanhngan202 (vothithanhngann@gmail.com)
Figure 57: Full code for stack in Java. ........................................................................................................................... 44
Figure 58: Program Result. ............................................................................................................................................... 45
Figure 59: Employee Source Code. ................................................................................................................................ 46
Figure 60: Employee Management Source Code. ..................................................................................................... 50
Figure 61: Menu Option. .................................................................................................................................................... 50
Figure 62: Option 1: Input................................................................................................................................................. 50
Figure 63: Option 2: Display Employee's List. .......................................................................................................... 51
Figure 64: Option 3: Find By Name. .............................................................................................................................. 52
Figure 65: Option 4: Sort By Name. ............................................................................................................................... 52
Figure 66: Option 5: Update New Allowance............................................................................................................. 53
Figure 67: Option 6: Display Employee Who Don’t Have Allowance. .............................................................. 54

Table of Tables
Table 1: Basic Operations. ....................................................................................................................................................9
Table 2: Example Queue in VDM. ................................................................................................................................... 25
Table 3: Example Stack in VDM. ..................................................................................................................................... 38

Document shared on www.docsity.com


Downloaded by: thanhngan202 (vothithanhngann@gmail.com)
Introduction
If data is kept in a well-organized manner on storage media and in computer memory, it may
be accessible quickly for processing, reducing latency and providing a prompt response to the
user.
A data structure is a strategy for organizing data, or in other terms, a data structure is an
arrangement of data in a computer's memory that allows the data to be immediately available
to the processor for essential computations. A data structure should be viewed as a logical idea
that must meet two key issues. First, how will the data be saved, and then, what operations
will be done on it? Because a data structure is a system for organizing data, its functional
specification should be independent of its implementation. ADT (Abstract Data Type) is the
functional specification of a data structure that is independent of implementation. The
implementation is left to developers, who pick which technology is best suited to their
project's requirements.

Document shared on www.docsity.com


Downloaded by: thanhngan202 (vothithanhngann@gmail.com)
Chapter 1: Create a design specification for data structures explaining the valid operations that can be
carried out on the structures. (P1)
I. Abstract Data Type.
1. Definition.
Abstract Data Type (ADT) is a kind of (or class of) object whose behavior is defined by
a collection of values and actions. The definition of ADT just specifies which operations
must be completed, not how they will be carried out. It makes no mention of how data
will be stored in memory or which algorithms will be used to carry out the actions. The
name "abstract" refers to the fact that it provides a view that is independent of
implementation.

Figure 1: Abstract Data Type.

2. Examples.
A Doubly Linked List, as opposed to a Single Linked List, is a form of a Linked List in
which navigation is accessible in both ways, forward and backward. The following are
key words to grasp the notion of a doubly linked list.
 Link – A linked list's links can each hold data known as elements.
 Next – Each link in a linked list has a Next link to the next link.
 Prev − Each link in a shared
Document linked list has a Prev link to the previous link.
on www.docsity.com
Downloaded by: thanhngan202 (vothithanhngann@gmail.com)

 LinkedList − A Linked List has a connection link to the first link named First
and a connection link to the last link called Last.
Figure 2: Doubly Linked List Representation.

The following are the key elements to examine, as illustrated above.


 A link element named first and last appears in a Doubly Linked List.
 Each link has a data field(s) as well as two link fields named next and previous.
 Each link is connected to its next link via its following link.
 Each connection is related to its predecessor via its predecessor.
 The last link contains a null link to indicate the end of the list.
 Basic Operations
Following are the basic operations supported by a list.
Operation Description
Insertion Adds an element at the beginning of the list.
Deletion Deletes an element at the beginning of the
list.
Insert Last Adds an element at the end of the list.
Delete Last Deletes an element from the end of the list.
Insert After Adds an element after an item of the list.
Delete Deletes an element from the list using the
key.
Display forward Displays the complete list in a forward
manner.
Display backward Displays the complete list in a backward
Document shared on www.docsity.com
manner.
Downloaded by: thanhngan202 (vothithanhngann@gmail.com)

Table 1: Basic Operations.


 Insertion on a Doubly Linked List.
Pushing a node to a doubly-linked list is identical to pushing a node to a linked list, but
more work is necessary to handle the prior node's reference.
We can introduce entries into a doubly-linked list at three distinct points:
- Insertion at the beginning.
- Insertion in-between nodes.
- Insertion at the End.
Assume we have a two-linked list with the items 1, 2, and 3.
1. Insertion at the Beginning.
Let's add a node with value 6 at the beginning of the doubly linked list we made
above.
a) Create a new node.
 allocate memory for newNode
 assign the data to newNode .

Figure 3: New node.

b) Set prev and next pointers of new node.


 point next of newNode to the first node of the doubly linked list
 point prev to null

Document shared on www.docsity.com


Downloaded by: thanhngan202 (vothithanhngann@gmail.com)

Figure 4: Reorganize the pointers (changes are denoted by purple arrows).


c) Make new node as head node.
 Point prev of the first node to newNode (now the previous head is the
second node)
 Point head to newNode

Figure 5: Reorganize the pointers.

Code for Insertion at the Beginning in Java Program Language.

// insert node at the front


public void insertFront(int data) {
// allocate memory for newNode and assign data to newNode
Node newNode = new Node(data);

// make newNode as a head


newNode.next = head;

// assign null to prev of newNode


newNode.prev = null;

// previous of head (now head is the second node) is newNode


if (head != null)
head.prev = newNode;

// head points to newNode


head = newNode;
}
Figure 6: Insertion at the Beginning.

Document shared on www.docsity.com


Downloaded by: thanhngan202 (vothithanhngann@gmail.com)
2. Insertion in between two nodes.
Let's add a node with value 6 after node with value 1 in the doubly linked list.
a) Create a new node.
 allocate memory for newNode
 assign the data to newNode .

Figure 7: New node.

b) Set the next pointer of new node and previous node.


 assign the value of next from previous node to the next of newNode
 assign the address of newNode to the next of previous node

Figure 8: Reorganize the pointers.

c) Set the prev pointer of new node and the next node.
 assign the value of prev of next node to the prev of newNode
 assign the address of newNode to the prev of next node

Document shared on www.docsity.com


Downloaded by: thanhngan202 (vothithanhngann@gmail.com)

Figure 9: Reorganize the pointers.


The final doubly linked list is after this insertion is:

Figure 10: Final list.

Code for Insertion in between two Nodes.

// insert a node after a specific node


public void insertAfter(Node prev_node, int data) {

// check if previous node is null


if (prev_node == null) {
System.out.println("previous node cannot be null");
return;
}

// allocate memory for newNode and assign data to newNode


Node new_node = new Node(data);

// set next of newNode to next of prev node


new_node.next = prev_node.next;

// set next of prev node to newNode


prev_node.next = new_node;

// set prev of newNode to the previous node


new_node.prev = prev_node;

// set prev of newNode's next to newNode


if (new_node.next != null)
new_node.next.prev = new_node;
}
Figure 11: Insertion in between two Nodes.
Document shared on www.docsity.com
Downloaded by: thanhngan202 (vothithanhngann@gmail.com)
3. Insertion at the End.
Let's add a node with value 6 at the end of the doubly linked list.
a) Create a new node.

Figure 12: New node.

b) Set the next pointer of new node and previous node.


If the linked list is empty, make the newNode as the head node. Otherwise,
traverse to the end of the doubly linked list and

Figure 13: Reorganize the pointers.

The final doubly linked list looks like this.

Figure 14: The final list.


Document shared on www.docsity.com
Downloaded by: thanhngan202 (vothithanhngann@gmail.com)
Code for Insertion at the End.

// insert a newNode at the end of the list


void insertEnd(int data) {
// allocate memory for newNode and assign data to newNode
Node new_node = new Node(data);

// store the head node temporarily (for later use)


Node temp = head;

// assign null to next of newNode


new_node.next = null;

// if the linked list is empty, make the newNode as head node


if (head == null) {
new_node.prev = null;
head = new_node;
return;
}

// if the linked list is not empty, traverse to the end of the linked list
while (temp.next != null)
temp = temp.next;

// assign next of the last node (temp) to newNode


temp.next = new_node;

// assign prev of newNode to temp


new_node.prev = temp;
}
Figure 15: Insertion at the End.

Document shared on www.docsity.com


Downloaded by: thanhngan202 (vothithanhngann@gmail.com)
 Deletion from a Doubly Linked List.
Similarly to inserting, we may remove a node from one of three points in a doubly linked
list.
Assume we have a two-linked list with the items 1, 2, and 3.

Figure 16: Original doubly linked list.

1. Deletion the First Node of Doubly Linked List.


If the node to be deleted (i.e. del_node ) is at the beginning
Reset value node after the del_node (i.e. node two).

Figure 17: Reorganize the pointers.

Finally, free the memory of del_node . And, the linked will look like this

Figure 18: Final list.

2. Deletion of the Inner Node.


Document shared on www.docsity.com
Downloaded by: thanhngan202 (vothithanhngann@gmail.com)

If del_node is an inner node (second node), we must have to reset the value
of next and prev of the nodes before and after the del_node .
For the node before the del_node (i.e. first node)
Assign the value of next of del_node to the next of the first node.
For the node after the del_node (i.e. third node)
Assign the value of prev of del_node to the prev of the third node.

Figure 19: Reorganize the pointers.

Finally, we will free the memory of del_node . And, the final doubly linked list looks
like this.

Figure 20: Final list.

3. Delete the Last Node Of Doubly Linked List.


In this case, we are deleting the last node with value 3 of the doubly linked list.
Here, we can simply delete the del_node and make the next of node
before del_node point to NULL .

Document shared on www.docsity.com


Downloaded by: thanhngan202 (vothithanhngann@gmail.com)

Figure 21: Reorganize the pointers.


The final doubly linked list looks like this.

Figure 22: Final list.

Code for Deletion from a Doubly Linked List

// delete a node from the doubly linked list


void deleteNode(Node del_node) {

// if head or del is null, deletion is not possible


if (head == null || del_node == null) {
return;
}

// if del_node is the head node, point the head pointer to the next of del_node
if (head == del_node) {
head = del_node.next;
}

// if del_node is not at the last node, point the prev of node next to del_node
// to the previous of del_node
if (del_node.next != null) {
del_node.next.prev = del_node.prev;
}

// if del_node is not the first node, point the next of the previous node to the
// next node of del_node
if (del_node.prev != null) {
del_node.prev.next = del_node.next;
}

} Document shared on www.docsity.com


Downloaded by: thanhngan202 (vothithanhngann@gmail.com)
Figure 23: Deletion from a Doubly Linked List.
Full source code for Doubly Linked List in Java Program Language.

public class DoublyLinkedList {

// node creation
Node head;

class Node {
int data;
Node prev;
Node next;

Node(int d) {
data = d;
}
}

// insert node at the front


public void insertFront(int data) {
// allocate memory for newNode and assign data to newNode
Node newNode = new Node(data);

// make newNode as a head


newNode.next = head;

// assign null to prev of newNode


newNode.prev = null;

// previous of head (now head is the second node) is newNode


if (head != null)
head.prev = newNode;

// head points to newNode


head = newNode;
}

Document shared on www.docsity.com


// insert a node after Downloaded
a specific node
by: thanhngan202 (vothithanhngann@gmail.com)

public void insertAfter(Node prev_node, int data) {

// check if previous node is null


if (prev_node == null) {
System.out.println("previous node cannot be null");
return;
}

// allocate memory for newNode and assign data to newNode


Node new_node = new Node(data);

// set next of newNode to next of prev node


new_node.next = prev_node.next;

// set next of prev node to newNode


prev_node.next = new_node;

// set prev of newNode to the previous node


new_node.prev = prev_node;

// set prev of newNode's next to newNode


if (new_node.next != null)
new_node.next.prev = new_node;
}

// insert a newNode at the end of the list


void insertEnd(int data) {
// allocate memory for newNode and assign data to newNode
Node new_node = new Node(data);

// store the head node temporarily (for later use)


Node temp = head;

// assign null to next of newNode


new_node.next = null;
// if the linked list is empty, make the newNode as head node
if (head == null) {
new_node.prev = null;
head = new_node;
return;
Document shared on www.docsity.com
} Downloaded by: thanhngan202 (vothithanhngann@gmail.com)

// if the linked list is not empty, traverse to the end of the linked list
while (temp.next != null)
temp = temp.next;
// assign next of the last node (temp) to newNode
temp.next = new_node;
// assign prev of newNode to temp
new_node.prev = temp;
}
// delete a node from the doubly linked list
void deleteNode(Node del_node) {
// if head or del is null, deletion is not possible
if (head == null || del_node == null) {
return;
}
// if del_node is the head node, point the head pointer to the next of
del_node
if (head == del_node) {
head = del_node.next;
}
// if del_node is not at the last node, point the prev of node next to
del_node
// to the previous of del_node
if (del_node.next != null) {
del_node.next.prev = del_node.prev;
}

// if del_node is not the first node, point the next of the previous node to
the
// next node of del_node
if (del_node.prev != null) {
del_node.prev.next = del_node.next;
}
}
// print the doubly linked list
public void printlist(Node node) {
Node last = null;
while (node != null) {
System.out.print(node.data + "->");
last = node;
node = node.next;
Document shared on www.docsity.com
} Downloaded by: thanhngan202 (vothithanhngann@gmail.com)

System.out.println();
}
public static void main(String[] args) {
DoublyLinkedList doubly_ll = new DoublyLinkedList();

doubly_ll.insertEnd(5);
doubly_ll.insertFront(1);
doubly_ll.insertFront(6);
doubly_ll.insertEnd(9);

// insert 11 after head


doubly_ll.insertAfter(doubly_ll.head, 11);

// insert 15 after the seond node


doubly_ll.insertAfter(doubly_ll.head.next, 11);
doubly_ll.printlist(doubly_ll.head);

// delete the last node


doubly_ll.deleteNode(doubly_ll.head.next.next.next.next.next);
doubly_ll.printlist(doubly_ll.head);
}
}
Figure 24: Full source code for Doubly Linked List.

Figure 25: Result.

II. VDM Specification Language.


The Vienna Development Technique (VDM) is a model-oriented formal method for developing
computer-based systems and software that has been in use for many years. It consists of a set
of mathematically sound languages and tools for expressing and analyzing system models
Document shared on www.docsity.com
during the early phasesDownloaded
of design, before(vothithanhngann@gmail.com)
by: thanhngan202 making costly implementation commitments. The
model's development and analysis aid in identifying areas of incompleteness or ambiguity in
informal system requirements, as well as providing some assurance that a legitimate
implementation will have crucial features, particularly those of safety or security. VDM has a
proven track record of practical use, often by practitioners who are not experts in the
underlying formalism or logic. The method's experience implies that the effort devoted on
formal modeling and analysis can be returned in lower rework costs due to design flaws.

Figure 26: VDM Specification Language.

III. Queue Data Structure.


A queue is a dynamic set in which the order in which members are deleted and added is
determined in advance. It uses the FIFO (First In First Out) mechanism to access things. Queues
are often used to manage threads in multithreading and priority queuing systems. This article
will educate us about queue data structures, fundamental operations that may be done on
them, and implementation.

Document shared on www.docsity.com


Downloaded by: thanhngan202 (vothithanhngann@gmail.com)

Figure 27: Queue Data Structure.


 Real Life example of a queue data structure
Consider a queue of people waiting to buy a movie ticket at a theater. A new person will
join the line from the back, and the person in front will be the first to receive the ticket
and depart the line. Similarly, in a queue data structure, data added first will be the first
to depart the queue.
Other real-world queuing uses include:
 People riding the escalator.
 A store's cashier line.
 A vehicle wash station.
 Exits with just one direction.

Figure 28: Queue Example.

Because queue is a dynamic set, it may insert and delete elements as well as perform
other actions. The Queue data structure is shown below.
Name: Queue
Symbol: Queue
Values: queue of nat1, queue of bool, queue of char, …
Document shared on www.docsity.com
Downloaded by: thanhngan202 (vothithanhngann@gmail.com)
Operator: Assume that a in the following denote arbitrary queues of which their data
types is an arbitrary type b
Operator Name Type
Enqueue a Enqueue Queue of b-> Queue of b
Dequeue a Dequeue Queue of b -> b
Peek a Peek Queue of b -> b
Size a Find size Queue of b -> nat1
IsEmpty a Find if a is empty Queue of b -> bool
IsFull a Find if full Queue of b -> bool
Table 2: Example Queue in VDM.

IV. Queue Operations.


Queues have two pointers that contain the back and front addresses of the queue. The majority
of its activity would consist of inserting or removing data and adjusting these pointers
dependent on the status of the queue. Enqueue, dequeue, peek, size, isFull, and isEmpty are
the operations.
 Enqueue().
Queues keep two data pointers, one in front and one in the back. As a result, its
operations are more complicated to implement than stacks'.
To enqueue (insert) data into a queue, perform the following steps:
Step 1 − Check if the queue is full.
Step 2 − If the queue is full, produce overflow error and exit.
Step 3 − If the queue is not full, increment rear pointer to point the next empty
space.
Step 4 − Add data element to the queue location, where the rear is pointing.
Step 5 − Return success.

Document shared on www.docsity.com


Downloaded by: thanhngan202 (vothithanhngann@gmail.com)

Figure 29: Queue Enqueue.


Here is the enqueue operation in Java Programing Language.

public void Enqueue(int item)


{
// check for queue overflow
if (isFull())
{
System.out.println("Overflow\nProgram Terminated");
System.exit(-1);
}
System.out.println("Inserting " + item);
rear = (rear + 1) % capacity;
arr[rear] = item;
count++;
}
Figure 30: Enqueue in Java.

 Dequeue().
Accessing data from the queue entails two steps: accessing the data where the front is
pointing and removing the data after access. To do a dequeue operation, take the
following steps:
Step 1 − Check if the queue is empty.
Step 2 − If the queue is empty, produce underflow error and exit.
Step 3 − If the queue is not empty, access the data where front is pointing.
Step 4 − Increment front pointer to point to the next available data element.
Step 5 − Return success.

Document shared on www.docsity.com


Downloaded by: thanhngan202 (vothithanhngann@gmail.com)

Figure 31: Queue Dequeue.


Here is the implementation of dequeue in Java programing language.

public int Dequeue()


{

// check for queue underflow


if (isEmpty())
{
System.out.println("Underflow\nProgram Terminated");

System.exit(-1);
}
int x = arr[front];

System.out.println("Removing " + x);

front = (front + 1) % capacity;

count--;

return x;
}
Figure 32: Dequeue in Java.

 Peek().
This function facilitates viewing the data at the front of the queue. The peek() function's
algorithm is as follows:

Document shared on www.docsity.com


Downloaded by: thanhngan202 (vothithanhngann@gmail.com)

Figure 33: Peek.


Here is the implementation of peek in Java programing language.

public int Peek()


{
if (isEmpty())
{
System.out.println("Underflow\nProgram Terminated");
System.exit(-1);
}
return arr[front];
}
Figure 34: Peek in Java.

 isFull().
This action produces a boolean result indicating whether or not the queue is full.

public boolean isFull() {


return (size() == capacity);
}
Figure 35: isFull in Java.

 isEmpty().
This operation returns a boolean value that indicates whether or not the queue is
empty.

public boolean isEmpty() {


return (size() == 0);
}
Figure 36: isEmpty in Java.

 Size().
This operation returns the total number of elements present in the queue.

public int Size() {


return count;
}
Document shared on www.docsity.com
Downloaded by: thanhngan202 (vothithanhngann@gmail.com)
 Full code for Queue in Java.

 package Queue;

class Queue
{
private int[] arr; // array to store queue elements
private int front; // front points to the front element in the
queue
private int rear; // rear points to the last element in the
queue
private int capacity; // maximum capacity of the queue
private int count; // current size of the queue

// Constructor to initialize a queue


Queue(int size)
{
arr = new int[size];
capacity = size;
front = 0;
rear = -1;
count = 0;
}

// Utility function to dequeue the front element


public int dequeue()
{
// check for queue underflow
if (isEmpty())
{
System.out.println("Underflow\nProgram Terminated");
System.exit(-1);
}
int x = arr[front];
System.out.println("Removing " + x);
front = (front + 1) % capacity;
Document shared on www.docsity.com
count--;
Downloaded by: thanhngan202 (vothithanhngann@gmail.com)

return x;
}

// Utility function to add an item to the queue


public void enqueue(int item)
{
// check for queue overflow
if (isFull())
{
System.out.println("Overflow\nProgram Terminated");
System.exit(-1);
}

System.out.println("Inserting " + item);


rear = (rear + 1) % capacity;
arr[rear] = item;
count++;
}

// Utility function to return the front element of the queue


public int peek()
{
if (isEmpty())
{
System.out.println("Underflow\nProgram Terminated");
System.exit(-1);
}
return arr[front];
}

// Utility function to return the size of the queue


public int size() {
return count;
}

// Utility function to check if the queue is empty or not


public boolean isEmpty() {
return (size() == 0);
}
// Utility function to check if the queue is full or not
Document shared on www.docsity.com
public boolean isFull()
Downloaded by: thanhngan202{(vothithanhngann@gmail.com)

return (size() == capacity);


}
}
Figure 37: Full code for queue in Java.
Figure 38: Program Result.

Document shared on www.docsity.com


Downloaded by: thanhngan202 (vothithanhngann@gmail.com)
Chapter 2: Determine the operations of a memory stack and how it is used to implement function calls
in a computer. (P2)
I. How stack in computer’s memory is organized.
A stack work using a LIFO (Last In First Out) policy, in which the last element added would be
the first one to be removed.
The stack has three basic functions:
 Push: Add a new element to the top of the stack.
 Pop: Take out the top element of the stack.
 Check: To see whether the stack is empty.
In computer memory (typically RAM), the stack grows downwards. Stack frames, also known
as activation records, comprise the stack. After a function is called, a stack frame is created and
de-allocated when the function returns.

Document shared on www.docsity.com


Downloaded by: thanhngan202 (vothithanhngann@gmail.com)

Figure 39: Stack Frames.


Each function has local memory associated with it to hold incoming parameters, local
variables, and (in some cases) temporary variables. This region of memory is called a stack
frame and is allocated on the process’ stack. A frame pointer (the ebp register on intel x86
architectures, rbp on 64-bit architectures) contains the base address of the function’s frame.
The code to access local variables within a function is generated in terms of offsets to the frame
pointer. The stack pointer (the esp register on intel x86 architectures or rsp on 64-bit
architectures) may change during the execution of a function as values are pushed or popped
off the stack (such as pushing parameters in preparation to calling another function). The
frame pointer doesn’t change throughout the function.

Figure 40: Stack in memory.

When a function is invoked, a new stack frame is created and the steps listed below will
be carried out:
 Step 1: Arguments are stored on the stack.
 Step 2: Current frame pointer and return address are recorded.
 Step 3: Local variables areonallocated
Document shared www.docsity.com memory.
Downloaded by: thanhngan202 (vothithanhngann@gmail.com)

 Step 4: Stack pointer is adjusted.


When a function returns, the top stack frame is removed, and the following operations
are performed:
 Step 1: Old frame pointer and return address are restored.
 Step 2: Stack pointer is adjusted.
 Step 3: The caller can find the return value, if there is one, on top of the stack.

II. Recursion in memory stack.


Recursion is the act of a function calling itself within its code. This means that the stack may
include many stack frames that represent the same function. Recursion may be used to tackle
many issues that would be difficult to solve using iteration. However, every recursion function
must have a base case in which it may be stopped. Otherwise, it can call itself forever,
consuming the whole limited capacity of the stack.

Figure 41: Recursion.

The following is an example of a recursion function that uses the "Tower of Hanoi" issue and
how it acts in stack memory.

void towerOfHanoi(int n, char from_rod, char to_rod, char aux_rod)


{ Document shared on www.docsity.com
Downloaded by: thanhngan202 (vothithanhngann@gmail.com)

if (n == 1)
{
System.out.println("Move disk 1 from rod " + from_rod + " to rod " +
to_rod);
return;
}
towerOfHanoi(n-1, from_rod, aux_rod, to_rod);
System.out.println("Move disk " + n + " from rod " + from_rod + " to rod " +
to_rod);
towerOfHanoi(n-1, aux_rod, to_rod, from_rod);
}
public static void main(String[] args) {
Recursion recursion = new Recursion();
Scanner sc = new Scanner(System.in);
int n;
System.out.print("Enter number: ");
n = sc.nextInt();
System.out.println("Tower of Hanoi in "+n+" disk:");
recursion.towerOfHanoi(n, 'A', 'C', 'B');
}
Figure 42: Tower Of Hanoi code for recursion's example.

Figure 43: Result.

As we can see, the function began with a base case of 1 and a function call to itself. When the
number is n (the number of disk that you want to input), the function calls in the stack memory
will act as follows.

Document shared on www.docsity.com


Downloaded by: thanhngan202 (vothithanhngann@gmail.com)
Figure 44: Function Calling.

When the functions return, it will go out in the LIFO manner

Document shared on www.docsity.com


Downloaded by: thanhngan202 (vothithanhngann@gmail.com)

Figure 45: Function Return.


Chapter 3: Using an imperative definition, specify the abstract data type for a software stack. (P3)
I. Stack Data Type.
A stack is an Abstract Data Type (ADT) that is found in almost all computer languages. It is
called a stack because it behaves like a real-world stack, such as a deck of cards or a pile of
dishes.

Figure 46: Stack Data Structure.

It’s a linear data structure of which the operations follow a particular order. “The order may
be LIFO(Last In First Out) or FILO(First In Last Out).” (GeeksforGeeks, 2022). Just like the real
world “stacks”, stack only allow users to do all the data operations on one end only.

Document shared on www.docsity.com


Downloaded by: thanhngan202 (vothithanhngann@gmail.com)

Figure 47: Example for element in Stack.


The Stack data structure is specified using the VDM specification language.
Name: Stack
Symbol: Stack
Values: set of nat1, set of char, …
Operators: Assume that a in the following denote arbitrary stack of which their data types is
an arbitrary type b
Operator Name Type
Push a Enqueue Stack of b -> Stack of b
Pop a Dequeue Stack of b -> b
Peek a Peek Stack of b -> b
IsEmpty a Find if a is empty Stack of b -> bool
IsFull a Find if full Stack of b -> bool
Table 3: Example Stack in VDM.

II. Stack’s operations.


Initializing the stack, utilizing it, and ultimately de-initializing it are examples of stack
operations. Aside from these fundamentals, a stack is utilized for the two principal activities
listed below.
 Push() - Pushing (storing) a stack element.
 Pop() - Removing (gaining access to) a stack element.
We must additionally validate the stack's status in order to use it properly. Stacks are capable
of the following:
 Peek() – Extract the stack's top data element without deleting it.
 IsFull() – Examine the stack to check if it is full.
 IsEmpty() – Determine whether the stack is empty.

Document shared on www.docsity.com


Downloaded by: thanhngan202 (vothithanhngann@gmail.com)
Push()
Push Operation refers to the process of adding a new data piece to the stack. A push operation
consists of the following steps:
 Step 1: Determines whether the stack is full.
 Step 2: If the stack is full, an error is generated and the program exits.
 Step 3: If the stack is not complete, the top is incremented to refer to the next vacant
slot.
 Step 4: Adds a data element to the stack place indicated by top.
 Step 5: Success is returned.

Figure 48: Push operation in Stack.

Push is implemented in the Java Programming Language.

public void push(int x)


{
if (isFull())
{
System.out.println("Overflow\nProgram Terminated\n");
System.exit(-1);
}

System.out.println("Inserting " + x);


Document shared on www.docsity.com
arr[++top] = x; Downloaded by: thanhngan202 (vothithanhngann@gmail.com)

}
Figure 49: Push in Java.
Pop()
Pop Operation refers to accessing the content while removing it from the stack. The data
element is not really destroyed in an array implementation of the pop() action; instead, top is
decremented to a lower place in the stack to refer to the next item. Pop(), on the other hand,
removes data elements and deal-locates memory space in linked-list implementations.
The following steps may be involved in a Pop operation:
 Step 1: Determines whether or not the stack is empty.
 Step 2: If the stack is empty, an error is generated and the program exits.
 Step 3: If the stack is not empty, it accesses the data element pointed to by top.
 Step 4: Lowers the value of top by one.
 Step 5: Success is returned.

Figure 50: Pop operation in Stack.

Pop is implemented in the Java Programming Language.

public int pop()


{
if (isEmpty())
{
System.out.println("Underflow\nProgram Terminated");
System.exit(-1);
}
System.out.println("Removing " + peek());
// decrease stack size by 1 and (optionally) return the popped element
Document shared on www.docsity.com
return arr[top--]; Downloaded by: thanhngan202 (vothithanhngann@gmail.com)

}
Figure 51: Pop in Java.
Peek()
This operation returns the top element of the stack without removing it.

Figure 52: Peek operation in Stack.

Peek is implemented in the Java Programming Language.

public int peek()


{
if (!isEmpty()) {
return arr[top];
}
else {
System.exit(-1);
}

return -1;
}
Figure 53: Peek in Java.

isFull()
The operation determines whether or not a stack is full and then returns a Boolean value. If
the top value equals the stack's last index, the stack is full.
Document shared on www.docsity.com
Downloaded by: thanhngan202 (vothithanhngann@gmail.com)

public boolean isFull() {


return top == capacity - 1; // or return size() == capacity;
}
Figure 54: isFull in Java.
isEmpty()
The IsEmpty procedure determines whether or not the stack is empty. This operation differs
somewhat from the IsFull operation in that it only returns "True" when the top value in the
array is "-1" since the index in the array starts at 0.

public boolean isEmpty() {


return top == -1; // or return size() == 0;
}
Figure 55: isEmpty in Java.

This is the main function and the result of the program.

public static void main (String[] args)


{
Stack stack = new Stack(3);
stack.push(1); // inserting 1 in the stack
stack.push(2); // inserting 2 in the stack
stack.pop(); // removing the top element (2)
stack.pop(); // removing the top element (1)
stack.push(3); // inserting 3 in the stack
System.out.println("The top element is " + stack.peek());
stack.pop(); // removing the top element (3)
// check if the stack is empty
if (stack.isEmpty()) {
System.out.println("The stack is empty");
}
else {
System.out.println("The stack is not empty");
}
}
Figure 56: Main function.

Full code for stack in Java.

package Stack;

class Stack Document shared on www.docsity.com


Downloaded by: thanhngan202 (vothithanhngann@gmail.com)

{
private int arr[];
private int top;
private int capacity;
// Constructor to initialize the stack
Stack(int size)
{
arr = new int[size];
capacity = size;
top = -1;
}

// Utility function to add an element `x` to the stack


public void push(int x)
{
if (isFull())
{
System.out.println("Overflow\nProgram Terminated\n");
System.exit(-1);
}

System.out.println("Inserting " + x);


arr[++top] = x;
}

// Utility function to pop a top element from the stack


public int pop()
{
// check for stack underflow
if (isEmpty())
{
System.out.println("Underflow\nProgram Terminated");
System.exit(-1);
}

System.out.println("Removing " + peek());

// decrease stack size by 1 and (optionally) return the popped element


return arr[top--];
Document shared on www.docsity.com
} Downloaded by: thanhngan202 (vothithanhngann@gmail.com)

// Utility function to return the top element of the stack


public int peek()
{
if (!isEmpty()) {
return arr[top];
}
else {
System.exit(-1);
}

return -1;
}

// Utility function to check if the stack is empty or not


public boolean isEmpty() {
return top == -1; // or return size() == 0;
}

// Utility function to check if the stack is full or not


public boolean isFull() {
return top == capacity - 1; // or return size() == capacity;
}

public static void main (String[] args)


{
Stack stack = new Stack(3);
stack.push(1); // inserting 1 in the stack
stack.push(2); // inserting 2 in the stack
stack.pop(); // removing the top element (2)
stack.pop(); // removing the top element (1)
stack.push(3); // inserting 3 in the stack
System.out.println("The top element is " + stack.peek());
stack.pop(); // removing the top element (3)
// check if the stack is empty
if (stack.isEmpty()) {
System.out.println("The stack is empty");
}
else {
System.out.println("The stack is not empty");
Document shared on www.docsity.com
} Downloaded by: thanhngan202 (vothithanhngann@gmail.com)

}
}
Figure 57: Full code for stack in Java.
Figure 58: Program Result.

III. ADT Application.


ADT has various applications in software development. One of them is the Employee
Management System. The user may enter data, monitor the list, search or sort employee
names, and last but not least, see who does not have allowance. In this example, I'll utilize this
management system to illustrate an issue that requires an ADT, specifically an Array.
Here is the Employee source code, which will execute several operations such as entering
information.

package EmployeeManagement;

import java.util.Scanner;

public class Employee {


String id, name;
int age;
float salary,allowance;
Employee(){}
Employee(String id, String name, int age, float salary, float allowance){
this.id = id;
this.name = name;
this.age = age;
Document shared on www.docsity.com
this.salary = salary;
Downloaded by: thanhngan202 (vothithanhngann@gmail.com)

this.allowance = allowance;
}
public void enterInformation(){
Scanner scanner = new Scanner(System.in);
System.out.println("Enter ID: ");
id = scanner.nextLine();
System.out.println("Enter name: ");
name = scanner.nextLine();
System.out.println("Enter age: ");
age = scanner.nextInt();
System.out.println("Enter salary: ");
salary = scanner.nextFloat();
System.out.println("Enter allowance: ");
allowance = scanner.nextFloat();
}
}

Figure 59: Employee Source Code.

And here is the EmployeeManagement source code which performance some function such as
sort, find, … and also displays the menu choices for user.

package EmployeeManagement;
import java.util.Objects;
import java.util.Scanner;
public class EmployeeManagement {
static Employee[] ls = new Employee[100];
static int index = 0;
void inputs(){
Scanner scanner = new Scanner(System.in);
String choice;
do {
Employee employee = new Employee();
employee.enterInformation();
ls[index] = employee;
index++;
System.out.println("You want to continue? (y/n)");
choice = scanner.next();
Document shared on www.docsity.com
Downloaded by: thanhngan202 (vothithanhngann@gmail.com)
}while (choice.equalsIgnoreCase("y"));
}
void outputs(){
System.out.println("List employees");
System.out.println("ID\t\t Name\t Age\tSalary\t\t Allowance");
for (int i = 0; i<index;i++){
Employee employee = ls[i];
System.out.printf("%1s %10s %5d
",employee.id,employee.name,employee.age);
System.out.printf("%5s %12s\n",employee.salary,employee.allowance);
}
}
void displayWithoutAllowance(){
System.out.println("List employees zero commission");
System.out.println("ID\t\t Name\t Age\tSalary\t\t Allowance");
for (int i = 0; i<index;i++){
Employee employee = ls[i];
if (employee.allowance == 0) {
System.out.printf("%1s %10s %5d
",employee.id,employee.name,employee.age);
System.out.printf("%5s
%12s\n",employee.salary,employee.allowance);
}
}
}
void findName(String name){
System.out.println("List employees");
System.out.println("ID\t\t Name\t Age\tSalary\t\t Allowance");
for (int i = 0; i < index; i++) {
if (Objects.equals(ls[i].name, name)){
Employee employee=ls[i];
System.out.printf("%1s %10s %5d
",employee.id,employee.name,employee.age);
System.out.printf("%5s %12s\n",employee.salary,employee.allowance);
}
}
}
void Sort(){
System.out.println("Sort by name");
for (int i = 0; i < index; i++) {
int min=i;
Document shared on www.docsity.com
for (int j = i;Downloaded
j < index; j++)
by: thanhngan202 {
(vothithanhngann@gmail.com)

if (ls[j].name.compareToIgnoreCase(ls[min].name)<0){
min=j;
Employee employee=ls[i];
ls[i]=ls[min];
ls[min]=employee;
}
}
}
}
void updateAllowance(float newAllowance,String id){
for (int i = 0; i < index; i++) {
if (ls[i].id.compareToIgnoreCase(id)==0){//found
Employee employee=ls[i];
ls[i].allowance =ls[i].allowance + newAllowance;
System.out.println("Update commission");
System.out.println("List employees");
System.out.println("ID\t\t Name\t Age\tSalary\t\t Allowance");
System.out.printf("%1s %10s %5d
",employee.id,employee.name,employee.age);
System.out.printf("%5s %12s\n",employee.salary,employee.allowance);
}
}
}
public static void showMenu() {
System.out.println("-------------------- Menu ---------------------");
System.out.println("1. Input");
System.out.println("2. Display Employee's List");
System.out.println("3. Find By Name");
System.out.println("4. Sort By Name");
System.out.println("5. Update Allowance");
System.out.println("6. Display employee who don't have allowance");
System.out.println("0. exit.");
System.out.println("-----------------------------------------------");
System.out.print("Please choose: ");
}
public static void Option(EmployeeManagement employeeManagement){
Scanner scanner = new Scanner(System.in);
String choose = null;
boolean exit = false;
// show menu
Document shared on www.docsity.com
showMenu(); Downloaded by: thanhngan202 (vothithanhngann@gmail.com)

while (true) {
choose = scanner.nextLine();
switch (choose) {
case "1":
employeeManagement.inputs();
break;
case "2":
employeeManagement.outputs();
break;
case "3":
System.out.println("Enter employee's name to find: ");
String name = scanner.nextLine();
employeeManagement.findName(name);
break;
case "4":
employeeManagement.Sort();
employeeManagement.outputs();
break;
case "5":
System.out.println("Enter id to update");
String id = scanner.nextLine();
System.out.println("Enter new allowance");
float newAllowance = scanner.nextFloat();
employeeManagement.updateAllowance(newAllowance,id);
break;
case "6":
employeeManagement.displayWithoutAllowance();
break;
case "0":
System.out.println("exited!");
exit = true;
break;
default:
System.out.println("invalid! please choose action in below
menu:");
break;
}
if (exit) {
break;
}
Document shared on www.docsity.com
// show menu Downloaded by: thanhngan202 (vothithanhngann@gmail.com)

showMenu();
}
}
public static void main(String[] args) {
EmployeeManagement employeeManagement = new EmployeeManagement();
Option(employeeManagement);
}
}
Figure 60: Employee Management Source Code.

And here are the results for the system.

Figure 61: Menu Option.

This is the menu option for the user when they have onlined the app.

Document shared on www.docsity.com


Downloaded by: thanhngan202 (vothithanhngann@gmail.com)

Figure 62: Option 1: Input.


This is the option 1 when user chose, it will display the information they want to input and
when they finished their input the system will ask “You want to continue” if they want to add
more they need to press “y” to continue add another employee. If the amount of employee that
input to the system is enough, they need to press “n” to finished their input and the system
will return to the menu option.

The second option is display the employee’s list and here is the result of this.

Document shared on www.docsity.com


Downloaded by: thanhngan202 (vothithanhngann@gmail.com)

Figure 63: Option 2: Display Employee's List.


The third option is find by name, when they chose option 3 the system will display the place
where you input employee’s name.

Figure 64: Option 3: Find By Name.

When they input the name they want, the information of that employee will display.

The fourth option is sort by name, this option will sort names alphabetically and here is the
result of this.

Document shared on www.docsity.com


Downloaded by: thanhngan202 (vothithanhngann@gmail.com)

Figure 65: Option 4: Sort By Name.


 Before sort:

 After sort:

The fifth option is update new allowance for the employee, when they chose option 5 the
system will display the place where you input employee’s id and new allowance for that
employee.

Figure 66: Option 5: Update New Allowance.

Document shared on www.docsity.com


Downloaded by: thanhngan202 (vothithanhngann@gmail.com)
Here is the result of option 5.
 Before Update:
I will update new allowance for the employee who name is “duc”

 After Update:

Finally, the last option is display employee who do not have allowance. In this option the
employee who have the allowance equal to 0 will display to the screen.

Figure 67: Option 6: Display Employee Who Don’t Have Allowance.

Document shared on www.docsity.com


Downloaded by: thanhngan202 (vothithanhngann@gmail.com)
Conclusion
Data structure is a method of gathering and organizing data so that we may conduct operations
on it effectively. Data Structures is the process of displaying data pieces in terms of some
connection in order to improve organization and storage.
If you are familiar with Object Oriented programming principles, a class accomplishes the
same thing: it aggregates many types of data under a single entity. The only distinction is that
data structures give strategies for efficiently accessing and manipulating data. Data Structures
are structures that are created to contain ordered data so that various operations may be done
on them conveniently. It represents data knowledge to be stored in memory. It should be
designed and implemented in a way that reduces complexity while increasing efficiency.

Document shared on www.docsity.com


Downloaded by: thanhngan202 (vothithanhngann@gmail.com)
References
Deepali, 2022. Queue Data Structure: Types, Implementation, Applications. [Online]
Available at: https://www.naukri.com/learning/articles/queue-data-structure-types-
implementation-applications/
[Accessed 07 12 2022].

Geeksforgeeks, 2022. Abstract Data Types. [Online]


Available at: https://www.geeksforgeeks.org/abstract-data-types/
[Accessed 07 12 2022].

Geeksforgeeks, 2022. Queue Data Structure. [Online]


Available at: https://www.geeksforgeeks.org/queue-data-structure/
[Accessed 07 12 2022].

Geeksforgeeks, 2022. Stack Data Structure. [Online]


Available at: https://www.geeksforgeeks.org/stack-data-structure/
[Accessed 07 12 2022].

Krzyzanowski, P., 2018. Stack frames. [Online]


Available at: https://people.cs.rutgers.edu/~pxk/419/notes/frames.html
[Accessed 07 12 2022].

Overturetool, n.d. The Vienna Development Method. [Online]


Available at: https://www.overturetool.org/method/
[Accessed 07 12 2022].

Programiz, n.d. Doubly Linked List. [Online]


Available at: https://www.programiz.com/dsa/doubly-linked-list#insertion-at-end
[Accessed 10 12 2022].
Document shared on www.docsity.com
Downloaded by: thanhngan202 (vothithanhngann@gmail.com)
Sheldon, R., n.d. Stack pointer. [Online]
Available at: https://www.techtarget.com/whatis/definition/stack-pointer
[Accessed 07 12 2022].
Techiedelight, n.d. Stack Implementation in Java. [Online]
Available at: https://www.techiedelight.com/stack-implementation-in-java/
[Accessed 07 12 2022].

Tutorialspoint, n.d. Data Structure - Doubly Linked List. [Online]


Available at:
https://www.tutorialspoint.com/data_structures_algorithms/doubly_linked_list_algorithm.htm
[Accessed 10 12 2022].

Tutorialspoint, n.d. Data Structure and Algorithms - Stack. [Online]


Available at: https://www.tutorialspoint.com/data_structures_algorithms/stack_algorithm.htm
[Accessed 07 12 2022].

Document shared on www.docsity.com


Downloaded by: thanhngan202 (vothithanhngann@gmail.com)
Document shared on www.docsity.com
Downloaded by: thanhngan202 (vothithanhngann@gmail.com)

Powered by TCPDF (www.tcpdf.org)


Index of comments

2.1 Good points:


P1: Specification of ADT is presented well.
P2: You have shown how memory stack is used to implement function calls in a computer.
P3: Application of ADT is included.

Weak points:
+ Format of the report is not good
+ Writing skill is limited.

Document shared on www.docsity.com


Downloaded by: thanhngan202 (vothithanhngann@gmail.com)

Powered by TCPDF (www.tcpdf.org)

You might also like