+ All Categories
Home > Technology > Data structures and algorithms short note (version 14).pd

Data structures and algorithms short note (version 14).pd

Date post: 17-Feb-2017
Category:
Upload: nimmi-rashinika
View: 247 times
Download: 4 times
Share this document with a friend
79
1 | Page Data Structures and Algorithms IN 2110 Reference: http://coltech.vnu.edu.vn/~sonpb/DSA/Data%20Structures%20and%20Algorithms%20in%20Java,%206t h%20Edition,%202014.pdf Lesson 01: Introduction Why do we need data structures? Their impact is broad and far reaching o Internet o Biology o Computers o Computer graphics o Security o Physics etc Old roots, new opportunities To solve problems that could not otherwise be addressed o Ex: network connectivity For intellectual stimulation o Great algorithms are poetry of computation To become a proficient programmer o To organize data o To create more efficient computer programs They may unlock secrets of life and of the universe o Ex: machine learning algorithms, data mining algorithms For fun and profit Measurements for Efficiency of an algorithm/solution 1. Space o Memory usage of a data structure operation should be little as possible. 2. Time o Running time or execution time of operations of data structure should be small as possible Cost of an algorithm/solution (what we have to sacrifice)
Transcript
Page 1: Data structures and algorithms short note (version 14).pd

1 | P a g e

Data Structures and Algorithms IN 2110

Reference:

http://coltech.vnu.edu.vn/~sonpb/DSA/Data%20Structures%20and%20Algorithms%20in%20Java,%206t

h%20Edition,%202014.pdf

Lesson 01: Introduction

Why do we need data structures?

Their impact is broad and far reaching

o Internet

o Biology

o Computers

o Computer graphics

o Security

o Physics etc

Old roots, new opportunities

To solve problems that could not otherwise be addressed

o Ex: network connectivity

For intellectual stimulation

o Great algorithms are poetry of computation

To become a proficient programmer

o To organize data

o To create more efficient computer programs

They may unlock secrets of life and of the universe

o Ex: machine learning algorithms, data mining algorithms

For fun and profit

Measurements for Efficiency of an algorithm/solution

1. Space

o Memory usage of a data structure operation should be little as possible.

2. Time

o Running time or execution time of operations of data structure should be small as

possible

Cost of an algorithm/solution (what we have to sacrifice)

Page 2: Data structures and algorithms short note (version 14).pd

2 | P a g e

1. Space (for storing each data item)

2. Time (to perform each operation)

3. Effort (for programming)

*note: each problem has constrains on available space and time.

There are two types of data structures.

1. Abstract data structures

Normally called abstract data types (ADT)

2. Concrete data structures

Generally the term ‘Data structures’ refers to concrete data structures

Watch: https://www.youtube.com/watch?v=CCq5qvmuStY

Abstract Data Structures Also called Abstract data types (ADT)

Abstract data type is a collection of data with a set of operations (such as insert, delete, search etc )

supported to manipulate the structure.

This is a mathematical/ logical model which looks at the abstract view of data.

Collection of data items

Operations supported on them

Types of parameters of the operations

This applies the concept of abstraction to design of data types.

Examples: list, set, stack, queue, priority queue, dictionary

Lists and Sets The difference between list and set: list allows duplicity

Some operations a List data type supports:

add(element)

clear()

copy():set

difference(set):set

remove(element)

intersection(set):set

isDisjoint():boolean

isSubset():boolean

Page 3: Data structures and algorithms short note (version 14).pd

3 | P a g e

Stack and Queue

Figure 1: Stack and Queue

Stack

Figure 2: Push (put into stack) and Pop (pull out from stack)

Last In First Out (LIFO)

Some operations a stack data type supports:

push(new_item: item_type)

o Adding a new item

pop():item_type

o Remove the most recently pushed item and return it

top():item_type

o Returns the last pushed item

is_empty(): Boolean

o Returns true if there are no items in the stack

is_full(): Boolean

o Returns true if stack is full

get_size(): Integer

o Returns the number of elements in the stack

Page 4: Data structures and algorithms short note (version 14).pd

4 | P a g e

Queue

Figure 3: Enqueue and Dequeue in a queue

First In First Out (FIFO)

Some operations a queue data type supports:

enqueue(new_item: item_type)

o Adding a new item

dequeue():item_type

o Removes the item from the front of the queue and return it

front(): item_type

o Returns the item at the front of the queue

is_empty(): Boolean

o Returns true if there are no items in the queue

is_full(): Boolean

o Returns true if queue is full

get_size(): integer

o Returns the number of elements in the queue

*note: Data structures such as Arrays, linked lists could be used to implement these ADTs.

Refer: https://en.wikibooks.org/wiki/Data_Structures/Stacks_and_Queues#Queues

Concrete Data structures Generally the term ‘Data structures’ refers to concrete data structures

Concrete Data structures are the implementation of abstract data structures.

Examples: arrays, linked lists, trees, heaps, hash table

From here onwards I use the term ADT to Abstract data structures and the generic term data structures

to Concrete data structures.

*note: Further Understanding of ADT and Data Structures

Page 5: Data structures and algorithms short note (version 14).pd

5 | P a g e

ADT is a logical description and data structure is concrete.

ADT is the logical picture of the data and the operations to manipulate the component element

of the data.

Data structure is the actual representation of the data during the implementation and the

algorithms to manipulate the data elements.

ADT is in logical level and data structure is in implementation level.

Example: List is what you want, so it is the ADT. You thought of using an array to implement this

in the program. So that array is the data structure.

Types of Data Structures Based on memory allocation and representation

Types Based on memory allocation:

1. Static (fixed sized) data structures

Ex: Arrays

2. Dynamic (variable sized) data structures

Ex: Linked Lists

Types based on representation:

1. Linear Data structures

Elements form a sequence

Can reach only one element directly from another

Very easy to implement, since the memory of the computer is also organized in a linear

fashion.

Ex: Arrays, Linked Lists

An arrays is a collection of data elements where each element could be identified using

an index.

A linked list is a sequence of nodes, where each node is made up of a data element and

a reference to the next node in the sequence.

2. Non-Linear Data Structures

Data items are not arranged in a sequential structure

Each element may be connected with two or more other items or elements

Removing one of the links could divide data structure into two disjoint pieces

Ex: Multi dimensional arrays, Trees, graphs

A multidimensional array is simply a collection of one-dimensional arrays.

A tree is a data structure that is made up of a set of linked nodes, which can be used to

represent a hierarchical relationship among data elements.

A graph is a data structure that is made up of a finite set of edges and vertices. Edges

represent connections or relationships among vertices that stores data elements.

Page 6: Data structures and algorithms short note (version 14).pd

6 | P a g e

Implementation of ADT using Data structures The operations such as Insertion, Deletion, Searching, and Sorting could be done using algorithms. The

actual storage of data items in computer memory has to considered, i.e data structures.

Operations:

Sorting

o Operation of arranging data in some given order such as increasing or decreasing.

Searching

o Finding the location of the record with a given key value, or finding the locations of all

records, which satisfy one or more conditions

Inserting

o Adding a new record to the structure

Traversing

o Accessing each record exactly once so that certain items in the record may be

processed.

Removing

o Removing a record from structure

Programs consist of Data structures and Algorithms. We have to use the most appropriate data

structure and the most appropriate algorithm when implementing ADTs.

Example: Someone is looking for a data structure with following properties.

1. High efficiency for searching

2. Moderate efficiency for insertion

3. No need to care deletion

Now what is the best data structure and what is the best algorithm to use with that particular data

structure? In few weeks we can learn the answer for the above problem.

*note:

When implementing ADT (such as stack, queue, bag, priority queue etc) it can be implemented using

different data structures as above mentioned in this document.

Therefore in programming we use an interface to declare ADT (ex: Stack) and different classes (ex:

ArrayStack, LinkedArray etc) that implements the ADT interface to write method bodies declared in the

interface using different data structures.

Page 7: Data structures and algorithms short note (version 14).pd

7 | P a g e

Example Code:

//Stack interface //E is used to show the type of elements in stack ex: int, String, Dog etc public interface Stack<E> { int size(); boolean isEmpty(); void push(E e); E peek(); //sometimes referred to as top() E pop(); }

