 # UNIT-V: Searching & Sorting

## Presentation on theme: "UNIT-V: Searching & Sorting"— Presentation transcript:

UNIT-V: Searching & Sorting
Objectives To understand classical approaches to sort arrays. To write programs that sort data using the three classical algorithms. To understand the divide and conquer sorting algorithms. To be able to analyze the efficiency of a sort algorithm. To understand two classical search algorithms. To write programs that search arrays. To be able analyze the efficiency of searching algorithms. 1

Sorting Sorting is the process through which data is arranged according to their values. Three sorting algorithms: Selection Sort Bubble Sort Insertion Sort 2

Selection Sort (1 of 4) The list is divided into two sub lists, categorized as sorted and unsorted lists. The sub lists are divided by an imaginary wall. Find the smallest element from the unsorted sub list and swap it with the element at the beginning of the unsorted sub list. After each selection and swapping, the wall between the two sub lists moves one element ahead, increasing the number of sorted elements and decreasing the number of unsorted sub list elements. Move one element from the unsorted sub list to the sorted sub list, that completes a sort pass. Thus a list of n elements need n-1 passes to completely rearrange the data.

Selection Sort (2 of 4) Example 4

Selection Sort (3 of 4) Flowchart 5

Complexity of Selection Sort
Selection Sort (4 of 4) Code: selection_sort ( int A[ ] , int n ) { int i , j , small , temp ; for ( i = 0 ; i < n ; i++ ) small = i ; for ( j = i + 1 ; j <= n ; j ++ ) if ( A [ j ] < A [ small ] ) small = j ; } temp = A [ i ] ; A [ i ] = A [ small ] ; A [ small ] = temp ; Complexity of Selection Sort Best Case : O ( n2 ) Average Case : O ( n2 ) Worst Case : O ( n2 ) 6 C program u7_ex1.c

Bubble Sort (1 of 4) The list is divided into two sub lists categorized as sorted and unsorted lists. The smaller element is bubbled from the unsorted sub list and moved to the sorted sub list. After moving the smallest element to the sorted list, the wall moves one element ahead, increasing the number of sorted elements and decreasing the number of unsorted ones. Move one element from the unsorted sub list to the sorted sub list, that completes one sort pass. Thus for a list of n elements, the bubble sort requires up to n-1 passes to sort the data. 7

Bubble Sort (2 of 4) Example: 8

Bubble Sort (3 of 4) Flowchart: 9

Complexity of Bubble_Sort
Bubble Sort (4 of 4) Complexity of Bubble_Sort The complexity of sorting algorithm is depends upon the number of comparisons that are made. Total comparisons in Bubble sort is n ( n – 1) / 2 ≈ n 2 – n Complexity = O ( n 2 ) Code: bubblesort ( int A[ ] , int n ) { int i , j, temp ; for ( i = 0 ; i < n ; i++ ) for ( j = n; j > i ; j - - ) if ( A [ j ] < A [ j-1 ] ) temp = A [ j ] ; A [ j ] = A [ j - 1 ] ; A [j -1] = temp ; } 10 C program u7_ex2.c

Searching Another common operation in computer science is searching, which is the process used to find the location of a target among a list of objects. In the case of an array, searching means that for a given value, one need to find the location of the first occurrence of the element of the array. There are two basic searches for arrays: 1. The sequential search 2.The binary search The sequential search can be used to locate an item in any array. The binary search, on other hand, requires the list to be sorted.

Linear/ Sequential search (1 of 9)
Sequential search is used whenever the list is unordered. Generally we use the technique only for small lists or lists that are not searched often. In the sequential search, search starts from the beginning of the list, and continue until the search element is found. The search process ends when there is no element found. This gives us two possibilities: either we find it or we reach the end of the list

Linear search Example (2 of 9)
Locating data in unordered list

Linear search Example (3 of 9)
Locating data in unordered list

Linear search Example (4 of 9)
Unsuccessful search in unordered list

Linear search Example (5 of 9)
Unsuccessful search in unordered list

Linear search Example (6 of 9)
Unsuccessful search in unordered list

Linear search Algorithm (7 of 9)
1.start 2.read n 3.read elements of list (a[]) 4.read element to be searched(item) 5.initialize found=0 for(i=0;i<n;i++) { If(a[i]==item) found=1 Break } 8.if (found==1) then print element a[i] is found i th location else print element not found 9.stop

Linear search Flowchart (8 of 9)

Linear search (9 of 9) Advantages : 1.Easy to understand
2.The list need not be in sorted order 3.If item is located at the beginning, not many comparisons are needed Disadvantages: 1.Slow, if list is large 2.When an item found at the end of the list, the search takes more time to execute 3.Involves more time and space. Complexity: Best case: O(1) Average case: O(n) Worst case: O(n) C program u7_ex6.c

Binary search (1 of 5) Sequential search algorithm is very slow if list contains more number of elements. If the array is not sorted, linear search is the only solution. If the list is sorted, we can use a more efficient algorithm called the binary search. binary search can be used whenever the list is large. This process splits the list into two. The binary search starts by testing the data in the element at the middle of the list. This determines if the target is in first half or second half of the list. If it is in first half , we do not need to check the second half. If it is in second half , we do not need to check the first half. In other words ,either way eliminate one half of the list from further consideration. Repeat this process until the target is found or not found. To find the middle of the list, three variables can be used, to identify the beginning of the list(first) to identify the middle of the list(mid) to identify the end of the list(last) mid=( first + last )/2

Binary search Example (2 of 5)
Binary search example if target is present in the list

Binary search Example (3 of 5)
Binary search example if target is not present in the list

Binary search Example (4 of 5)
Binary search example if target is not present in the list

Binary search Algorithm (5 of 5)
Iterative Algorithm int binarysearch (int a[], int target, int n) // pre: list is sorted in ascending order //post: ITERATIVE binary search will return the index of the target element, else -1 { int mid; int first = 0; int last = n-1 while ( first <= last ) mid = (first + last) / 2; if ( a[mid] == target ) return mid; if ( a[mid] > target ) last = mid - 1; else first = mid + 1; } return -1; Complexity of quick sort: Best case: O(log n) Average case: O(log n) Worst case: O(log n) C program u7_ex7.c

Data Structures A list is a collection of related data. We can divide lists into two categories: linear lists and non-linear lists. Linear lists are general lists, stacks and queues. Non-linear lists are trees and graphs.

Data Structures Atomic and Composite Data
Atomic Data: Data that we choose to consider as a single, nondecomposable entity. Example: An integer 4562 may be considered as a single integer value. Of course, you can decompose it into digits, but the decomposed digits do not have the same characteristics of the original integer. An atomic data type is a set of atomic data having identical properties. Atomic data types are defined by a set of values and a set of operations that act on these values. Example: int ,float ,char. Composite Data: Data that can be broken into subfields that have meaning. Example: Telephone number. A telephone number actually has three different parts. First is the country code, second is the STD code and third the telephone number.

Data Structures A data structure is a collection of elements and the relationships among them. Data structures can be nested. That is, we can have a data structure that consists of other data structures. A combination of elements, each of which is either a data type or another data structure. A set of associations or relationships involving the combined elements. For example, we can define two structures array and struct.

Abstract Data Type Linear lists are useful structures, we may use them in many applications. Rather than rewrite their functions each time, we can write functions once and put them in a library. Set of functions built like this is abstract data type(ADT). For example, the standard input/output library is an ADT. ADT consists of a set of prototype definitions that allow the programmer to use the functions while hiding the implementation. This generalization of operations with unspecified implementations is known as abstraction. An abstract data type(ADT) is formally defined as a data declaration packaged together with the operations that are allowed on the data type. The ADT definition implies two attributes: The structures are opaque. We can use them with out knowing how they are implemented. The operations are opaque. We know what they do, we don’t know how they do it.