//implement ADT Stack using array data structure public class ArrayStack<E> implements Stack<E>{ private int capacity; private E[] dataStack; private int top = -1; public ArrayStack(int capacity){ this.capacity=capacity; //dataStack=new E[this.capacity]; //cannot create a generic array E[] dataStack=(E[])new Object[this.capacity];

} public int size(){ //code goes here } public boolean isEmpty(){ //code goes here } public void push(E e){ //code goes here } public E peek(){ //code goes here } public E pop(){ //code goes here } }

The above code segment implements Stack using arrays.

The following code segment implements Stack using linked lists.

This is the way how we serve different clients requesting for same ADT with different requirements, i.e

Arrays or linked lists or etc.

Page 8: Data structures and algorithms short note (version 14).pd

8 | P a g e

//implement ADT Stack using linked list data structure //class SinglyLinkedStack library can be found in net public class LinkedStack<E> implements Stack<E>{ private SinglyLinkedList<E> list = new SinglyLinkedList<>(); public int size(){ //code goes here } public boolean isEmpty(){ //code goes here } public void push(E e){ //code goes here } public E peek(){ //code goes here } public E pop(){ //code goes here } }

It is clear that there is a separation between interface and implementation of ADTs using Data

structures.

Benefits of this separation:

Client can’t know details of implementation => Client has many implementation from which to

choose.

Implementation can’t know details of client needs => Many clients can re-use the same

implementation.

Design: creates modular reusable libraries

Performance: use optimized implementation where it matters

Terminology:

Client: program using operations defined in interface

Implementation: actual code implementing operations

Interface: description of data type, basic operations

*note that the above implementations are not the only way. There can be several ways.

We have discussed Data structures up to a certain level. Now let’s see what Algorithms are.

Page 9: Data structures and algorithms short note (version 14).pd

9 | P a g e

Algorithms Step by step recipe for performing a task within a fine period of time.

Algorithms often operate on a collection of data, which is stored in a data structure.

A problem can be solved by many algorithms.

Sorting problems can be solved using following algorithms:

Insertion sort

Bubble sort

Selection sort

Shell sort

Merge sort

Characteristics of a good algorithm:

Finiteness

o Terminates after a finite number of steps and each step should be executable in finite

amount of time

No ambiguity

o Each step of an algorithm must be precisely defined

Input

o Algorithm should have a finite number of inputs

Output

o An algorithm has one or more outputs(at least one output)

o Can be proved to produce the correct output for a given input

Effectiveness

o Steps should be simple and basic

Algorithm creation techniques

1. Flow chart

2. Pseudo code

3. Programming language

Numerical factors for measuring the goodness and effectiveness of an algorithm

1. Running time

2. Total memory usage

Page 10: Data structures and algorithms short note (version 14).pd

10 | P a g e

Lesson 02: Stacks and Queues Reference: Chapter 6, Data Structures and Algorithms in Java 6th edition by Goodrich

Stacks A collection of objects that are inserted and removed according to the Last In First Out (LIFO) principle

that can access or remove the most recently inserted object

Figure 4: Items are added (push) and removed (pop) at top of the stack

Examples:

Internet browsers store the addresses of recently visited sites on a stack.

o Each time a user visits a page,

push(address_of_the_visited_page_just_now)

o When user hits the “back” button,

pop():address_of_the_recently_visited_page

Text editors store text changes in a stack.

o “undo” mechanism use this stack

Implementing function calls (ex: revise recursive functions)

Dijkstra’s two-stack algorithm

Methods (operations) of a stack:

1. Update methods

push(new_item: item_type)

o Adding a new item

pop():item_type

o Remove the most recently pushed item and return it

o Returns null if the stack is empty

2. Accessor methods

top():item_type

o Returns the last pushed item

Page 11: Data structures and algorithms short note (version 14).pd

11 | P a g e

o Returns null if the stack is empty

isEmpty(): Boolean

o Returns true if there are no items in the stack

isFull(): Boolean

o Returns true if the stack is full

size(): Integer

o Returns the number of elements in the stack

Exercise:

Assume that initially stack is empty.

Method Return Value Stack content

push(5) (5)

push(3) (5,3)

size() 2 (5,3)

pop() 3 (5)

isEmpty() false (5)

pop() 5 ()

isEmpty() true ()

pop() null ()

push(6) (6)

push(8) (6,8)

top() / peek() 8 (6,8)

A simple Array-based Stack implementation You can directly use java.util.Stack interface without defining a new interface called Stack.

//Stack.java //Stack interface //E is used to show the type of elements in stack ex: int, String, Dog etc public interface Stack<E> { int size(); boolean isEmpty(); void push(E e); E peek(); E pop(); }

Page 12: Data structures and algorithms short note (version 14).pd

12 | P a g e

//ArrayStack.java //implement ADT Stack using array data structure public class ArrayStack<E> implements Stack<E>{ private int capacity; private E[] dataStack;

//dataStack was made private becoz you cannot reach array elements using //indexes. only the top element that you can reach.

private int top = -1; public ArrayStack(int capacity){ this.capacity=capacity; //dataStack=new E[this.capacity]; //cannot create a generic array E[] dataStack=(E[])new Object[this.capacity]; } public int size(){ return top+1; } public boolean isEmpty(){ return (top==-1); } public void push(E e){ if(size()==capacity) System.out.println("Sorry, stack is full."); else dataStack[++top] = e; } public E peek(){ //sometimes also referred to as top() return dataStack[top]; } public E pop(){ if(isEmpty()) return null; else return dataStack[top--]; } }

Page 13: Data structures and algorithms short note (version 14).pd

13 | P a g e

//ArrayStack.java public class Test { public static void main(String[] args) { ArrayStack<Integer> stack = new ArrayStack<>(10); stack.push(10); System.out.println(stack.peek()); stack.push(12); stack.push(11); System.out.println(stack.pop()); stack.push(15); System.out.println(stack.pop()); System.out.println(stack.pop()); System.out.println(stack.isEmpty()); //false System.out.println(stack.pop()); System.out.println(stack.isEmpty()); //true System.out.println(stack.pop()); stack.push(23); stack.push(65); stack.push(19); stack.push(11); stack.push(10); stack.push(20); stack.push(41); stack.push(67); System.out.println(stack.size()); stack.push(11); System.out.println(stack.size()); stack.push(17); System.out.println(stack.size()); //10 stack.push(15); } }

//Output /* 10 11 15 12 false 10 true null 8 9 10 Sorry, stack is full. You cannot insert further. */

Page 14: Data structures and algorithms short note (version 14).pd

14 | P a g e

In this example, we declare the parameterized type of the stack as the Integer wrapper class. This causes

the signature of the push method to accept an Integer instance as a parameter, and for the return type

of both top and pop to be an Integer. Of course, with Java’s autoboxing and unboxing a primitive int can

be sent as a parameter to push.

Drawbacks of the above Array-based implementation:

Overflow

o Array size is fixed

o Capacity exceeds from pushing items into the stack.

o Use resizing array for array implementation.

Loitering

o Holding a reference to an object when it is no longer needed.

o This happens in java.

o We just reduce the variable ‘top’ by 1, we do not delete the element after a pop().

Therefore that item is still in the array though we don’t use. i.e. holding a reference to

an object when it is no longer needed.

public E pop(){ if(isEmpty()) return null; else return dataStack[top--]; }

o So we can set top=null at appropriate place in the code as a solution. However it is

not possible all the time.

Corrected code without loitering is as follows.

public E pop(){ if(isEmpty()){ return null; }else{ E answer = dataStack[top]; dataStack[top]=null; top--; return answer; }

}

o Our reason for returning the cell to a null reference is to assist Java’s garbage collection

mechanism, which searches memory for objects that are no longer actively referenced

and reclaims their space for future use.

If the application needs much less space than the reserved capacity, memory is wasted.

Page 15: Data structures and algorithms short note (version 14).pd

15 | P a g e

Resizing Array Implementation There are so many approaches to resizing. Below shows a one approach among them.

Push: double size of the array when array is full

Pop: halve size of the array when array is one quarter full

Your code ArrayStack.java has to be changed as follows when implementing resizing property. Let’s

implement this feature in a new java file ResizingArrayStack.java. This will give the same output

public ResizingArrayStack(){ dataStack = (E[])new Object[1]; } public void push(E e){ if(size()==dataStack.length) resize(2*dataStack.length); dataStack[++top] = e; } private void resize(int newCapacity){ E[] copy = (E[])new Object[newCapacity]; for(int i=0;i<size();i++) copy[i]=dataStack[i]; dataStack=copy; } public E peek(){ return dataStack[top]; } public E pop(){ if(isEmpty()){ return null; }else{ E answer = dataStack[top]; //this step is essential here dataStack[top]=null; //this step is not essential here if(top==dataStack.length/4) resize(dataStack.length/2); top--; //this step is essential here return answer; } }

Page 16: Data structures and algorithms short note (version 14).pd

16 | P a g e

Implementing Stack with a Linked List Linked List is also a concrete data structure, or simply a data structure.

What is a linked list?

A linked list is a linear data structure where each element is a separate object.

Each element (we will call it a node) of a list is comprising of two items,

1. The data

2. A reference to the next node

The code for a node is as follows;

private class Node<E>{ E item; Node<E> next;

}

The last node has a reference to null. The entry point into a linked list is called the head of

the list.

Figure 5: Linked List

Using java class SinglyLinkedList is very easy, but for learning purposes let’s try to implement our own

Link list.

*note

Resizing array vs Linked list:

Linked list implementation:

Every operation takes constant time in the worst case

Use extra time and space to deal with the links (have to go from item to item, linear time)

Resizing array implementation:

Every operation takes constant amortized time

Less time, Less wasted space (constant time)

Page 17: Data structures and algorithms short note (version 14).pd

17 | P a g e

//LinkedArray.java //implement ADT Stack using linked list data structure public class LinkedStack<E> implements Stack<E>{ private Node<E> first = null; //inner class private class Node<E>{ E item; Node<E> next; } public int size(){ //this is my code, there may

//be a more feasible method //than this

if(first==null){ return 0; }else{ count=1; return isNull(first); } } private int count; //my variable private int isNull(Node x){ //my method if(x.next!=null){ //there is a better method in page 33 count++; return isNull(x.next); }else return count; } public boolean isEmpty(){ return first==null; } public void push(E e){ Node oldFirst = first; first = new Node<>(); first.item = e; first.next = oldFirst; } public E peek(){ return first.item; } public E pop(){ if(isEmpty()) return null; else{ E item = first.item; first=first.next; return item; } } }

Page 18: Data structures and algorithms short note (version 14).pd

18 | P a g e

Reversing an array using a stack int[] array = {1,4,2,3,4,6,2,3,9}; LinkedStack<Integer> stack = new LinkedStack<>(); for(int i = 0;i<array.length;i++) stack.push(array[i]); for(int i = 0;i<array.length;i++) array[i]=stack.pop(); for(int i = 0;i<array.length;i++) System.out.println(array[i]);

Addition of numbers using stacks

Figure 6: addition of two numbers using stacks

Matching Parenthesis and HTML Tags This involves testing for pairs of delimiters.

Page 19: Data structures and algorithms short note (version 14).pd

19 | P a g e

Queues A collection that keeps objects in a sequence, where element access and deletion are restricted to the

first element in the queue, and element insertions is restricted to the back of the sequence. i.e. First in

First Out (FIFO) principle.

Figure 7: Items are added to the back (enqueue) and removed from font (dequeue)

Examples:

Calls to a customer service center

Wait- list at a restaurant

Web server responding to requests

Network printer responding to requests

Methods (operations) of a queue:

1. Update methods

enqueue(new_item: item_type)

o Adding a new item to the back of the queue

dequeue():item_type

o Remove the item at the front of the queue and return it

o Returns null if the stack is empty

2. Accessor methods

first():item_type

o Returns the first element

o Returns null if the stack is empty

size(): Integer

o returns the number of elements in the queue

isEmpty(): Boolean

o returns true if the queue is empty

Page 20: Data structures and algorithms short note (version 14).pd

20 | P a g e

Exercise:

Assume that initially queue is empty.

Method Return Value Queue content

enqueue(5) (5)

enqueue (3) (5,3)

size() 2 (5,3)

dequeue() 5 (3)

isEmpty() false (3)

dequeue () 3 ()

isEmpty() true ()

dequeue () null ()

enqueue (6) (6)

enqueue (8) (6,8)

first() 6 (6,8)

Four types of queues:

1. Simple queue

Insertion occurs at the rear of the queue

Deletion occurs at the front of the queue

2. Circular queue

All nodes are treated as circular such that the first node follows the last node

Here we can move first element to the back of the queue using rotate() method

3. Priority queue

Contain items that have same preset priority

When removing elements, items with the highest priority is removed first

4. Deque (Double-Ended queue )

Insertion and deletion occur at both ends i.e. front and rear of the queue

Page 21: Data structures and algorithms short note (version 14).pd

21 | P a g e

Array-Based implementation of a Queue This method is also called realization of a queue by an array. You can directly use java.util.Queue

without using a new interface.

//Queue.java public interface Queue<E> { int size(); boolean isEmpty(); void enqueue(E e); E first(); E dequeue(); }

//ArrayQueue.java public class ArrayQueue<E> implements Queue<E> { private int maxSize; //array size private E[] dataQueue; private int front; //front locator private int rear; //rear loactor private int n; //number of items public ArrayQueue(int s){ maxSize = s; dataQueue = (E[])new Object[maxSize]; front = 0; rear = -1; n = 0; } public int size(){ return n; } public boolean isEmpty(){ return n==0; } public boolean isFull(){ return (n==maxSize); } public void enqueue(E e){ if(isFull()==false){ rear=(rear+1)%maxSize; dataQueue[rear]=e; n++; }else System.out.println("Sorry you cannot add more"); } public E dequeue(){ if(isEmpty()==false){ n--; E answer = dataQueue[front]; front=(front+1)%maxSize; return answer; }else return null;

Page 22: Data structures and algorithms short note (version 14).pd

22 | P a g e

} public E first(){ return dataQueue[front]; } }

//Test.java public class Test { public static void main(String[] args) { ArrayQueue<Integer> queue = new ArrayQueue(5); queue.enqueue(5); queue.enqueue(3); System.out.println(queue.size()); System.out.println(queue.dequeue()); System.out.println(queue.isEmpty()); System.out.println(queue.dequeue()); System.out.println(queue.isEmpty()); System.out.println(queue.dequeue()); queue.enqueue(6); queue.enqueue(8); System.out.println(queue.first()); } }

//output

/* 2 5 false 3 true null 6 */

*note

There is confusion in the implementation of a simple array and a circular array. Clear it from Ms.

Supunmali.

Page 23: Data structures and algorithms short note (version 14).pd

23 | P a g e

Linked List-Based implementation of a Queue Also called realization of a queue using a linked list

//LinkedQueue.java public class LinkedQueue<E> implements Queue<E>{ private Node<E> first = null; private Node<E> last = null; //inner class private class Node<E>{ E item; Node next; } public int size() { if(first==null){ return 0; }else{ count=1; return isNull(first); } } private int count; //my variable private int isNull(Node x){ //my method if(x.next!=null){ count++; return isNull(x.next); }else return count; } public boolean isEmpty() { return first==null; } public void enqueue(E e) { if(isEmpty()){ first = new Node<E>(); first.item = e; first.next = null; last = first; }else{ Node newLast = new Node<E>(); newLast.item = e; newLast.next = null; last.next = newLast; last = newLast; } } public E first() { return first.item; }

Page 24: Data structures and algorithms short note (version 14).pd

24 | P a g e

public E dequeue() { if(isEmpty()){ return null; }else{ E item = first.item; first=first.next; return item; } } }