LIST IMPLEMENTATIONS Arrays and pointers are used for list implementation. The array implementation uses static structures that are determine during the compilation. The pointer implementation uses dynamically allocated structures known as linked lists. Array Implementation The sequentiality of a list is maintained by the order of elements in the array(indexes). Searching an element in an array is very efficient, addition and deletion of elements are complex. Array implementations of lists can become excessively large, especially when there are several successors for each element. For these reasons arrays are less used.

A Linked list is an ordered collection of data in which each element contains the location of the next element. In a linked list, each element contains two parts: Data and links. The data parts holds the data to be processed. Links are used to chain the data together. They contain pointers that identify the next element. We can use a linked list to create linear and non-linear structures. In linear lists each element has only zero or one successor. In non-linear lists, each element can have zero, one or more successors. The major advantage of the linked list over the array is that data is easily inserted and deleted.

LIST IMPLEMENTATIONS Figure(a) shows a linked list implementation of a linear list. The link in each element, except the last, points to its unique successor, the link in the last element contains a null pointer, indicating the end of the list. Figure(b) shows a linked list implementation of a non-linear list. An element in a non-linear list can have two or more links. Here each element contains two links, each link points to one successor.

LIST IMPLEMENTATIONS Pointers to Linked Lists
Figure(c) contains an example of an empty list, linear or non-linear. We define an empty list as a pointer with a null value. Nodes: In linked list implementations, the elements in a list are called nodes. A node is a structure that has two parts: the data and one or more links. The nodes in a linked list are called self-referential structures . The data part in a node can be a single field, multiple fields, or a structure that contains several fields, but it always acts as a single field. Pointers to Linked Lists A linked list must always have a head pointer. Depending on how we use the list, we may have several other pointers as well.

General Linear Lists A general linear list is a list in which operations, such as retrievals, insertions, changes, and deletions, can be done anywhere in the list. Insert a Node We use the following four steps to insert a node into a linear list: Allocate memory for the new node. Determine the insertion point that is, the position within the list where the new data is to be placed. To identify the insertion position, we need to know only the new node’s logical predecessor(pPre). This pointer can be in one of two states: It can contain the address of a node, or it can be null. Point the new node to its successor. Point the predecessor to the new node. FIGURE Pointer Combinations for Insert

General Linear Lists FIGURE Insert Node to Empty List
Insert into an Empty List When the head of the list is null, then the list is empty . FIGURE Insert Node to Empty List The statements to insert a node into an empty list are shown below. pNew->link=pList; //set link to NULL pList =pNew; //point list to first node Note the order of these two statements. We must first point the new node to NULL,, then we can change the head pointer.

General Linear Lists Insert at the beginning
We insert a node at the beginning of the list whenever it must be placed before the first node of the list. We determine that we are inserting at the beginning of the list by testing the predecessor pointer(pPre). If it is null, then there is no predecessor, so we are at the beginning of the list. To insert a node at the beginning of the list, we simply point the new node to the first node of the list and then set the head pointer(pList) point to the new first node. FIGURE Insert Node at Beginning If you compare the two statements in both cases you will see that they are the same. This is because, logically, inserting into an empty list is the same as inserting at the beginning of a list.

General Linear Lists Insert in Middle
When we insert a node anywhere in the list, the predecessor(pPre) is not null. To insert a node between two nodes, we must point the new node to its successor and then point the predecessor to the new node. Again the address of the new node’s successor can be found in the predecessor’s link field. FIGURE Insert Node in Middle

General Linear Lists Insert at the end
When we insert at the end of the list, we only need to pint the predecessor to the new node. There is no successor to point to. It is necessary, however, to set the new node’s link field to NULL. The statements to insert a node at the end of a list are shown below. pNew->link=NULL; pPre->link=pNew; FIGURE Insert Node at End

General Linear Lists Insert Node Function
Write the function that puts it all together and inserts a node into the list. We are given the head pointer(pList), the predecessor(pPre), and the data to be inserted(item). We must allocate memory for the new node(malloc) and adjust the link pointers appropriately. NODE* insertNode(NODE* pList, NODE* pPre, DATA item);

General Linear Lists

General Linear Lists Delete a Node
When we delete a node we logically remove the node from the linear list by changing various link pointers and then physically deleting it from heap. We can delete the first node, any node in the middle, or the end node of a list. Delete First Node When we delete the first node, we must reset the head pointer to point to the first node’s successor and then recycle(free) the deleted node. FIGURE Delete First Node

General Linear Lists General Delete case
Same logic handles deleting a node in the middle of the list and deleting a node at the end of the list. For both of these cases, we simply point the predecessor node, identified by pPre, to the successor of the node being deleted. The node being deleted is identified by the current node pointer, pCur. Its successor is pCur->link. pPre->link=pCur->link; free(pCur);

General Linear Lists Locating Data in Linear Lists
When we insert and delete data in a linear list, we must first search the list. To insert a node, we search to identify the logical predecessor of the new node in its key sequence. To delete a node, we search to identify the location of the node to be deleted and its logical predecessor. Search a Linear List For insert, we need to know the predecessor to the node to be inserted. For delete we need to know the predecessor to the node to be deleted. Also, to locate a node for processing, such as adding a count or printing its contents, we need to know its location.

Linear List Search Results
General Linear Lists Table Linear List Search Results

Example1:Program to implement single linked list with all operations
General Linear Lists FIGURE Search Results Example1:Program to implement single linked list with all operations

Stacks A stack is a linear list in which all additions and deletions are restricted to one end, called the top. Stacks are known as the last in– first out (LIFO) data structure. A graphic representation of a stack is shown in figure.

Stacks Stack structures Data structure
Several data structures can be used to implement a stack. we implement the stack as a linked list. Data structure To implement the stack linked list, we need two different structures, a head and a data node. The head structure contains meta data that is, data about data, and a pointer to the top of the stack. The data structure contains data and a link pointer to the next node in the stack. The conceptual and physical implementations of the stack are shown in figure.

Stacks Stack Head Stack Data node
The head for a stack requires , only two attributes. A top pointer and a count of the number of elements in the stack. A basic head structure is shown in figure Stack Data node The rest of the data structure is a typical linked list data node. Data node contains a link pointer to other data nodes , making it a self-referential structure. The stack data node is also shown in above figure.

Stacks Stack Algorithms Push stack
Implementation of a stack depends somewhat on the implementation language, it is usually implemented with a stack head structure in C. Push stack Push stack inserts an element in to the stack . When we push data into a stack, it needs to find memory for the node. once the memory is allocated, we simply assign the data to the stack node and then set the link pointer to point to the node currently indicated as the stack top. To develop the insertion algorithm using a linked list, we need to analyze three different stack conditions Insertion into an empty stack. 2. Insertion into a stack with data. 3. Insertion into a stack when the available memory is exhausted.

Stacks When insert into a stack that contains data, the new node’s link pointer is set to point to the node currently at the top, and the stack’s top pointer is set to point to the new node. When we insert into an empty stack, the new node’s link pointer is set to null and the stack’s top pointer is set to point to the new node. The following figure traces a push stack operation in which a new pointer( pnew) is used to identify the data to be inserted into the stack and shows before and after conditions when we push data into a stack.

Stacks Pop Stack Pop stack sends the data in the node at the top of the stack back to the calling algorithm. It then adjusts the pointers to logically delete the node. After the node has been logically deleted, it is physically deleted by recycling the memory, that is, returning it to dynamic memory. After the count is adjusted by subtracting 1, the algorithm returns the statuts to the caller: if the pop was successful, it returns true, if the stack is empty when pop was called, it returns false. The operations for pop stack are traced in figure.