Double-Ended Queues (Deque) A queue where insertion and deletion could be done at both front and the back

Figure 8: Deque

Deque:

More general than both the stack and queue

Richer than both the stack and the queue ADTs

Provides a symmetrical abstraction

Examples:

When modeling any kind of real-world waiting line: entities (bits, people, cars, words, particles,

whatever) arrive with a certain frequency to the end of the line and are serviced at a different

frequency at the beginning of the line. While waiting some entities may decide to leave the

line.... etc. The point is that you need "fast access" to insert/deletes at both ends of the line,

hence a deque.

Page 25: Data structures and algorithms short note (version 14).pd

25 | P a g e

Methods (operations) of a deque:

1. Update methods

addFirst (new_item: item_type)

o Adding a new item to the front of the queue

addLast (new_item: item_type)

o Adding a new item to the back of the queue

removeFirst():item_type

o Remove the item at the front of the queue and return it

o Returns null if the queue is empty

removeLast():item_type

o Remove the item at the back of the queue and return it

o Returns null if the queue is empty

2. Accessor methods

first():item_type

o Returns the first element

o Returns null if the queue is empty

last():item_type

o Returns the last element

o Returns null if the queue is empty

size(): Integer

o returns the number of elements in the queue

isEmpty(): Boolean

o returns true if the queue is empty

Exercise:

Assume that initially Deque is empty.

Method Return Value Deque content

addLast(5) (5)

addFirst (3) (3,5)

addFirst(7) (7,3,5)

first() 7 (7,3,5)

removeLast() 5 (7,5)

size() 2 (7,5)

removeLast () 5 (7)

removeFirst() 7 ()

addFirst (6) (6)

last() 6 (6)

addFirst (8) (8,6)

isEmpty() false (8,6)

last() 6 (8,6)

Page 26: Data structures and algorithms short note (version 14).pd

26 | P a g e

Implementation of Deque Java.uitl.Deque is an interface in java that you can use directly when implementing a Deque.

//Deque.java public interface Deque<E> { int size(); boolean isEmpty(); E first(); E last(); void addFirst(E e); void addLast(E e); E removeFirst(); E removeLast(); }

Priority Queues A queue which stores the priority additionally with the items in the queue

Priority Queue:

Items are ordered by a priority value, at the insertion.

Item with the largest priority is always at the front.

Remove the element from the queue that has the highest priority and return it.

Methods (operations) of a priority queue:

1. Update methods

insert(key,value)

1. if the no: of items in the queue is maxsize, then no more items can be inserted

(queue is full), else step 2.

2. If initially there are no more elements, insert new item at first position zero (0)

index, otherwise if new item is larger than the existing one’s shift those

elements upward one by one till the larger one is found.

3. Insert item to that new location.

removeMin():[key,value]

1. if the number of items in the queue is zero then no more items to be deleted,

Quit, else step 2.

2. Remove the front element.

2. accessors

min():[key,value]

if priority queue is not empty, return a queue entry (key, value) having minimal

key, Else returns null.

size():integer

isEmpty():Boolean

Page 27: Data structures and algorithms short note (version 14).pd

27 | P a g e

Exercise:

Assume that initially Priority Queue is empty.

Method Return value Priority queue content

insert(5,A) {(5,A)}

insert(9,c) {(5,A),(9,C)}

insert(3,B) {(3,B),(5,A),(9,C)}

min() (3,B) {(3,B),(5,A),(9,C)}

removeMin() (3,B) {(5,A),(9,C)}

size() 2 {(5,A),(9,C)}

insert(7,D) {(5,A),(7,D),(9,C)}

removeMin() (5,A) {(7,D),(9,C)}

removeMin() (7,D) {(9,C)}

removeMin() (9,C) {}

removeMin() null {}

isEmpty() true {}

Task:

Assume that you have a set of numbers like 5,4,3,7,1,6.

Consider the priorities of these numbers are equivalent to number itself.

Hint: Assume 1 has higher priority than 2.

Implement a priority queue with inserting operation to illustrate the above scenario.

Page 28: Data structures and algorithms short note (version 14).pd

28 | P a g e

Lesson 03: Linked Lists A linear data structure where each element is a separate object

Issues/ limitations of arrays:

Changing size of the array requires a new array and copy all data from old sized array to new

sized array and then continue.

Data in the array are next to each other sequentially in memory, so to insert an item inside the

array; we need to shift some data.

To overcome the above limitations, we need Linked structures.

Linked data structures:

A data structure which consists of a set of data records (nodes) linked together and organized by

references (links or pointers). The link between data can also be connector.

Major differences between Array data structure and Linked data structures:

Linked data structures Array data structure

Easier to grow organically Needs to be known the size in advance, or have to re-create when it needs to grow

references are compared with equality, no need to do arithmetic operations on references (pointers)

have perform arithmetic operations on references when referring

Types of linked data structures:

Linked lists

Search trees

Expression trees

*note

Linked data structures are also key building blocks for many efficient algorithms, such as topological sort

and set union-find.

In this lesson we study about link lists.

Traversing/ link hopping/ pointer hopping:

Starting at the head and moving from one node to another node by following each node’s next

reference.

Page 29: Data structures and algorithms short note (version 14).pd

29 | P a g e

Linked list A linear collection of data elements called ‘nodes’ pointing to the next node by means of pointer

The principle benefit of a linked list over a conventional array is that the list elements can be

easily be inserted or removed without reallocation or reorganization of the entire structure

becoz data items need not be stored contiguously in memory or on disk.

The major limitation of linked lists is that inability to random access to the data due to absence

of a efficient indexing.

Node:

Composed of data and a reference

Figure 9: How Nodes are connected in a linked list

Types of linked lists:

1. Singly linked list

Figure 10: Singly linked list

o Each node is divided into two parts. i.e. INFO field(data) and LINK field (pointer)

1. The first part contains the information of the element and is called ‘INFO Field’.

2. The second part contains the address of the next node and is called ‘LINK Field’

or ‘NEXT Pointer Field’.

Implementation of singly linked list node in java:

This is implemented as a class in java, and struct in c.

class Node<E>{ E item; //data (INFO) Node<E> next; //reference to the next node (successor)

}

*note

In this lesson our interested area is the singly linked list.

Page 30: Data structures and algorithms short note (version 14).pd

30 | P a g e

2. Doubly linked list

Figure 11: Doubly linked list

o Here each node is divided into three parts:

1. The first part is ‘PREV’ part. It is previous pointer field. It contains the address of

the node which is before the current node.

2. The second part is the ‘INFO’ part. It contains the information of the element.

3. The third part is ‘NEXT’ part. It is next pointer field. It contains the address of

the node which is after the current node.

Implementation of singly linked list node in java:

This is implemented as a class, and struct in c.

class Node<E>{ E item; //data (INFO) Node<E> next; //reference successor Node<E> prev; //reference predecessor }

3. Circular linked list

Figure 12: Circular linked list

o Here the last node does not contain NULL pointer. Instead the last node contains a

pointer that has the address of first node and thus points back to the first node.

o The structure and implementation of the node is as same as the node of a singly linked

list.

Page 31: Data structures and algorithms short note (version 14).pd

31 | P a g e

Singly Linked list

Features of Singly linked list

Only one variable is used to access any node in the list.

o Ex: if the first node is ‘p’

Then the second node is ‘p.next’

The third node id ‘p.next.next’ etc

Last node can be recognized by null reference field.

Figure 13 : Inserting an element at the Head of a Singly Linked List

Figure 14 : Inserting an element at the Tail of a Singly Linked List

Page 32: Data structures and algorithms short note (version 14).pd

32 | P a g e

Figure 15 : Removing an element from the Head of the linked list

//SLLNode.java (NODE) public class SLLNode<E> { public E data; public SLLNode next; public SLLNode(E e){ this(e,null); } public SLLNode(E e,SLLNode n){ data = e; next = n; } }

//SinglyLinkedList.java public class SinglyLinkedList <E>{ private SLLNode head, tail; private int n = 0; public SinglyLinkedList(){ head = tail = null; } public boolean isEmpty(){ return head == null; } public void addToHead(E e){ head = new SLLNode(e, head);

Page 33: Data structures and algorithms short note (version 14).pd

33 | P a g e

if(tail==null){ tail = head; } n++; }