Example 2 stack implementation using linked list
Stacks Stack Demonstration To demonstrate the push and pop algorithms, we write a program that inserts random numbers into a stack. After the numbers are inserted, they are popped and printed. Example 2 stack implementation using linked list

Example 3 stack implementation using array
STACK ADT USING ARRAYS Implementing a stack in an array: the base is found at the first stack element, index 0. The top then moves up and down as data is inserted and deleted. To push an element into the stack, add 1 to the top and use it as the array index for the new data. To pop an element from the stack, copy the data at index location top and then subtract 1 from top. The structure for the array implementation with a maximum size of 5 elements is shown in the following figure. Example 3 stack implementation using array

STACK APPLICATIONS Postponement Infix to postfix transformation
Stacks can be useful when the usage of data needs to be postponed. Infix to postfix transformation Arithmetic expressions are represented in three ways- infix, prefix and postfix. The infix notation is the normal algebraic notation where the operator comes between the operands (A+B). In prefix notation, the operator comes before the two operands(+AB). In postfix notation it comes after the operands(AB+) Converting an infix expression to postfix is as follows Parenthesize the expression using explicit parentheses and arithmetic precedence. 2. Convert all infix notations in each parenthesis to postfix notation ( i.e move the operator to the position of the closing parentheses), starting from the innermost parenthesis. 3. Remove the parentheses.

STACK APPLICATIONS Demonstration of Manual infix to postfix conversion
Step 1 A + B * C by placing paranthesis results ( A + ( B * C ) ) Step 2 moves the multiply operator after C ( A + (B C *) ) moves the addition operator to between the last two closing parentheses. This change is made because the closing parentheses for the plus sign is the last parenthesis. We now have ( A ( B C * ) + ) Finally ,step 3 removes the parentheses A B C * +

Example 4 converting infix expression to postfix expression
STACK APPLICATIONS Infix Transformations A + B * C – D / E Converts to A B C * + D E / - Above transformation is illustrated in following figure. Example 4 converting infix expression to postfix expression

STACK APPLICATIONS Evaluation of Postfix Expression
In evaluation of postfix expression, it is the operands that are pushed on to the stack. The postfix expression is scanned from left to right. Any operands encountered are pushed on to the stack. When an operator is encountered, the top two operands are popped from the stack. The operation is performed and the result is pushed back on to the stack. In the end, the final value is popped from the stack and returned.

Example 5 evaluation of postfix expression
STACK APPLICATIONS Evaluation of Postfix Expression For example given expression is A B C + * And assuming that A is 2, B is 4, and C is 6 , the following figure shows the evaluation of postfix expression. Example 5 evaluation of postfix expression

Queues Definition A queue is a linear list in which data can be inserted at one end, called the rear, and deleted from the other end, called the front. It is a first in–first out (FIFO) restricted data structure. A queue is same as Ex: 1)a line of people waiting for a bus at bus station. 2)a list of waiting jobs to be processes by a computer. The fig-1 below shows two examples of a queue. A) A queue of people B) a computer queue

Queues Objectives: Queue Operations Queue Linked List Design
Queue Functions Queue Demonstration

Queues Queue operations: The two basic queue operations:
1)Insertion operation (enqueue) 2)Deletion operation (dqueue) Data can be inserted at the rare in queue Data can be deleted at front in queue

Queues Enqueue The queue insert operation is known as enqueue
After the data have been inserted into the queue, the new element become the rear The potential problem with the queue insertion is running out of room for the data If there is no enough room for another element in the queue, the queue is in an overflow state Fig-2 shows enqueue implementation FIGURE Enqueue

Queues Dequeue The queue deletion operation is known as dequeue
Data at the front of the queue are returned to the user and removed from the queue. If there is no data in the queue when a dequeue is attempted , the queue is in an underflow state Fig-3 shows dequeue implementation FIGURE Dequeue