public void addToTail(E e){ if(!isEmpty()){ tail.next = new SLLNode(e); tail = tail.next; }else head = tail = new SLLNode(e); n++; } public E deleteFromHead(){ E e = (E) head.data; if(head==tail) //if only one in the list head = tail = null; else head = head.next; n--; return e; } public E deleteFromTail(){ E e = (E) tail.data; if(head==tail) //if only one in the list head = tail = null; else{ SLLNode temp; for(temp = head; temp.next!=null; temp=temp.next); tail = temp; tail.next = null; } n--; return e; } public void delete(E e){ //deletes the first object matches if(!isEmpty()){ if(head==tail && e==head.data){ head = tail = null; n--; } else if(e==head.data){ head = head.next; n--; } else{ SLLNode pred, temp; for(pred=head,temp=head.next; temp!=null && temp.data!=e; pred = pred.next, temp=temp.next

Page 34: Data structures and algorithms short note (version 14).pd

34 | P a g e

); if(temp!=null){ //if e was found pred.next = temp.next; if(temp==tail) //if e is in the last node tail = pred; n--; } } } } public int size(){ return n; } public E getHead(){ return (E) head.data; } public E getTail(){ return (E) tail.data; } } //Test.java import java.util.Scanner; public class Test { public static void main(String[] args) { SinglyLinkedList<Integer> sll = new SinglyLinkedList<>(); sll.addToHead(10); sll.addToHead(10); sll.addToHead(12); sll.addToTail(20); System.out.println(sll.getTail()); //20 System.out.println(sll.getHead()); //12 System.out.println(sll.deleteFromHead()); //12 System.out.println(sll.size()); //3 System.out.println(sll.getHead()); //10 sll.delete(10); System.out.println(sll.getHead()); //10 } }

*note

In singly linked list, deleteFromTail() and addToTail() lead to an issue scanning the entire list to stop right

in front of the tail. Solution: Doubly linked list

Page 35: Data structures and algorithms short note (version 14).pd

35 | P a g e

Doubly Linked List

Doubly linked list node consists of three fields

1. Data/ INFO field

2. Next field (reference field to successor)

3. Prev field (reference field to predecessor)

Figure 16: Doubly Linked list

Implementation:

//inserting to the tail public void addToTail(E e){ if(!isEmpty()){ tail = new DLLNode(e,null,tail); tail.prev.next = tail; }else head = tail = new DLLNode(e); n++; } //deleting from the tail public E deleteFromTail(){ E e = (E) tail.data; if(head==tail) //if only one in the list head = tail = null; else{ tail = tail.prev; tail.next = null; } n--; return e; }

*note

You can use java.util.LinkedList class. All the methods we implemented our self could be found here.

java.util.LinkedList<Integer> ll = new java.util.LinkedList<>(); ll.add(90); System.out.println(ll.getFirst()); ll.addFirst(7); System.out.println(ll.size()); System.out.println(ll.removeLast()); System.out.println(ll.size());

Page 36: Data structures and algorithms short note (version 14).pd

36 | P a g e

Usage of Doubly Linked list:

A great way to represent a deck of cards in a game.

The browser cache which allows you to hit the BACK button (a linked list of URLs)

Applications that have a Most Recently Used (MRU) list (a linked list of file names)

A stack, hash table, and binary tree can be implemented using a doubly linked list.

Undo functionality in Photoshop or Word (a linked list of state)

Circular Linked Lists A linked list, which is essentially a singularly linked list in which the next reference of the tail node is set

to refer back to the head of the list (rather than null).

Figure 17: Circular Linked list

We use this model to design and implement a new CircularlyLinkedList alss, which supports all of the

public behaviors of our SinglyLinkedlist class and one additional update method, i.e. rortate() which

moves the first element to the end of the Linked list.

Figure 18: rotate() method

(a) before the rotation; representing sequence { LAX, MSP, ATL, BOS }

(b) after the rotation; representing sequence { MSP, ATL, BOS, LAX }

Page 37: Data structures and algorithms short note (version 14).pd

37 | P a g e

Figure 19: Adding a new data item

Usage of circular linked lists:

Round Robin scheduling (how each process will come to ready queue and get chance to execute

in CPU)

Multiplayer board game (how players are getting chance to play)

Round Robin Scheduling

A round-robin scheduler could be implemented with a traditional linked list, by repeatedly performing

the following steps on linked list L.

process p = L.removeFirst( ); Give a time slice to process p; L.addLast(p);

With this new operation in circular linked list rotate(), round-robin scheduling can be efficiently

implemented by repeatedly performing the following steps on a circularly linked list C:

Give a time slice to process C.first( ); C.rotate( );

Page 38: Data structures and algorithms short note (version 14).pd

38 | P a g e

Lesson 04: Implementation of Stack and Queues using Linked Lists

//SLLNode.java public class SLLNode<E> { public E data; public SLLNode next; public SLLNode(E e){ this(e,null); } public SLLNode(E e,SLLNode n){ data = e; next = n; } }

*note sometimes we use a private inner class inside the LinkedStack or LinkedQueue to hide the

implementation of the SLLNode class.

In the following codes of implementation I have used a provate Node class instead of public SLLNode

class.

Implementation of Stack (LIFO) Elements are added to head or the first element; elements are removed from the head or the first

element.

//LinkedStack.java public class LinkedStack<E> implements Stack<E>{ private Node<E> first = null; private int n = 0; //inner class private class Node<E>{ E item; Node<E> next; } public int size(){ return n; } public boolean isEmpty(){ return first==null; }

Page 39: Data structures and algorithms short note (version 14).pd

39 | P a g e

public void push(E e){ //add to front Node oldFirst = first; first = new Node<>(); first.item = e; first.next = oldFirst; n++; } public E peek(){ return first.item; } public E pop(){ //remove from front if(isEmpty()) return null; else{ E item = first.item; first=first.next; n--; return item; } }

Implementation of Queue (FIFO) Elements are added to the rear of the linked list or to the last element; elements are removed from the

head or the first element.

//LinkedQueue.java public class LinkedQueue<E> implements Queue<E>{ private Node<E> first = null; private Node<E> last = null; private int n = 0; //inner class private class Node<E>{ E item; Node next; } public int size() { return n; } public boolean isEmpty() { return first==null; }

Page 40: Data structures and algorithms short note (version 14).pd

40 | P a g e

public void enqueue(E e) { if(isEmpty()){ first = new Node<E>(); first.item = e; first.next = null; last = first; }else{ Node newLast = new Node<E>(); newLast.item = e; newLast.next = null; last.next = newLast; last = newLast; } n++; } public E first() { return first.item; } public E dequeue() { if(isEmpty()){ return null; }else{ E item = first.item; first=first.next; n--; return item; } } }

Page 41: Data structures and algorithms short note (version 14).pd

41 | P a g e

Lesson 05: Recursion A programming technique in which a method/ function make one or more calls to itself during execution

Characteristics of a recursive function:

The method calls it self

At some point, this recursion should be terminated

o Otherwise it leads to an infinite loop

o Those points are called base cases.

Base case and the recursive case:

Let’s consider an example;

𝑛! = {1 𝑛 = 0𝑛. (𝑛 − 1)! 𝑛 ≥ 1

This definition is typical of many recursive definitions of functions.

First we have one or more base case stating that 𝑛! = 1 for 𝑛 = 0.

Second we have one or more recursive cases, which define the function in terms of

itself.

Examples of the use of recursion:

The factorial function

The Fibonacci function

English ruler structure

Binary search

o When the sequence is unsorted, the standard approach to search for a target value is to

use a loop to examine every element, until either finding the target or exhausting the

data set. This algorithm is known as linear search, or sequential search, and it runs in

O(n) time (i.e., linear time) since every element is inspected in the worst case.

File system

Page 42: Data structures and algorithms short note (version 14).pd

42 | P a g e

Example: Factorial of n

𝑛! = {1 𝑛 = 0𝑛. (𝑛 − 1)! 𝑛 ≥ 1

Implement with using a for loop:

int factorial(int n){ int fact = 1; if(n==1) return fact; else{ for(int i=1;i<=n;i++) fact *= i; return fact; } }

Implement using a recursive function:

int factorial(int n){ if(n==0) return 1; else return n*factorial(n-1); }

Execution model for factorial:

Calling the recursion function factorial(5)

5*factorial(4)

5*{4*factorial(3)}

S*{4*{3*factorial(2)}}

5*{4*{3*{2*factorial(1)}}}

Returning values after the base case

5*{4*{3*{2*1}}}

5*{4*{3*2}}

5*{4*6}

5*24

120

Page 43: Data structures and algorithms short note (version 14).pd

43 | P a g e

Example: Fibonacci Series

𝑓𝑖𝑏(𝑛) = {0 𝑛 = 01 𝑛 = 1𝑓𝑖𝑏(𝑛 − 1) + 𝑓𝑖𝑏(𝑛 − 2) 𝑛 > 1

The Fibonacci series is as follows:

0, 1, 1, 2, 3, 5, 8,…

Implementing using a for loop:

int fib(int n){ int old1 = 0; int old2 = 1; if(n==1) return old1; else if(n==2) return old2; else{ int fib = 0; for(int i=3;i<=n;i++){ fib = old1 + old2; old1 = old2; old2 = fib; } return fib; } }

Implement using a recursive function:

int fib(int n){ if (n==1) return 0; else if(n==2) return 1; else return fib(n-1)+fib(n-2); }

Invocation tree:

A tree structure which shows the invoking precedence of a recursive function

Invocation tree of Fibonacci function if n=4:

Figure 20: Invocation tree for fib(4)

Page 44: Data structures and algorithms short note (version 14).pd

44 | P a g e

Categorization of Recursive functions Recursive functions can be categorize in different ways, we examine 3 of them here.

1. Tail recursive and non tail recursive

2. Direct recursion and indirect recursion

3. Linear recursion, binary recursion and multiple recursion

Tail recursive Vs Non tail recursive A recursive function is said to be tail recursive if there is nothing to do after the methods returns expect

return value. Otherwise it is called non-tail recursive

Example for non-tail Recursive function:

factorial()

When returning back from a recursive call, there is still one pending operation, multiplication.

Therefore, factorial() is a non-tail recursive function.

Example for tail Recursive function:

void tailrec(int i){ if(i>0) System.out.println("i = "+i); tailrec(i-1); }

When returning back from athe above recursive call, there is still no pending operation,

Therefore, it is a tail recursive function.

*note that the following example is not a tail recursion.

void prog(int i){ if(i>0){ prog(i-1); System.out.println("i = "+i); prog(i-1); } }

Converting a non tail recursive function to a tail recursion

int tailFactorial(int n, int sofar){ if(n==1) return sofar; else return tailFactorial(n-1,sofar*n); }

Page 45: Data structures and algorithms short note (version 14).pd

45 | P a g e

Indirectly/ Mutually Recursion

Direct recursion:

If X() makes a recursive call to X() itself, it is called direct recursion,

void X(){ X(); }

Indirect recursion:

If recursion methods call them indirectly through calling other methods, it is called indirect

recursion. In general, indirect recursion is a circular sequence of two or more recursive calls

g()->f()->…->g()

void g(){ f(); } void f(){ g(); }

void main(){ g(); }

Linear recursive Vs Binary recursive Vs Multiple recursive

Linear Recursion:

If a recursive call starts at most one other, we call it a linear recursion.

Ex: factorial(int n), power(double x, int n)

public double power(double x, int n) { if (n == 0) return 1; else { double partial = power(x, n/2); double result = partial * partial; if (n % 2 == 1) result *= x; return result; } }

Page 46: Data structures and algorithms short note (version 14).pd

46 | P a g e

Figure 21: Recursion trace for an execution of power(2, 13)

Binary Recursion:

If a recursive call may start others, we call it a binary recursion.

Ex: fib(int n), binarySum(int[ ] data, int low, int high)

public static int binarySum(int[ ] data, int low, int high) { if (low > high) // zero elements in subarray return 0; else if (low == high) // one element in subarray return data[low]; else { int mid = (low + high) / 2; return binarySum(data, low, mid) + binarySum(data, mid+1, high); } }

Figure 22: Recursion trace for the execution of binarySum(data, 0, 7)

Page 47: Data structures and algorithms short note (version 14).pd

47 | P a g e

Multiple Recursion:

If a recursion call may start three or more others, we call it a multiple recursion.

Figure 23: Recursion trace for an execution of PuzzleSolve(3, S, U)

Exercise:

What the Tower of Hanoi algorithm?

Implement it using Java.

Refer:

http://www.tutorialspoint.com/data_structures_algorithms/tower_of_hanoi.htm

https://www.youtube.com/watch?v=MbybmBZVjWk

http://www.tutorialspoint.com/data_structures_algorithms/tower_of_hanoi_in_c.htm

Figure 24: The Tower of Hanoi

Page 48: Data structures and algorithms short note (version 14).pd

48 | P a g e

The mission is to move all the disks from source tower to the destination tower without violating the

sequence of arrangement.

Rules:

Only one disk can be moved among the towers at any given time.

Only the top disk can be removed.

No large disk can sit over a small disk.

*note Tower of Hanoi puzzle with n disks can be solved in minimum 2n-1 steps.

Algorithm:

Disks are numbered from top to bottom from I to n.

Our ultimate goal is to move disks n from source to destination and then put all the other (n-1) disks

onto it.

Step 1 – Move n-1 disks from source to aux

Step 2 – Move nth disk from source to destination

Step 3 – Move n-1 disks from aux to destination

Now we can imagine to apply the same recursive way for all given set of disks.

A recursive algorithm for tower of Hanoi can be driven as follows.

START

Procedure Hanoi (disk, source, destination, aux)

IF disk == 0, THEN

Move disk from source to destination

ELSE

Hanoi(disk-1, source, aux, destination) //step 1

Move disk from source to destination //step 2

Hanoi(disk-1, aux, destination, source) //step 3

END IF

END Procedure

STOP

Page 49: Data structures and algorithms short note (version 14).pd

49 | P a g e

Lesson 06: Trees A non linear data structure that represents nodes connected by edges. Tree provides a natural

organization data. Tree can be a ADT or a data structure depending on the implementation.

Components of a tree:

1. Nodes

2. edges

Figure 25: A tree with 17 nodes representing the organization of a fictitious corporation.

Refer:

http://www.tutorialspoint.com/data_structures_algorithms/tree_data_structure.htm

Examples where trees are used:

Organizational hierarchy of a company

Hierarchical relationship between files and directories in a computer’s file system

Components of a structured document such as a report, book etc.

Binary Tree:

A special data structure used for data storage purposes. A binary tree has a special condition

that each node can have only two children at maximum.

Page 50: Data structures and algorithms short note (version 14).pd

50 | P a g e

Terms related to Tree Data Structure

Figure 26: Terms related to Tree

Root: Element at the top of the hierarchy

Child: Node below a given node connected by its edge downward

Grandchild: Elements next in the hierarchy

Siblings: The nodes belongs to the same parent

Ancestors: Nodes situated in the path from a given node to the root node

Descendents: Nodes that are descendents of a given node

Leaf: Node which does not have any child nodes

Sub-tree: Descendents of a given node

Levels: Generation of the node

Visiting: Checking value of a node when control is on the node

Traversing: Passing through nodes in a specific order

Key: represents a value of a node based on which a search operation is to be carried out for a node

Page 51: Data structures and algorithms short note (version 14).pd

51 | P a g e

Figure 27: An Example tree

Leaves = {Mike, Ai, Sue, Chris}

Parent(Mary) = Joe

Grandparent(Sue) = Mary

Siblings(Mary) = {Ann, John}

Ancestors(Mike) = {Ann, Joe}

Descendents(Mary) = {Mark, Sue}

Node degree: Number of children a given node has

Tree degree : Maximum of node degrees

Node degrees of nodes in the Figure 27 are as follows:

NodeDegree(Joe) = 3 <= Tree degree

NodeDegree(Ann) = 2

NodeDegree(Mary) = 1

NodeDegree(John) = 1

NodeDegree(Mike) = 0

NodeDegree(Ai) = 0

NodeDegree(Mark) = 1

NodeDegree(Sue) = 0

NodeDegree(Chris) = 0

Level 3

Level 2

Level 1

Level 0 Joe

Ann

Mike Ai

Mary

Mark

Sue

John

Chris

Page 52: Data structures and algorithms short note (version 14).pd

52 | P a g e

Path: if n1, n2,…nk is a sequence of nodes in a tree such that ni is the parent of ni+1 for 1<=i<=k, then this

sequence is called a path from node n1 to nk.

Length of the path = number of nodes in the path – 1

*note Node to Node: length of path = 0

Height of a node: length of the longest path from a node to a leaf

Height of a tree: height of the root node

Depth of a node: length of the path from the root to the given node

Recursive Definition of a Tree:

A single node by itself is a tree. This node is also the root of this tree.

Let t1, t2,…tk be disjoint trees with roots r1, r2,…rk respectively, and let R be another node. We

can get a new tree by making R the parent of the nodes r1, r2,…rk.

Tree Traversal Methods of visiting (processing) each node in the tree exactly one time

Methods of traversal:

1. Breadth First

2. Depth First

a. Preorder traversal

b. Postorder traversal

c. Inorder traversal (for binary trees only)

Page 53: Data structures and algorithms short note (version 14).pd

53 | P a g e

PreOrder Traversal of a General Tree

Traverse a tree in node-left-right sequence

Figure 28: Preorder traversal of an ordered tree

Paper, Title, Abstract, $ 1, $ 1.1, $ 1.2, $ 2, $ 2.1, $ 2.2, $2.3, $ 3, $ 3.1, $3.2, References

Algorithm for PreOrder Traversal:

Procedure perOrder(root) if(root is not null) process(root) preOrder(leftSubtree) preOrder(rightSubtree) End if End Procedure

Processing order:

Figure 29: Processing Order in PreOrder Traversal

Page 54: Data structures and algorithms short note (version 14).pd

54 | P a g e

PostOrder Traversal of a General Tree

Traverse a tree in left-right-node sequence

Figure 30: Postorder traversal of the ordered tree

Title, Abstract, $ 1.1, $ 1.2, $ 1, $ 2.1, $ 2.2, $ 2.3, $ 2, $ 3.1, $ 3.2, $ 3, Reference

Algorithm for PostOrder Traversal:

Procedure PostOrder (root) if(root is not null)

PostOrder (leftSubtree) PostOrder (rightSubtree) process(root) End if End Procedure

Processing order:

Figure 31: Processing Order in PostOrder Traversal

Page 55: Data structures and algorithms short note (version 14).pd

55 | P a g e

InOrder Traversal of a Binary Tree

Traverse a tree in left- node-right- sequence

Figure 32: InOrder traversal of a binary tree

(((2 + 1) x 3)/ (9 – 5) + 2 ) – ((3 x (7 - 4) + 6)

Algorithm for inOrder Traversal:

Procedure inOrder (root) if(root is not null)

inOrder (leftSubtree) process(root)

inOrder (rightSubtree) End if End Procedure

Processing order:

Figure 33: Processing Order in inOrder Traversal

Page 56: Data structures and algorithms short note (version 14).pd

56 | P a g e

Euler Tour We can unify the tree traversal algorithms into a single framework known as a Euler tour traversal. The

Euler tour traversal of a tree T can be informally defined as a walk round T, where we start by going

from root forward its leftmost child, viewing the edge of T as being walls that we always keep to our left.

Figure 34: Euler Tour Traversal

Lets us consider an example;

Figure 35: PreOrder Traversal A, B, C, D, E, F

Figure 36: PostOrder Traversal C, D, B, F, E, A

Figure 37: InOrder Traversal C, B, D, A, E, F

Page 57: Data structures and algorithms short note (version 14).pd

57 | P a g e

Breadth First

Visit all the positions at depth d before visit the positions at depth d+1. This is a level by level approach

from layer 0 (root layer) to upwards.

Figure 38: Breadth first traversal of the ordered tree

Paper, Title, Abstract, $ 1, $ 2, $ 3, References, $ 1.1, $ 1.2, $ 2.1, $ 2.2, $ 2.3, $ 3.1, $ 3.2

Page 58: Data structures and algorithms short note (version 14).pd

58 | P a g e

Lesson 07: Binary Trees A data structure, in which a record is linked to two successor records, could be either a ADT or a data

structure

Types of Binary trees:

Full binary tree (proper binary tree or 2 - tree)

Complete binary tree

Balanced binary tree

Full binary tree:

A binary tree in which every node other than leaves has two children

Figure 39: A full binary tree

*note leaves are in blue color.

Complete binary tree

A binary tree in which every level, except possibly the last, is completely filled and all nodes are as far

left as possible. i.e. all nodes of the last layer should be filled from left to right

Figure 40: A complete binary tree

*note last level is in blue colour.

Page 59: Data structures and algorithms short note (version 14).pd

59 | P a g e

Examples:

Exercise:

Identify whether the following Binary tree is a full tree, a complete tree or a full and complete tree or

none of above mentioned.

Answer: this is not full, not complete, therefore none of above mentioned types

Balanced Binary tree

Height of the left and the right sub tress can vary by one level at most (maximum)

Figure 41: (a) non-balanced, (b) balanced

Page 60: Data structures and algorithms short note (version 14).pd

60 | P a g e

Implementation of Binary tree ADT Arrays based implementation and linked lists based implementation is discussed here.

Methods (operations) of a Binary Tree:

addRoot(value)

addLeft(position, value)

addRight(position, value)

set(position, value)

o replace existing element of the given position

attach(position, T1, T2)

o Attaches the trees of T1 and T2 as left and right sub trees of leaf position p

remove(position): value

find(value): node

Array based implementation For every position p of tree T, let f(p) be the integer defined as follows.

If p is the root of T, then f(p) = 0

If p is the left child of position q, then f(p) = 2f(q)+1

If p is the right child of position q, then f(p) = 2f(q)+2

The numbering function f is known as a level numbering of the position in a binary tree T, for it numbers

the positions on each level of T in increasing order from left to right.

*note Level numbering is based on potential positions within a tree, not actual shape of a specific tree,

so they are not necessarily consecutive.

Figure 42: Positions of the nodes when implemented using a array

Page 61: Data structures and algorithms short note (version 14).pd

61 | P a g e

Example:

*note The space usage of an array based representation depends greatly on the shape of the tree.

Linked List based implementation A natural way to realize a binary tree T is to use a linked structure, with a node that maintains

references to the elements stored at a position p and to the nodes associated with the children and

parent of p.

If p is the root element, then the parent node reference is null.

If p is a leaf node, both children references are null.

Figure 43: (a) Node structure (b) Example Binary tree

*note

Page 62: Data structures and algorithms short note (version 14).pd

62 | P a g e

root variable is a Node reference that keeps reference for the root node of the tree.

size variable is a int variable that keeps the track of the total number of nodes in the tree.

Node class of the linked structure used to implement the Binary tree ADT

class Node<E>{ E element; Node<E> parent; Node<E> leftChild; Node<E> rightChild; }

*note Sometimes in the Node class the reference to the parent node is absent.

class Node<E>{ E element; Node<E> leftChild; Node<E> rightChild; }

Binary Search Tree (BST): A BST is a binary tree in symmetric order.

Symmetric Order:

Each node contains one key (also known as data).

The keys in the left sub tree are less than the key in its parent node.

The keys in the right sub tree are greater than the key in its parent node.

Duplicate keys are not allowed.

A Binary Search Tree is where each node has a comparable key and an associated value and satisfies the

restriction that the key in any node is larger than the keys in all the nodes in that node’s left sub tree

and smaller than the keys in all nodes in that node’s right sub tree.

Other names for BST:

Ordered tree

Sorted binary tree

A node in a BST comprised of four fields:

key

value

left sub tree

right sub tree

Page 63: Data structures and algorithms short note (version 14).pd

63 | P a g e

Node Class of a Binary Search Tree:

class Node<Key extends Comparable<Key>,Value>{ Key key; Value val; //sometimes a tree do not have a value field Node leftChild; Node rightChild; Node(Key key, Value val){ this.key = key; this.val = val; } }

Figure 44: Binary Search tree

Figure 45: Order of growth of the running time for Ordered linked list and a binary tree

Binary Search:

If less, go left;

If greater, go right;

If equal, search hit

Binary Insert:

If less, go left;

If greater, go right;

If null, insert a new node, else if the key already exists reset existing value

Page 64: Data structures and algorithms short note (version 14).pd

64 | P a g e

Binary Search Tree Implementation using a Linked Structure

//This is a implementation of Map ADT using a BST. //I say this is a map since there are entries with a key and a value in each entry. public class BST <Value>{ private Node root; private class Node<Value>{ Integer key; //key is always a integer value in this example Value val; Node leftChild; Node rightChild; Node(Integer key, Value val){ this.key = key; this.val = val; } } public void put(Integer key, Value val){ root = put(root, key, val); } private Node put(Node x, Integer key, Value val){ if(x==null) return new Node(key,val); if(key<x.key) x.leftChild = put(x.leftChild,key,val); else if(key>x.key) x.rightChild = put(x.rightChild,key,val); else x.val = val; return x; } public Value get(Integer key){ Node x = root; while(x != null){ if(key<x.key) x = x.leftChild; else if(key>x.key) x = x.rightChild; else return (Value) x.val; //search hit } return null; //unsuccessful search } public void delete(Integer key){ //this is some what complex, you can try it later }

Page 65: Data structures and algorithms short note (version 14).pd

65 | P a g e

}

*note

In the above implementation of binary insertion, many BSTs correspond to same set of keys depending

on the order that we insert. If we insert keys according to an order, that leads to a worst case.

Number of compares for search/insert is equal to 1+ depth of node.

Figure 46: Different BSTs for same set of keys

public Node get(int p, int k){ if (p<0) return p; //unsuccessful search else if(k== key(p)) return p; //successful search else if (k< key(p)) //recur on left sub tree return get(left(p), k); else //recur on right sub tree if k>key(p) return get(right(p), k); }

*note

The above code segment is a recursive function for binary search.

Binary Deletion:

There are three cases that we have to pay attention.

o Case 1: Deleting a leaf node

Set null the pointer to that node

o Case 2: Deleting a node having only one child

Let the single child replace the parent

o Case 3: Deleting a node has two children

Find the leftmost node of its right sub tree (inOrder successor)

Let successor replaces node to be deleted

Or find the right most node of the left sub tree (inOrder predecessor)

Let predecessor replaces node to be deleted

Page 66: Data structures and algorithms short note (version 14).pd

66 | P a g e

AVL (Adelson, Velski & Landis) Trees A BST where the height of the left and right sub trees of each node differ by at most 1.

Balance factor = height(left sub tree) – height(right sub tree)

Accepted balance factors for a BST to become a AVL tree are -1, 0 and 1.

*note

What happens of input to binary search tree comes in sorted ascending order and descending manner?

Figure 47: Balanced not balanced not balanced

In second tree, the left sub tree of C has height 2 and right sub tree has height 0, so the difference is 2.

In third tree, the right sub tree of A has height 2 and left is missing, so it is 0, and the difference is 2

again. AVL tree permits difference balance factor to be only 1.

To make itself balanced, an AVL tree may perform 4 kinds of rotations:

1. Left rotation

2. Right rotation

3. Left – Right rotation

4. Right – Left rotation

Refer:

http://www.tutorialspoint.com/data_structures_algorithms/avl_tree_algorithm.htm

Figure 48: Left rotation

Page 67: Data structures and algorithms short note (version 14).pd

67 | P a g e

Figure 49: Right rotation

Figure 50: Example for a AVL tree

However there are many different varieties if trees and Binary trees.

Ex: tries, red black trees, etc

Page 68: Data structures and algorithms short note (version 14).pd

68 | P a g e

Lesson 08: Maps An ADT designed to store and retrieve values based upon a uniquely identifying search key for each.

Key value pairs of (k,v) are called entries where k for Key and v for Value of the entry.

Keys are required to be unique.

Maps are known as associative arrays, because the key serves somewhat like an index into the map, in

that it assists the map in efficiently locating the associated entry. Unlike a standard array, a key of a map

need not to be numeric, and it does not directly designates a position within the structure.

Common applications of maps:

A university’s information system relies on some form of a student ID as a key that is mapped to

that student’s associated record serving as the value.

The Domain-Name System (DNS) maps a host name to an IP address.

A social media site typically relies on a (nonnumeric) username as a key that can be efficiently

mapped to a particular user’s associated information.

Methods (operations) of a Map:

size():integer

isEmpty():Boolean

get(key:data_type_of_key):data_type_of_value

put(key:data_type_of_key, value: data_type_of_value):data_type_of_value

o return the existed value if there already an entry existing from that key

remove(key:data_type_of_key)

keySet():data_type_of_key[]

o Returns an iterable collection containing all the keys stored

Values():data_type_of_value[]

o Returns an iterable collection containing all the values of entries stored

entrySet():all key-value entries

o Returns an iterable collection containing all the key-value entries in Map

In java, we can use java.util.Map interface to implement a map.

Page 69: Data structures and algorithms short note (version 14).pd

69 | P a g e

Exercise:

Assume that initially Deque is empty.

Method Return Value Map content

isEmpty() true {}

put(5,A) null {(5,A)}

put(7,B) null {(5,A),(7,B)}

put(2,C) null {(5,A),(7,B),(2,C)}

put(8,D) null {(5,A),(7,B),(2,C),(8,D)}

put(2,E) C {(5,A),(7,B),(2,E),(8,D)}

get(7) B {(5,A),(7,B),(2,E),(8,D)}

get(4) null {(5,A),(7,B),(2,E),(8,D)}

get(2) E {(5,A),(7,B),(2,E),(8,D)}

size() 4 {(5,A),(7,B),(2,E),(8,D)}

remove(5) A {(7,B),(2,E),(8,D)}

remove(2) E {(7,B),(8,D)}

get(2) null {(7,B),(8,D)}

remove(2) null {(7,B),(8,D)}

isEmpty() false {(7,B),(8,D)}

entrySet() {(7,B),(8,D)} {(7,B),(8,D)}

keySet() {7,8} {(7,B),(8,D)}

values() {B,D} {(7,B),(8,D)}

Map implementation

//Map interface Map.java public interface Map<K,V> { int size(); boolean isEmpty(); V get(K key); V put(K key, V value); V remove(K key); Iterable<K> keySet(); Iterable<V> values(); Iterable<Entry<K,V>> entrySet(); }

Implementation of the above Map interface could be done in many ways

Array (ex: ArrayList in java)

Linked List

BST

Hash Table

Page 70: Data structures and algorithms short note (version 14).pd

70 | P a g e

The following code segment shows the structure of a entry(node) in linked list implementation of the

Map

class MapEntry<K,V>{ //equivalent to Node class K key; V value; MapEntry next; MapEntry prev }

Hash Tables One of the most efficient data structures for implementing a map

A map M supports the abstraction of using keys as addresses that help locate an entry. As a mental

warm-up, consider a restricted setting in which a map with n entries uses keys that are known to be

integers in a range from 0 to N-1. In this case we can represent the map using a lookup table of length N.

Figure 51: A lookup table with length 11 for a map containing entries (1,D), (3,Z), (6,C), and (7,Q)

Basic Map operations get, put, and remove can be implemented in O(1) worst-case time.

The challenges in extending this framework to the more general setting of a map:

If new keys that are not in the range (ex: 11) appear to put into the map, the lookup table

should be lengthen

Unnecessarily allocating space

Only integer values can be used as keys

The solution is the use of a Hash function to map general keys to corresponding indices in a table.

The keys will be distributed in the range from 0 to N-1 by a hash function, but in practice there may be

two or more distinct keys that get mapped to the same index. So we declare our table as a Bucket array.

Exercise:

Assume that you have following entries to enter in a hash table with 11 buckets indexed from 0 to 10.

(1,D), (25,C), (3,F), (14,Z), (6,A), (39,C) and (7,Q)

Use the following hash function

H(key) = key % 11

Page 71: Data structures and algorithms short note (version 14).pd

71 | P a g e

Figure 52: A bucket array of capacity 11 with entries (1,D), (25,C), (3,F), (14,Z), (6,A), (39,C) and (7,Q) using a simple hash function

Hash function is used to decide which bucket a key, value pair should be placed. The most simple hash

function is the modulus.

In the above exercise,

H(key) = key % 11

is the hash function.

Here 11 is the number of buckets in the bucket array. Therefore the output of any key value through

hash function lies between 0 and 10.

Collision:

Collisions occur if you have more than one item in a bucket. If you have perfect hash function,

there should be a very less number of collisions.

The problem is how you are going to distribute entries within the range of indices of the bucket

array.

Hash function consists of two parts

1. Hash code

2. Compression function

The advantage of separating hash function into two such components is that the hash code portion of

that computation is independent of a specific hash table size. This allows the development of a general

hash code for each object that can beused for a hash table of any size; only the compression function

depends upon the table size

Page 72: Data structures and algorithms short note (version 14).pd

72 | P a g e

Figure 53: Two parts of a hash function

Key

(ex: A to Z)

Hash Code

An integer

Compression function

Bucket number

0 to (N-1)

Page 73: Data structures and algorithms short note (version 14).pd

73 | P a g e

Lesson 09: Sorting Algorithms Sorting means to put elements of a list in a certain order.

There are 5 popular algorithms for sorting:

Simple sorting:

1. Bubble sort

2. Selection sort

3. Insertion sort

Advance sorting:

4. Merge sort

5. Quick sort

Classification of sorting:

1. Internal sorting

o The amount of data to be sorted is sufficient to process and the process is carried out in

the computer RAM.

2. External sorting

o The amount of data to be sorted is too much and process can’t carry out in the

computer RAM at once.

o Therefore data are stored on a secondary storage device.

Page 74: Data structures and algorithms short note (version 14).pd

74 | P a g e

Bubble Sort (Exchange sort) Reference: Lecture Slides

Bubble search focuses on successive adjacent pairs of elements in the list, compares them, and either

swaps them or not.

( 5 1 4 2 8 ) -> ( 1 5 4 2 8 ) -> ( 1 4 5 2 8 ) -> ( 1 4 2 5 8) -> ( 1 4 2 5 8 )

( 1 4 2 5 8 ) -> ( 1 4 2 5 8 ) -> ( 1 2 4 5 8 ) -> ( 1 2 4 5 8 )

( 1 2 4 5 8 ) -> ( 1 2 4 5 8 ) -> ( 1 2 4 5 8 )

( 1 2 4 5 8 ) -> ( 1 2 4 5 8 )

( 1 2 4 5 8 )

Implementation of bubble sort

public class Test { static int[] bubbleSort(int[] array){ for (int i = 0; i < array.length-1; i++) { for (int j = 0; j < array.length-1-i; j++) { if(array[j]>array[j+1]){ int temp = array[j]; array[j] = array[j+1]; array[j+1] = temp; } } } return array; } public static void main(String[] args) { int[] array = new int[]{1,2,3,4,3,29,8,2}; array = bubbleSort(array); for (int i = 0; i < array.length; i++) { System.out.println(array[i]); } } }

Page 75: Data structures and algorithms short note (version 14).pd

75 | P a g e

Selection Sort The basic operation of the selection sort is to identify the smallest element from the sequence of

elements.

As the first step scan the elements from the beginning to end and find the smallest and swap it with the

first one etc.

( 5 1 4 2 8 ) -> ( 1 5 4 2 8 ) Smallest value is 1, swap 1 and 5

( 1 5 4 2 8 ) -> ( 1 2 4 5 8 ) Next smallest value is 2, swap 2 and 5

( 1 2 4 5 8 ) -> ( 1 2 4 5 8 ) Next smallest value is 4, no change

( 1 2 4 5 8 ) -> ( 1 2 4 5 8 ) Next smallest value is 5, no change

( 1 2 4 5 8 ) Done

Implementation of insertion sort

public class Test {

static int[] selectionSort(int[] array){ for (int i = 0; i < array.length-1; i++){ int minIndex = i; for(int j = i+1; j<array.length; j++){ if(array[minIndex]>array[j]){ minIndex = j; } } int temp = array[i]; array[i] = array[minIndex]; array[minIndex] = temp; } return array; } public static void main(String[] args) { int[] array = new int[]{1,2,3,4,3,29,8,2}; array = selectionSort(array); for (int i = 0; i < array.length; i++) { System.out.println(array[i]); } } }

Page 76: Data structures and algorithms short note (version 14).pd

76 | P a g e

Insertion Sort The basic operation is insertion of a single element into a sequence of sorted elements.

Generally, suppose that we have already sorted first i-1 number of elements. Then we take ith element

and scan through the sorted list to see where to insert item i.

( 5 1 4 2 8 ) -> ( 1 5 4 2 8 ) Fix 5 and take 1 and see where to put. Put it.

( 1 5 4 2 8 ) -> ( 1 4 5 2 8 ) Fix 1,5 and take 4 and see where to put. Put it.

( 1 4 5 2 8 ) -> ( 1 2 4 5 8 ) Fix 1,4,5 and take 2 and see where to put. Put it.

( 1 2 4 5 8 ) -> ( 1 2 4 5 8 ) Fix 1,2,4,5 and take 8 and see where to put. Put it.

( 1 2 4 5 8 ) Done

Implementation of insertion sort

public class Test { static int[] insertionSort(int[] array){ for (int i = 1; i < array.length; i++){ int j=i-1; int number = array[i]; while(number<array[j]){ array[j+1] = array[j]; j--; } array[j+1] = number; } return array; } public static void main(String[] args) { int[] array = new int[]{1,2,3,4,3,29,8,2}; array = insertionSort(array); for (int i = 0; i < array.length; i++) { System.out.println(array[i]); } } } //best case if array is already in ascending order, //worst case if the array is in descending order.

Page 77: Data structures and algorithms short note (version 14).pd

77 | P a g e

Classic Sorting Algorithms (Advanced Sorting Algorithms) Critical components in the world’s computational infrastructure:

Full scientific understanding of their properties has enabled us to develop them into practical

system sorts.

Quicksort honored as one of the top 10 algorithms of 20th century in Science and engineering.

Classic sorting algorithms:

Shellsort

o Embedded systems

Mergesort

o Java sort for objects

Quicksort

o Java sort for primitive types

Divide and Conquer

Merge sort and quick sort use recursion in an algorithmic design pattern called divide and conquer.

Three steps of divide and conquer pattern

1. Divide

If the input size is smaller than a certain threshold (one or two elements), solve the

problem directly using a straightforward method and return the solution so obtained.

Otherwise, divide the input data into two or more disjoint subsets.

2. Conquer

Recursively solve the subproblems associated with the subsets.

3. Combine

Take the solution to the subproblems and merge them into a solution to the original

problem.

Merge-Sort We can visualize an execution of the merge-sort algorithm by means of a binary tree T, called merge-

sort tree. Each mode of T represents a recursive invocation (or call) of the merge-sort algorithm.

The following two figures summarizes the execution of the merge-sort algorithm for unsorted array of

{ 85, 24, 63, 45, 17, 31, 96, 50}.

The array is divided until it become a single element.

Then it is sorted backwards and keep on merging.

Page 78: Data structures and algorithms short note (version 14).pd

78 | P a g e

Figure 54: Merge-sort recursive invocation tree

Figure 55: Merge-sort returning procedure

Implementation of Merge-sort

When talk about the implementation of the merge-sort algorithm, we have to use separate functions for

merging and sorting.

Page 79: Data structures and algorithms short note (version 14).pd

79 | P a g e

public class Test { private static void merge(Integer[] array,Integer[] aux,int lo,int mid,int hi){ for(int k = lo; k<=hi; k++) aux[k] = array[k]; int i = lo; int j = mid + 1; for(int k = lo; k<=hi; k++){ if(i>mid) array[k] = aux[j++]; else if(j>hi) array[k] = aux[i++]; else if(aux[j]<aux[i]) array[k] = aux[j++]; else array[k] = aux[i++]; } } private static void sort(Integer[] array,Integer[] aux, int lo, int hi){ if (hi<=lo) return; int mid = (lo + hi)/2; sort(array,aux,lo,mid); sort(array,aux,mid+1,hi); merge(array,aux,lo,mid,hi); } static Integer[] mergeSort(Integer[] array){ Integer[] aux = new Integer[array.length]; sort(array,aux,0,array.length-1); return aux; } public static void main(String[] args) { Integer[] array = new Integer[]{1,2,3,4,3,29,8,2}; array = mergeSort(array); for (int i = 0; i < array.length; i++) { System.out.println(array[i]); } } }


Recommended