We can implement queue using linked list Data Structure We need two different structures to implement the queue: 1) queue head structure 2) a data node structure The queue will have one head node and zero or more data node Fig shows the conceptual and physical implementations for our queue structure. FIGURE Conceptual and Physical Queue Implementations

The queue requires two pointers and a count These field are stored in the queue head structure . Other queue attributes such as 1)the maximum number of items that were ever present in the queue and 2)total number of items that have been processed through the queue Fig shows the queue head structure. Queue Data Structure The queue data node contains the user data and a link field poniting to the next node These node are stored in dynamic memory The nodes are inserted and deleted as requested by using program Fig shows the queue node structure

Queues Linked List FIGURE Queue Data Structure

There two basic functions in queue using linked list 1) Enqueue 2) Dequeue Enqueue when we insert data into a queue, the queue’s front and rear pointers must be set to the new node When we insert data into a queue with data already in it, we must point both the link field in the last node and rear pointer to the new node. If insert is successful, it returns true else if no memory left for the new node, it returns false Fig shows enqueue

Queues Linked List FIGURE -6 Enqueue Example

Example -6 for queue using linked list
Queues Linked List Dequeue If the queue is empty, we have underflow and return false We first ensure that the queue contains data. If the queue contains data, then set the front pointer to the next item in the queue If we dequeue the last item, the queue front pointer automatically becomes null pointer. it also assigns null pointer to link filed of the last node. Fig shows dequeue implementation. Example -6 for queue using linked list

Queues Linked List FIGURE -7 Dequeue Examples

Queues using arrays Enqueue We can also implement queue using arrays.
There are mainly two functions in implementation of queue: 1) enqueue 2) dequeue Enqueue An enqueue to an empty queue is placed in the first element of the array. which becomes both front and rear. Subsequent enqueues are placed at the array locations following rear i.e if the last element is stored at array location 11,the data for next enqueue is placed in element 12.

FIG-8 Physical structure
Queues using arrays Dequeue A dequeue takes place at the front of the queue. As an element is deleted from the queue, the queue front is advanced to the next location Fig-8 shows about physical structure of queue Queue ary front rare count Max size 7 17 5 11                 ` FIG-8 Physical structure

Example -7 for queue using array
Queues using arrays Disavantages: In a queue, we delete elements at front and insert elements at rear. when rear reaches maximum size of an array, we can’t Insert new element though we have space at front end of a queue. Therefore queue is not full because there are empty elements at the beginning of the array. It shows queue is full. Fig shows array queue with last elements filled Queue rare Queue front              Fig array queue with last elements filled Example -7 for queue using array

Example -8 for circular queue using array
Queues using arrays This disadvantage is overcome by shifting all the elements from end to the beginning of the array In the above example, we shift from element 5 to 0 and 6 to 1 and so on. A more efficient alternative is found in circular queue In a circular queue, the last element is logically followed by the first element Example -8 for circular queue using array

Example -9 for circular queue using array
Queues using arrays Array queue implementation: Operations in queue 1) Create the queue 2) Destroy the queue 3) Enqueue 4) Dequeue 5) Queue front 6) Queue rear 7) Queue count 8) Empty queue 9) Full queue Example -9 for circular queue using array

Queues using arrays Array queue implementation: Operations in queue
1) Create the queue: The create queue allocates memory to an array. we can allocate memory dynamically. 2) Destroy the queue: destroy queue function is called at last to destroy the queue. If queue memory is allocated dynamically then we free the allocated memory in this function 3) Enqueue: this function is used to insert a new element in the queue

Queues using arrays 4) Dequeue: this function is used to delete the element from the queue 5) Queue front: the queue front logic parallels dequeue except the status of the queue is not changed. 6) Queue rear : the queue rear returns a pointer to the data at the rear of the queue without changing the contents 7) Queue count: it returns number of elements in the queue 8) Full queue: It simply test the count to maximum size of the queue. if they are equal, queue is full else queue is not full 9) Empty queue: It simply test the count to zero if they are equal queue is empty else not empty

Similar presentations