* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
Download Data Structures Using C(cs221) - Prof. Ramkrishna More Arts
Survey
Document related concepts
Transcript
University of Pune Data Structures Using C (CS-211) S.Y.B.Sc.(Computer Science) Semester I 1 Advisors: Prof. A. G. Gangarde (Chairman, BOS-Comp. Sc.) Chairman: Prof. S. S. Deshmukh (Head & Vice-Principal, Modern College, Pune 5) Co-ordinator: Mr. A. V. Sathe Authors: Mrs. Madhuri Ghanekar Mrs. A. S. Bachav Mrs. Smita Ghorpade Mrs. G. S. Marane Mrs. Sonali Ghule Board of Study (Computer Science) members: 1. Mr. M. N. Shelar 2. Mr. S. N. Shinde 3. Mr. U. S. Surve 4. Mr. V. R. Wani 5. Mr. Prashant Mule 6. Dr.Vilas Kharat 7. Mrs. Chitra Nagarkar 2 Table of Contents About the work book……………………………………………………………4 1. Sorting Techniques……………………………………………………………6 2. Searching Techniques………………………………………………………...12 3. Linked List……………………………………………………………………...15 4. Stack……..………………………………………………………………………29 5. Queue..………..…………………………………………………………………34 6. Trees....…………………………………………………………………………...41 7.Graph...…………………………………………………………………………...47 3 About the Work Book Objectives of this book This workbook is intended to be used by S.Y.B.Sc(Computer Science) students for the two computer science laboratory courses. The objectives of this book are 1. The scope of the course. 2. Bringing uniformity in the way course is conducted across different colleges. 3. Continuous assessment of the students. 4. Providing ready references for students while working in the lab. How to use this book? This book is mandatory for the completion of the laboratory course. It is a measure of the performance of the student in the laboratory for the entire duration of the course. Instructions to the students 1) 2) 3) 4) Students should carry this book during practical sessions of computer science. Students should maintain separate journal for the source code, SQL queries/commands along with outputs. Student should read the topics mentioned in Reading section of this book before coming for practical. Students should solve only those exercises which are selected by practical in-charge as a part of journal activity. However, students are free to solve additional exercises to do more practice for their practical examination. Exercise Set Self Activity Difficulty Level NA SET A Easy SET B Medium SET C Difficult 5) Rule Student should solve these exercises for practice only. All exercises are compulsory. At least one exercise is mandatory. Not Compulsory. Students will be assessed for each exercise on a scale of 5 1. Note Done 2. Incomplete 3.Late Complete 4.Needs Improvement 5.Complete 6.Well Done 0 1 2 3 4 5 4 Instructions to the Practical In-charge 1) 2) 3) 4) 5) 6) Explain the assignment and related concepts in around ten minutes using white board if required or by demonstrating the software. Choose appropriate problems to be solved by student. After a student completes a specific set, the instructor has to verify the outputs and sign in the provided space after the activity. Ensure that the students use good programming practices. You should evaluate each assignment carried out by a student on a scale of 5 as specified above ticking appropriate box. The value should also be entered on assignment completion page of respected lab course. 5 SESSION 1: Sorting Techniques Start Date / / Objectives To learn about: Sorting array elements in increasing/decreasing order Various sorting methods and their time complexity Searching methods and their time complexity Reading You should read the following topics before starting the exercise. 1. Numeric / Character arrays and Array of structures. 2. Compare the one element with another element of the array 3. Swap the content of one location with another location in the array. 4. How to find the time complexity of an algorithm? Ready References 1.1 Time complexity The time T(P) taken by a program P is the sum of the compile time and the run (or execution) time. As compilation is a one time procedure, we approximate time complexity to execution time.For this we calculate the number of executable steps of any program which can be stored in a variable stepcnt. Algorithm Sum(a,n) 1 { 2 S= 0.0; 3 Stepcnt = stepcnt +1; 4 For i = 1 to n do 5 { 6 Stepcnt=stepcnt+1; 7 S = S + a[i]; 8 Stepcnt = stepcnt +1; 9 } 10 Stepcnt = stepcnt +1; 11 Stepcnt = stepcnt +1; 12 Return S; 13 } Comments Stepcnt is initially zero. For the execution of for statement increment it once. Increment for the assignment statement For the last invocation of for For the return Important operations for sorting and searching algorithms are as follows: 1. Number of interchanges/swaps 2. Number of comparisons As these 2 operations are more time consuming, for sorting and searching algorithms swapcnt and compcnt is calculated to find number of swaps and number of comparisons along with the stepcnt. 6 Program Segment for (i=O; i< n; i++) { stepcnt ++; compcnt++; if ( x[i] > x[j] ) { swapcnt++; temp = x[i]; x[i] = x[j]; x[j] = x[i]; stepcnt +=4; } Comments Comparing 2 elements So compcnt++ Swapping of 2 elements So swapcnt ++ Total 4 steps . so stepcnt += 4 1.2 Sorting Techniques Most of the applications store lots of data and to find the required data from it, we must keep it in some sensible order. The sorting refers to the operation of arranging data in some given order, such as increasing or decreasing, with numerical or character data. There are various sorting methods are available. Most commonly used methods are (1) Bubble Sort (2)Insertion Sort (3)Merge Sort (4)Quick Sort 1.2.1 Bubble Sort In this method successive elements are compared and exchange according to the order required. The list to be sorted is traversed several times. Each pass puts one element in its correct position. In successive parses, the largest element sinks to the bottom. 1. 2. 3. 4. 5. 6. 7. 8. Algorithm Accept n numbers into the array x Initialize i=O Repeat step 4 to 7 as long as (i<n) if (x[j]>x[j+1]) interchange x[j] and x[j+1] Increment j if j<n-1-j got step 3 Increment i stop Example: Original array x After Pass 1 After Pass 2 After Pass 3 After Pass 4 After Pass 5 57 25 25 25 12 12 25 48 48 12 25 25 48 57 12 37 37 37 Complexity The number of passes: n-1 In first pass n-1 comparisons In second pass n-2 comparisons and so on Total=(n-1)+(n-2)+……+1= n(n1)/2 Time Complexity=O(n2) Best case= O(n2) Worst case= O(n2) 92 12 37 48 48 48 12 37 57 57 57 57 37 92 92 92 92 92 7 1.2.2 Insertion Sort Place an element into correct position in growing sorted list of data. Assume that we have a sorted list of i elements. We take the next element and add it to the sorted list in such a position that a new list of (i+1) elements is sorted. Algorithm Accept n numbers into the array x Let x[O] is sorted list of one element. Let j=1 Let newelem=x[j] and i=j-1 Repeat step 6 to 7 as long as (i>=O) and (newelem<x[i]) 6. Move x[i] at (i+1) position 7. i=i-1 8. Insert newelem at position (i+1) i.e. x[i+1]=newelem 9. j=j+1 1O. If j<n go to step 4 11. stop Complexity Best case: If the initial data is sorted, only one comparison is made in each pass. So the complexity is 0(n). 1. 2. 3. 4. 5. Example: Let x[O] is sorted list: Pass-1: newelem=25: Pass-2: newelem=48: Pass-3: newelem=57: Pass-4: newelem=12: Pass-5: newelem=36: 57 25 25 25 25 25 25 12 12 12 12 25 57 48 48 48 48 25 25 25 25 25 Worst case: If the initial data is in reverse order, total number of comparisons for (n-1) passes will be 1+2+3+……+(n-1)=n(n-1)/2 So the complexity is 0(n2) 48 48 57 57 57 48 48 48 48 48 36 12 12 12 12 57 57 57 57 57 48 48 36 36 36 36 36 36 36 36 57 57 57 1.2.3 Merge Sort It is based on Divide and Conquer Strategy. First the list to be sorted is decomposed into two sublists(Divide). Each sublist is sorted independently(Conquer). Then these two sorted sublists are merged into sorted sequence(Combine). 8 Algorithm //Array x of size n is to be sorted, Initially lb=O, ub=n-1 Mergesort(x, lb, ub) 1. If (lb<ub) do steps 2 to 5 otherwise goto 6 2. Find mid=(lb+ub)/2 3. call mergesort(lb, mid) 4. call mergesort(mid+1, ub) 5. call merge(x, lb, mid, ub) 6. stop //Merge two sorted sublists x[lb..mid] and x[mid+1..ub] to create a new sorted list x[lb…ub] Merge(x. lb, mid, ub) 1. //copy x into temp list For i=lb to ub do temp[i]=x[i] 2. Let i=lb, j=mid+1, k=lb 3. Repeat steps 4 to 6 while (i<=mid and j<=ub) 4. If (temp[i]<=temp[j]) //elem of first sublist is smaller/equal x[k]=temp[i] //copy elem of first sublist Increment i and k 5. Otherwise //elem of second sublist is smaller x[k]=temp[j] //copy elem of second sublist Increment j and k 6. Continue step 3 7. Copy remaining elements of first sublist into x if any 8. Copy remaining elements of second sublist into x if any 9. stop Complexity After pass P, the array x is partitioned into sorted subarrays where subarray, except possibly the last, will contain exactly 2P elements. Hence the algorithm requires at most log2 n passes to sort n elements of array x. However each pass merges a total of n elements. So time complexity, Best Case: O(n log n) Worst Case: O(n log n) 9 Example: Original array: [66 33 40 22 55 88 60 11] Pass-1: Merge each pair of elements to obtain the list of sorted pairs [66 33 40 22 11] [33 66] 55 88 [22 40] 60 [55 88] [11 60] Pass-2: Merge each pair of pairs to obtain the list of sorted quadruples [33 66] [22 40] 60] [22 33 40 60] [55 88] [11 [11 55 60 88] Pass-3: Merge each pair of sorted quadruples to obtain the sorted array [11 22 33 40 55 60 88] 1.2.4 Quick Sort It is also based on Divide and Conquer Strategy. Let x be an array and n be number of elements in the array to be sorted. To find proper position j for any element a of array x, it is partitioned at position j such that (I) All elements from 0 to j-1 are smaller than or equal to a (II) All elements from j+1 to n-1 are greater than a. Algorithm //sort array x[lb..ub]. Initially lb=0 and ub=n-1 QuickSort(x, lb, ub) // x is array 1. If (lb<ub) do steps 2 to 8 otherwise goto 9 2. Let i=lb, j=ub, a=x[i] //to find posi for a 3. Repeat step 4 while (x[j]>a && j>i) 4. decrement j 5. Interchange x[i] and x[j] 6. Repeat step 7 while (x[i]<=a && i<j) 7. increment i 8. Interchange x[i] and x[j] 9. quicksort(x, lb, i-1) //recursive call to sublist 10. quicksort(x, i+1, ub)//recursive call to sublist 11. Stop Complexity Best case: The reduction step produces two sublists. The reduction step in the kth level there will be 2k sublists. Each level uses at most n comparisons. So the time complexity is O(n log n) Worst case: If the list is already sorted then at first level, first list is empty and second list contains (n-1) elements. Accordingly the second element require (n-1) comparisons and so on. So the total comparisons are n+(n-1)+…+2+1= n(n+1)/2 The time complexity is O(n2) 10 Practical Assignments SET A 1) Write a C program to read n numbers from the user and sort them in ascending! descending order using Bubble sort method. Use step count, swap count, comp count in your program to calculate time complexity and at end display the 3 counts 2) Write a C program to read n numbers from the user and sort them in ascending!descending order using Insertion sort method. Use step count, swap count, comp count in your program to calculate time complexity. SET B 1) Write a C program to read n numbers from the user and sort them in ascending! descending order using Merge sort. Use step count, swap count, comp count in your program to calculate time complexity. 2) Write a C program to read n numbers from the user and sort them in ascending! descending order using Quick sort. Use step count, swap count, comp count in your program to calculate time complexity. SET C 1) Write a program that accept name of persons into array and sort them in alphabetical order. 2) Write a program that accept employee name, age and salary into array and sort them in descending order of salary. [ Hint: Use array of structure] Assignment Evaluation 0: Not Done [ ] 1:Incomplete [ ] 2.Late Complete [ ] 3:Needs Improvement [ ] 4:Complete [ ] 5:Well Done [ ] Signature of the Instructor Date of Completion ! ! End of Session 11 SESSION 2: Searching Techniques Start Date ! ! Objectives To learn about: Searching a desired element in the array Various searching methods and their time complexity Reading You should read the following topics before starting the exercise. 1. Numeric ! Character arrays and Array of structures. 2. Compare an element with any element of the array 3. Sorting the content of array in ascending or descending order 4. How to find the time complexity of an algorithm? Ready References Let LIST be a collection of data elements into memory. Searching refers to the operation of finding the location of given ITEM in LIST. The searching said to be successful, if ITEM is found in LIST and unsuccessful otherwise. There are two commonly used searching methods or algorithms (1) Linear Search (2) Binary Search 2.1. Linear Search In this method ITEM is compare with each element of LIST one by one. That is, first we test whether LIST[0] = ITEM and then we test whether LIST[1]=ITEM and so on. This method which traverses LIST sequentially to locate ITEM is called Linear or Sequential search. Algorithm !!Linear Search ITEM in LIST of n elements 1. LOC=0 2. Repeat steps 3 to 4 while (LOC<n) 3. If (LIST[LOC]=ITEM) print ITEM found at location LOC stop 4. Otherwise increment LOC by 1 continue step 2 5. print ITEM not found in LIST 6. Stop Complexity Best Case: ITEM found at location 1 Number of comparisons=1 Worst Case: ITEM not found in LIST Number of comparisons=n Complexity is O(n) An average of (n+1)!2 comparisons are required to search ITEM in a LIST. Time complexity is O(n) 12 2.2. Binary Search If the collection elements in a LIST is stored in sorted order (ascending or descending) then there is extremely efficient searching algorithm called Binary Search is available. In this method LIST is divided into two halves. The ITEM to be search is compare with middle element of the LIST. If matches then search terminates otherwise continues further. If the ITEM is less than middle element then the search proceeds in upper half of the LIST. If the ITEM is greater than middle element then the search proceed in lower half of the LIST. Algorithm !!Binary Search ITEM in LIST of n elements !!LB-Lower Bound UB-Upper Bound of LIST Recursive Bsearch(LIST, ITEM, LB, UB) 1. If (LB>UB) Print ITEM not found in LIST Stop 2. Find MID=(LB+UB)!2 3. If (LIST[MID]=ITEM) Print ITEM found at location MID in LIST Stop 4. Otherwise If (LIST[MID]<ITEM) Bsearch(LIST, ITEM, LB, MID-1) !!call 5. Otherwise 6. Bsearch(LIST, ITEM, MID+1, UB) !!call Non-Recursive 1. Let LB=O, UB=n-1 2. Repeat steps 3 to 5 while (LB<UB) 3. Find MID=(LB+UB)!2 4. If (LIST[MID]=ITEM) Print ITEM found at location MID in LIST Stop 5. Otherwise If (LIST[MID]<ITEM) UB=MID-1 !!search in upper half Continue step 2 6. Otherwise LB=MID+1 !!search in lower half Continue step 2 7. Print ITEM not found in LIST 8. Stop Complexity Best Case: ITEM found at MID position Number of Comparisons=1 Worst Case: ITEM not found in LIST After 1 comparison, remaining size of LIST to be search is (n!2)=(n!21). After 2 comparisons, remaining size of LIST to be search is (n!4)=(n!22). After k comparisons, remaining size of LIST to be search is (n!2k). If after k comparisons, remaining file size is 1 then (n!2k)=1. That means n=2k k=log2 n So, time complexity is O(log2 n) 13 Practical Assignments SET A 1) Write a program to accept list of n numbers and search a given number using Linear Search. Use stepcnt, swapcnt, compcnt in your program to calculate time complexity and at end display the 3 counts 2) Write a program to accept list of cities and search a given city using Linear Search. Use stepcnt, swapcnt, compcnt in your program to calculate time complexity and at end display the 3 counts SET B 1) Write a program to accept list of sorted n numbers and search a given number using Binary Search. 2) Write a program to accept list of student names in alphabetical order and search a given name using Binary Search. SET C Accept city name, area and population for n cities into array. Find the area and population of given city using 1) Linear Search method 2) Binary Search method (Hint: Use array of structures and sort the array on city name before applying binary search) Assignment Evaluation 0: Not Done [ ] 1:Incomplete [ ] 2.Late Complete [ ] 3:Needs Improvement [ ] 4:Complete [ ] 5:Well Done [ ] Signature of the Instructor Date of Completion ! ! End of Session 14 SESSION 3: Linked List Start Date ! ! Objectives To learn about: Linked list implementation — dynamic and static. Types of linked lists - singly linked list, singly circular linked list, doubly linked list, doubly circular linked list. Reading You should read following topics before starting the exercise. static and dynamic variables limitations of Array pointers in C malloc() and free() functions in C Concept of linked list Ready References 3.1 Linked list Linked list is a collection of nodes. These nodes are nothing but dynamic variables. These dynamic variables are allocated memory from heap space. All the nodes present in the linked list are not stored in contiguous memory location hence every node of the linked list contains data(info) and pointer to the next node called as link. Info Iink Head 10 20 30 40 50 NULL Following are the operations of linked lists: getnode() — creates a node for the linked list. freenode() — releases the memory acquired by the node . insertAt(int item, int pos) — insert the new element in the linked list by inserting a new node. deleteAt(int pos) — delete a node from the linked list. append(int item) — append new node at the end of the list. 15 3.1.1. How to create a singly linked list? Following are the steps to create singly linked list. In this example, we are crating a singly sorted linked list. Step1: Declare Self-referential structure typedef struct node { int info; !*data part of node*! struct node *next; !*pointer to the next node*! } DATANODE; Step2: getnode() operation for the linked list. getnode() : This operation creates new node for the linked list. DATANODE *getnode() { DATANODE *temp = (DATANODE *) malloc(sizeof(DATANODE)); temp->next = NULL; } Step3:freenode() operation for the linked list.. freenode() : This operation is used to free the memory allocated to the node. This operation is essential if the linked list contains complex data. It may be needed to release all the resources acquired by the node. void freenode(DATANODE *ptr) { free(ptr); !*deallocated memory of DATANODE pointed by ptr.*! } Stepr4: Operation to append new node in the sorted linked list. append(): This operation will attach new node as the last node in the sorted linked list. void append(DATANODE **head, int value) { DATANODE *p=NULL, *new=NULL; !* Create new node.*! new = getnode(); new->info = value; if (*head == NULL) !* List is empty. New node will be appended as the first node in the list.*! { *head = new; return; } !*Traverse the list till the end.*! p = *head; while(p->next) p = p->next; 16 } !*Append new node.*! p->next = new; Step5: Operation to insert new node in the sorted list. insert(): This operation is used to insert new node in the existing sorted linked list. void insert(DATANODE **head,int value) { DATANODE *p=NULL, *q=NULL, *new=NULL; int i=1; !*Create new node. *! new = getnode(); new->info = value; if ( *head == NULL) !* Linked List Is Empty.*! { *head = new; !* New node becomes the first node in the linked list.*! } return; if ( (*head)->info > value) !* New node has smallest value in the list.*! { new->next = *head; *head = new; return; } !*Traverse list to reach specific position.*! p = *head; while ( p && p->info <= value) { q = p; !* q follows p*! p = p->next; !* p moves to the next node.*! } } !* Insertion between q and p.*! q->next = new; new->next = p; 17 Step6: Operation to delete node from the sorted linked list. del(): This operation removes the specified node from the list and then that node will be deallocated. void del(DATANODE **head, int value) { DATANODE *p=NULL, *q=NULL; if (*head == NULL) { printf(”Error :: Linked List Is Empty.!”); exit(1); } if ((*head)->info == value) !*First node contains value.*! { p = *head; *head = (*head)->next; !*Second node will become first in the list.*! freenode(p); !*Delete node pointed by p.*! return; } !*Traverse the list to search for specific node.*! p = *head; while(p) { q=p; !*q follows p.*! p=p->next; } if (!p) { } printf(”Data Not Found In The List.!”); return; !*Remove node pointed by p from the list.*! q->next = p->next; } freenode(p); !*Delete node pointed by p.*! 18 Step7: Operation to display all nodes of the linked list. display(): This operation will display data present in all nodes of the list. void display(DATANODE *p) { !*Traverse till the end of the list.*! while (p) { printf(”%d ”, p->info); p = p->next; } } Step8: Operation to delete all nodes of the list. destroylisr(): This operation will delete all nodes of the list. This operation is required after the use of linked list in application is over. This will release the memory acquired by the list. void destroylist(DATANODE **head) { DATANODE *p = NULL; p = *head; while (p) { *head = p->next; !*Shift head pointer to the next node.*! freenode(p); !*Delete the node previously pointed by head.*! p = *head; } } 19 Program Listing: Sorted Singly Linked List. /* Program to implement sorted singly linked list.*/ #include <stdio.h> !*for input!output operations*! #include <malloc.h> !*for accessing library functions: malloc(), free()*! #include <stdlib.h> !*for accessing library functions such as exit()*! !* Declare Self Referential Structure for creating nodes of linked list.*! typedef struct node { int info; !*data part of node*! struct node *next; !*pointer to the next node*! } DATANODE; DATANODE *getnode(); !* Creates New Data Node.*! void freenode(DATANODE *ptr); !*Deallocates the memory assigned to datanode.*! void insert(DATANODE **head,int value);!*Inserts new node at the specified position.*! void del(DATANODE **head, int value);!*Delete the node from specified position.*! void append(DATANODE **head, int value);!*Add new element as the last node in the linked list.*! void display(DATANODE *head);!*Display all elements of the linked list.*! void destroylist(DATANODE **head); !*Delete all nodes from the list.*! int main() { int num,n,i; DATANODE *list = NULL; !* Initialize linked list.*! printf(”Program to store integers in sorted order.\n”); printf(”How many Numbers?:”); scanf(”%d”,&n); !* Append first number in the list.*! i = 1; printf(”Enter Number %d:”,i); scanf(”%d”,&num); append(&list,num); !*Insert remaining numbers in the list.*! while(i < n) { i++; printf(”Enter Number %d:”, i); scanf(”%d”,&num); } insert(&list,num); 20 printf(“The linked list is as follows......\n“); display(list); } !*Delete all nodes from the linked list to free memory locations.*! destroylist(&list); return 0; DATANODE *getnode() { DATANODE *temp = (DATANODE *) malloc(sizeof(DATANODE)); !* create node of type DATANODE.*! temp->next = NULL; } void freenode(DATANODE *ptr) { free(ptr); !*deallocated memory of DATANODE pointed by ptr.*! } void insert(DATANODE **head,int value) { DATANODE *p=NULL, *q=NULL, *new=NULL; int i=1; !*Create new node. *! new = getnode(); new->info = value; if ( *head == NULL) !* Linked List Is Empty.*! { *head = new; !* New node becomes the first node in the linked list.*! return; } if ( (*head)->info > value) !* New node has smallest value in the list.*! { new->next = *head; *head = new; return; } !*Traverse list to reach specific position.*! p = *head; while ( p && p->info <= value) { q = p; !* q follows p*! p = p->next; !* p moves to the next node.*! } } !* Insertion between q and p.*! q->next = new; new->next = p; 21 void append(DATANODE **head, int value) { DATANODE *p=NULL, *new=NULL; !* Create new node.*! new = getnode(); new->info = value; if (*head == NULL) !* List is empty. New node will be appended as the first node in the list.*! { *head = new; return; } !*Traverse the list till the end.*! p = *head; while(p->next) p = p->next; } !*Append new node.*! p->next = new; void del(DATANODE **head, int value) { DATANODE *p=NULL, *q=NULL; if (*head == NULL) { printf(“Error :: Linked List Is Empty.!“); exit(1); } if ((*head)->info == value) !*First node contains value.*! { p = *head; *head = (*head)->next; !*Second node will become first in the list.*! freenode(p); !*Delete node pointed by p.*! return; } !*Traverse the list to search for specific node.*! p = *head; while(p) { q=p; !*q follows p.*! p=p->next; } if (!p) { } printf(“Data Not Found In The List.!“); return; !*Remove node pointed by p from the list.*! q->next = p->next; 22 freenode(p); !*Delete node pointed by p.*! } void display(DATANODE *p) { !*Traverse till the end of the list.*! while (p) { printf(”%d ”, p->info); p = p->next; } } void destroylist(DATANODE **head) { DATANODE *p = NULL; p = *head; while (p) { *head = p->next; !*Shift head pointer to the next node.*! freenode(p); !*Delete the node previously pointed by head.*! p = *head; } } Compile and run this program as follows to see the output: #> cc SortedSinglyLinkedList.c #> ./a.out 1. Modify this program to delete repetitive elements from the list. 2. Modify this program to add header node in the linked list. Header node should contain a count of total nodes present in the linked list. 3.2. Doubly Linked List Need for doubly linked list: In singly linked list 0 traversing is possible only in forward direction. 0 If the value to be searched in a linked list is toward the end of the list, the search time would be higher. In doubly linked list, traversing is possible in both directions and search can be continued from any node in between either in forward of backward direction. Characteristics of doubly linked list In a doubly linked list, each node has two pointers, one pointing to the next node in the list, and the other pointing to previous node in the list. Previous pointer of first node is always NULL in doubly linked list. Last node’s next pointer is always NULL in doubly linked list. 23 Prey info Prev Head NULL 10 20 30 40 NULL Operations of doubly linked list Doubly linked contains same operations as in singly linked list. If required, traversing for doubly linked could be implemented in reverse order. Self Activity Let’s create doubly linked list. Following are the steps to create doubly linked list. In this example, we are crating a doubly sorted linked list. Step1: Declare Self-referential structure typedef struct node { struct node *prev; !*pointer to the previous node.*! int info; !*data part of node*! struct node *next; !*pointer to the next node*! } DATANODE; Step2: getnode() operation for the linked list. getnode() : This operation creates new node for the linked list. DATANODE *getnode() { DATANODE *temp = (DATANODE *) malloc(sizeof(DATANODE)); temp->prev = NULL; temp->next = NULL; } Step3: freenode() operation for the linked lisr. freenode() : This operation is used to free the memory allocated to the node. This operation is essential if the linked list contains complex data. It may be needed to release all the resources acquired by the node. void freenode(DATANODE *ptr) { free(ptr); !*deallocated memory of DATANODE pointed by ptr.*! } 24 Stepr4: Implement function to append new node in the sorted doubly linked list. append(): This operation will attach new node as the last node in the sorted linked list. void append(DATANODE **head, int value) { DATANODE *p=NULL, *new=NULL; !* Create new node.*! if (*head == NULL) first node in the list.*! { } !* List is empty. New node will be appended as the !*Traverse the list till the end.*! } !*Append new node.*! Step5: Implement function to insert new node in the sorted doubly list. insert(): This operation is used to insert new node in the existing sorted list. void insert(DATANODE **head,int value) { DATANODE *p=NULL, *q=NULL, *new=NULL; int i=1; !*Create new node. *! if ( *head == NULL) !* Linked List Is Empty.*! { } if ( (*head)_>info > value) !* New node has smallest value in the list.*! { } !*Traverse list to reach specific position.*! p = *head; while ( p && p_>info <= value) { } !* Insertion between q and p.*! } 25 Step6: Implement function to delete node from the sorted doubly linked list. del(): This operation removes specified node from the list and then that node will be deallocated. void del(DATANODE **head, int value) { DATANODE *p=NULL, *q=NULL; if (*head == NULL) { } if ((*head)_>info == value) !*First node contains value.*! { } !*Traverse the list to search for specific node.*! p = *head; while(p) { } if (!p) { } !*Remove node pointed by p from the list.*! } freenode(p); !*Delete node pointed by p.*! Step7: Implement function to display all nodes of the doubly linked list in forward as well as reverse order. display(): This operation will display data present in all nodes of the list. void display(DATANODE *p) { !*Traverse till the end of the list.*! while (p) { printf(”%d ”, p_>info); p = p_>next; } !*Traverse the list in reverse till we reach to the first node in the list.*! } 26 Step8: Operation to delete all nodes of the list. destroylisr(): This operation will delete all nodes of the list. This operation is required after the use of linked list in application is over. This will release the memory acquired by the list. void destroylist(DATANODE **head) { DATANODE *p = NULL; } p = *head; while (p) { *head = p_>next; !*Shift head pointer to the next node.*! freenode(p); !*Delete the node previously pointed by head.*! p = *head; } NOTE: 1. Please note that the above programs and program skeletons are guidelines for students. You are free to implement linked list by your own method under the guidance of teacher. 2. Linked list with header node will simplify insertion and deletion operations. Please concern your teacher to know more about it. Practical Assignments SET A 1. Write a C program to implement singly linked list of integers using array. 2. Write a C program to implement circular singly linked list. What are the advantages of circular singly list over linear singly list? 3. Write a C program to implement doubly circular linked list. What are the advantages of circular double linked list over linear doubly linked list? SET B 1. Write a C program to perform union, intersection operations on two sorted linked lists. 2. Write a C program to add two polynomials using linked list. 3. Write a C program to multiply two polynomials. 27 SET C 1. Write a C program to sort the singly linked list of integers. (Create an unsorted list and then sort it. 2. Write a C program to merge two sorted linked list. 3. Write a C program to create linked list of strings. Display all strings containing same substring. (Accept substring from user.) Assignment Evaluation 0: Not Done [ ] 1:Incomplete [ ] 2.Late Complete [ ] 3:Needs Improvement [ ] 4:Complete [ ] 5:Well Done [ ] Signature of the Instructor Date of Completion ! ! End of Session 28 SESSION 4: Stack Start Date ! ! Objectives To learn about: Concept of Stack Operations on stack Implementation of stack using array Implementation of stack using linked list Applications of Stack Reading You should read following topics before starting the exercise. Linked list implementation Stack as a data structure and all its applications Ready References 4.1. Stack In stack, insertion and deletion is possible only from one end called as top of the stack. It is a LIFO(Last In First Out) data structure. Following operations are possible on stack: push(stk,x) Data item x can pushed into stack stk. The size of stack stk is increased by 1. Top of the stack stk will be pointing to the last inserted element x. This operation is always valid because stack doesn’t have any upper limit. But, if stack is implemented using array then it can grow up to the size of array. If array is full, push() operation is not possible. This condition is called as “Stack Overflow Condition”. x = pop(stk) Topmost element of stack is removed from stack stk. The size of stack is reduced by 1 after this operation. This operation is invalid if stack is empty. The pop() operation on empty stack results into “Stack Underflow” condition. x = stacktop(stk) This operation returns the copy of topmost element present in stack stk. It does not remove it. The size of stack is unchanged after this operation. This operation is invalid if stack is empty. The stacktop() operation on empty stack results into “Stack Underflow” condition. empty(stk) The empty() operation returns true if the stack is empty, otherwise it returns false. 29 Self Activity Let’s implement Stack using Array (Static Representation) Stepi. Define structure to hold Stack as a single entity. typedef struct Stack { int data[MAXSIZE_1]; int top; } STACK; Step2: Implement initlist() operation for the Stack. void initlist(STACK *stk) { !* Write a code to initialize top pointer to _1 *! } Step3: Implement push() operation. void push(STACK *stk, int item) { !* Write a code to check for “Overflow Condition.” *! } !* Write a code to add new item at the top of stack.*! Step4: Implement pop() operation. int pop( STACK *stk) { !* Write a code to check for “Overflow Condition”. *! !* Write a code to delete and return topmost element from the stack.*! } Step5: Implement stacktop() operation. int stacktop( STACK *stk) { !* Write a code to check for “Overflow Condition”. *! !* Write a code to return a copy of topmost element from the stack.*! } 30 Step6: Implement empty() operation. int empty(STACK *stk) { !* if top is _1, the list is empty. *! } Let’s Implement Stack using Linked list (Dynamic Representation) Following are some guidelines to implement stack using linked list: 1. Define a structure for stack. typedef struct { int info; struct node *next; } Stack; 2. Declare stack pointer which will be treated as top pointer. Stack *top = NULL; 3. Implement push() function void push(Stack **top, int item) { !* Write a code to insert new node (new element of stack) at first position of the linked list. In other words, top pointer will be always pointing to newly inserted node in the linked list.*! } top 10 20 30 10 20 30 10 20 push(&top, 5); top 5 push(&top, 2); 2 5 top 4. Implement pop() function. 30 int pop(Stack **top) { 31 !* Write a code to delete first node from the list.*! !*Return data from deleted node.*! } top 2 5 l0 20 30 l0 20 30 2 X = pop(&top); top 5 Deleted Node X = pop(&top); top l0 20 30 5 Deleted Node 5. Implement stacktop() function. int stacktop(Stack **top) { !*Write a code to return the value of the first node without deleting it.*! } 6. Implement empty() function. int empty(Stack **top) { } Practical Assignments SET A 1. Write a C program to reverse a string using static stack. (Create Stack.h file.) 2. Write a C program to check whether the string is palindrome or not using dynamic stack. (Use Stack.h file.) 3. Write a recursive functions to solve following problems: a. Towers of Hanoi problem with n disks. (n must be accepted from user.) b. Calculate power of x to the n. c. Fibbonacci series. 32 Does all these functions are implemented using stack? If yes, How they are using stack? SET B 1. Write a C program to convert infix expression into postfix form and evaluate it. 2. Write a C program to convert infix expression into prefix form and evaluate it. SET C 1. Write a C program to simulate recursion of following functions: a. Factorial of n numbers b. Power function 2. Write a C program to simulate recursion of Towers of Hanoi function. Assignment Evaluation 0: Not Done [ ] 1:Incomplete [ ] 2.Late Complete [ ] 3:Needs Improvement [ ] 4:Complete [ ] 5:Well Done [ ] Signature of the Instructor Date of Completion ! ! End of Session 33 SESSION 5: QUEUE Start Date ! ! Objectives To learn about: The data structure QUEUE QUEUE as an Abstract Data Type Types of QUEUE Operations on QUEUE Static QUEUE Dynamic QUEUE Applications of QUEUE Reading You should read following topics before starting the exercise: concept of queue Representation of queue using array and linked list Concept of circular queue, dequeue, priority queue. multiple queues Ready References 5.1. Queue Definition: A queue is an ordered collection of items, from which items may be deleted from one end called the front, and into which items may be inserted at the other end called the rear end of the queue. QUEUE as an Abstract Data Type : The QUEUE is a FIFO (First In First Out) structure. We use this term many a times in our day to day activities. E.g. Cinema QUEUE, bus QUEUE etc. There are 2 active pointers to QUEUE, front and rear. We follow certain rules: 1) All additions at the rear end and all deletions from the front end It means that we always add new elements towards the rear end and we always delete the elements from the front end. 2) We normally use one of the following strategies: a) Increment rear and then add at that position OR b) Add at the rear position and then increment rear. Depending upon the strategy you choose, you can initialize the front and rear. For strategy a) we initialize front = _1, rear = _1; For strategy b) we initialize front = 0, rear = 0; 34 In the static implementation of queue front and rear are integers as they are giving the location of the array where delete ! insert should take place. In the dynamic implementation of queue front and rear are pointers. Types of Queue: 1) 2) 3) 4) Linear queue Circular queue Priority queue Double Ended Queue (DEQUE) All those types can be implemented either statically or dynamically. 5.2. Implementation of linear queue using array (static representation) Static implementation is array based implantation. This requires a structure (using struct keyword) as it allows us, user defined datatype declaration (Q becomes user defined datatype). Inside the structure we declare an array to store int data, and two pointers front and rear. Front Rear 10 20 30 0 1 2 40 50 3 4 60 5 70 80 90 6 7 8 Operations on a QUEUE : Different operations possible on a queue are as follows: 1) Create: This creates a new empty queue. #define MAX 10 typedef struct QUEUE { int data[MAX]; int rear, front; } Q; Q q1, q2; !* create 2 queues. */ Q *P; P = &q1; 2) Initialize : Initialize the rear and front pointers for an empty queue. If we use increment rear and add at that position strategy, we initialize front and rear to _1, if we adopt the other strategy, we initialize both front and rear to zero. void initq( Q * P) { P _> rear = _1; P _> front = _1; } 35 3) Add or insert : Adds a new element to the queue at the rear end. The operation can only be performed if the queue is not full. If the queue is full, and we try to add an element, an overflow results. int addQ(Q*p, int x) { if (! isfull(p)) { p_>data[++(p_>rear)] = x; return 1; } return 0; } 4) Delete : Removes an element from the front end of the queue. The operation can only be performed if the queue is not empty. int delQ(Q * P) { if( !isempty(P) ) return ( P _> data[++ ( P_>front)]); else return 0; } 5) Isempty : Checks whether a queue is empty, returns TRUE if queue is empty and FALSE otherwise. int isempty(Q *P) { if (P_>front = = P_>rear) return 1; else return 0; } 6) Isfull : Checks whether a queue is full, returns TRUE if queue is full and returns FALSE otherwise. If rear reaches MAX _1, but front is not _1, so some empty positions exist at the beginning of the queue. Now this situation is tackled in 2 ways. Method 1: Let the positions be empty only. This will cause wastage of memory locations. int isfull(Q *P) { if(p_>rear == MAX _1) { printf(”Q is full ” ) ; return 1 ; } else return 0 ; } 36 Method 2: If empty positions at beginning of queue, and rear reaches MAX — 1 then perform shift queue to reuse empty locations in the array. int isfull(Q *P) { if(p_>rear == MAX _1) { if (p_>front == _1) return 1 ; else shiftq(p) ; return 0 ; } 7) ShiftQ : As there are 2 active ends, (all additions at the rear end and all deletions from the front end,) even if you add at the rear end some locations towards begining of the queue might be empty. You have to reset the front pointer when rear reaches the MAX _1 position. i.e. You have to shift the queue elements to the beginning of the queue periodically( or when rear reaches MAX — 1) to get the free spaces at the rear end. ) sothat the empty locations can be utilized. void shiftQ( Q *P) { int topos =0, frompos; for( frompos = P->front+1; frompos < MAX; frompos++) P_>data[topos++]=P_>data[frompos]; P_>front = _1; P_>rear = topos_1; } 8) Display: Print elements of the queue. 5.3 Implementation of queue using linked list (Dynamic Queue) The word dynamic refers to run time allocation of memory. So for this purpose we use malloc(), calloc() kind of functions for run time memory allocation. Here, we get the memory allocated as per requirement. Therefore, the maximum number of items in the Queue we need not mention. Items can be linked together , so the item is stored in one node of the linked list. As and how we want to store an item , we get one node allocated. The declaration will look like this: typedef struct QUEUE { int data; struct QUEUE *next; }QNODE; QNODE *front, *rear; In the initialize function we can initialize front and rear to NULL; 37 For a dynamic queue except shiftQ() ,we write all the above functions. shiftQ() is not written because we are not required to shift the queue elements. front 10 rear 20 30 40 50 5.4 Circular Queue This queue also will not require shiftQ() function. Works like a clock. The first and the last positions are coming side by side. Also if MAXSIZE is 6( positions available are 0 to 5), then the 7th item should be placed in the zeroth position. i.e. We have to increment rear to rear + 1 % MAX when rear reaches to MAX_ 1 and front to front +1 % MAX when front reaches to MAX _1.Here one position from the queue will be underutilized. typedef struct CirQ { int items[MAX]; int front, rear; }Q; Functions for Circular Queue: 1. Initialize Queue void initQ (Q* cq) { cq_> front = cq_>rear = MAX _1; } 2. IsemptyQ Prototype: int isemptyQ(Q *cq) Queue will be empty if rear = front 3. IsfullQ int isfullQ(Q* cq) { return ((cq_>rear+1)% MAX == cq_>front) 4. AddQ Prototype: int addQ(Q *cq, int item) If Q is not full, then increment rear to (rear +1) % MAX and then add at that position. 5. DelQ Prototype: int delQ(Q *cq) While deleting increment front to (front + 1) % MAX and then delete. Return the deleted element 5.5 Priority Queue Definition: A priority Queue is a data structure in which the intrinsic ordering among the elements decides the result of its basic operations. 38 Types of priority Queue : 1. Ascending Priority Queue : Elements can be inserted arbitrarily but only the smallest element gets deleted first 2. Descending Priority Queue: Only the largest element gets deleted first. 5.6 Dequeue This is Double Ended Queue. A DEQUE is a linear list in which elements can be added or removed at either end. Elements can be added or removed from front or the rear end. A DEQUE is generalization of a stack and a queue. Types of DEQUE: 1. Input restricted DEQUE : allows insertin at only one end of the list but allows deletion from both the ends. 2. Output restricted DEQUE : allows deletion at only one end of the list, but allows insertion at both ends of the list. Operations possible are: Enquefront() : To add at front end of the queue. Enquerear() : To add at rear end of the queue. Dequeuefront() : To delete item at the fron end of the queue. Dequeuerear() : To delete an item at rear end of queue. Practical Assignments SET A 1. Write a C program to implement linear queue of strings using array. Store the structure and queue functions in “queue.h” and write the main function in a .C file. The program should be menu driven with the options : ADD, DELETE, EXIT. typedef struct { !! members }queue; void initq(queue *pq) { } int isempty(queue *pq) { } int isfull(queue *pq) { } void addq(queue *pq, char *str) { } char *delq(queue *pq) { } void main() { queue q; //menu driven program } 2. Write a C program to implement a circular queue using array. (Refer to the code above) 39 3. Write a C program to implement a queue of integers using linked list. The program should be menu driven with the following options: ADD, DELETE, EXIT. typedef struct node { !! members INODE; NODE *front, *rear; !!global variable void initqueue() { I void addq(int n) { I int delq() { I int isempty() { I void main() { !!menu driven program I SET B 1. Write a C program to implement static ascending priority queue. 2. Write a C program to sort n integers using bucket sort method. SET C 1. Write a C program to implement static DEQUE. 2. Write a C program to implement Multiple Queues using single array. 3. Write a C program to implement Josephus problem. Assignment Evaluation 0: Not Done [ ] 1:Incomplete [ ] 2.Late Complete [ ] 3:Needs Improvement [ ] 4:Complete [ ] 5:Well Done [ ] Signature of the Instructor Date of Completion ! ! End of Session 40 SESSION 6: Tree Start Date ! ! Objectives To learn about: The data structure Tree Tree as an Abstract Data Type Types of Tree Operations on Tree Applications of Tree Reading You should read following topics before starting the exercise. Concept & Terminologies of Binary tree and binary search tree Operations on BST — create. Insert, delete, traversals (preorder, inorder, postorder), counting leaf, non_leaf & total nodes Application _ Heap sort, Height balance tree_ AVL trees_ Rotations Ready References Tree can be treated as a special case of generalized link list. 6.1 Binary Tree A binary tree is a special form of a tree. A binary tree is finite set of nodes, which is empty or partitioned into 3 sets, one which is the root and the other 2 are binary trees called its left and right subtrees. It is a tree where every node can have at the most two branches or children. Some frequently used types of binary trees are as follows: 1. Binary Search Tree (BST) 2. Expression Tree 3. Heap Tree 4. Threaded Binary Tree 5. Huffman Tree 6. Height Balanced Tree (AVL tree) 6.2 Binary Search Tree (BST) Definition: A binary search tree is a binary tree, which is either empty or in which each node contains a key that satisfies following conditions: 1) For every node X, in the tree the values of all the keys in its left subtree are smaller than the key value in X. 2) For every node X, in the tree the values of all the keys in its right subtree are larger than the key value in X. 41 Structure of a node of a BST: typedef struct BST { int data; struct BST * left, * right; IBSTnode; Operations on a binary Search Tree: 1. Create: creating a binary search tree(BST).A BST can be created by making repeated calls to insert operation. BSTnode * create() { int i, totnodes, val; BSTnode * root =NULL; printf(” How many nodes to create?”); scanf(”%d”, &totnodes); printf(”Enter node values : ”); for ( i=O;i<totnodes;i++) { scanf(”%d”,&val); root = insert(root, val); I return ( root); I 2. Insert: Inserting one node in the BST. BSTnode * insert(BSTnode * T, int x) { if ( T = = NULL) { T = (BSTnode*) malloc (sizeof(BSTnode)); T_> data = x; T_>left = NULL; T_>right = NULL; return (T); I if(x > T_>data) { T_> right = insert(T_>right, x); return (T); I T_>left = insert(T_>left, x); return (T); I 3. Delete: a) b) c) Deleting one node of the BST. There are 3 cases: deleting a leaf node deleting a node with one child deleting a node with 2 children 4. Traversal: To visit all nodes and print the data of the BST. There are 3 types of traversals: inorder, preorder, postorder. 42 5. Findmin: Finds the minimum value in the BST. This value is situated in the leftmost node of the BST. BSTnode * findmin(BSTnode *T) { while (T_>left != NULL) T = T_>left; return(T); I 6. Findmax : Finds the maximum value of the BST. This value is situated at the rightmost position of BST. Prototype : BSTnode * findmax(BSTnode *T) 7. Find: finds the value X in the BST Prototype : BSTnode * find(BSTnode, int x) 6.3. Heap Tree Types of heaps: a) MaxHeap : A max heap is a complete binary tree with the property that the value of each node is at least as large as the values at its children. In the max heap the largest element is at the root. b) MinHeap : A min heap is a complete binary tree with the property that the value at each node is at least as small as the values at its children. Here, the smallest element is at the root. Sorting in ascending order: The best known application of heap is in sorting. It uses a very simple strategy for sorting. A heap can be sorted through repeated application of delete max( ) in the Maxheap. An array can be used for heap sort. Accept all values in an array where at zeroth position total number of values are stored. Algorithm : Step 1: Construct a max_heap. heap[O] has total values n and heap[1] is largest element. Step 2: Swap heap[1] and heap[n]. This will put largest at heap[n]. Step 3: Reduce the heap size by 1. i.e. heap[O] = heap[O] — 1; Largest element is in the array but it is not a part of the heap. Step 4: The new tree represented by heap[1..n_1] may no longer be a heap, as heap[1] is changed. The new tree can be converted to a heap by using a function downadjust(). Step 5 : Repeat steps 2 to 4, while number of elements in the heap > 1 ( i.e. heap[O] > 1) 43 Function to create the max_heap: void create(int heap[]) { int i,n; n = heap[O]; for ( i=n!2; i>=1; i ) down_adjust(heap,i); I Function to readjust the heap void down_adjust(int heap[], int i) { int j, temp, n,flag = 1; n= heap[O]; while (2*i <= n && flag = = 1) { j = 2 *i; !* j points to left child *! if ( j + 1 <=n && heap[j+1] > heap[j]) j=j+1; if (heap[i] > heap[j]) flag = O; else { temp = heap[i]; heap[i] = heap[j]; 44 heap[j] = temp; i = j; I!* end if *! I!* end while *! I!* end down adjust *! Function to sort the array elements: Sort(int heap[]) { int last, temp; while (heap[0] > 1) { !* swap heap[1] with heap[last] *! last = heap[0]; temp = heap[1]; heap[1] = heap[last]; heap[last] = temp; heap[o] ; down_adjust(heap,1); I I Practical Assignments SET A 1. a) Write a menu driven program for Binary Search Tree creation and inorder, preorder, postorder recursive traversal of all nodes. b) Modify the above program for performing following operations : a. Search a value. b. Insertion of a value 2. Write a program to perform Heap_sort using arrays. SET B 1. Write a program to create Binary Search tree with the following functions: a) tcopy _ function to make an identical copy of a tree T, returns root of newly created tree b) tmirror — checks whether a tree t1 is a mirror image of tree t2, returns 1 if true else returns 0 c) tleafcnt _ counting leaf nodes of a tree T 2. Write a program to create and evaluate expression tree. 3. Modify program in set A (Exercise 1) to perform deletion of a node in the BST 45 SET C 1. Write a program to perform Non_recursive traversal using stack(inorder, preorder, postorder) on the BST 2. Write a program to create height balanced tree. Write appropriate functions for different cases_ LL, RR, LR, RL to rotate the tree and maintain the balance. 3. Write a program to create Huffman tree for compression. Assignment Evaluation 0: Not Done [ ] 1:Incomplete [ ] 2.Late Complete [ ] 3:Needs Improvement [ ] 4:Complete [ ] 5:Well Done [ ] Signature of the Instructor Date of Completion ! ! End of Session 46 SESSION 7: Graph Start Date ! ! Objectives To learn about: Implementation of adjacency matrix and adjacency list Implementation of adjacency mult_ilist Graph traversal — BFS and DFS Shortest path algorithm — Dijkstra’s Algorithm Reading You should read the following topics before starting the exercise. 1. Graph Terminologies _ vertex, edge, graph, path, complete graph, 2. Graph representation techniques — Adjacency matrix, Adjacency list 3. Examples on Adjacency matrix, Adjacency list Ready References 7.1 Representation of Graph If we want to represent cities and highways connecting them, we can represent this information in the form a graph. Or components on circuit board with the connections among them. An organic chemical compound can be considered as a graph with atoms as the vertices and the bonds between them as edges. For such need most suitable data structure is ‘graph’. In computer systems graph can be stored using adjacency matrix, adjacency list or adjacency multilist. Adjacency Matrix A adjacency matrix A has a natural interpretation as A[v,w] = 1 iff vertex v is adjacent to vertex w, otherwise A[v,w] = O(if not adjacent) Example: V1 0 1 0 0 0 1 1 0 0 0 0 1 1 1 0 Graph G V4 0 V2 Adjacency Matrix V3 Adjacency List: Another way to represent a graph is adjacency list. This is linked list representation of graph; there is one list for each vertex in the graph. Thus for ‘n’ vertices, n list will be prepared. Each node of the list I consists of 1. Vertex numbers to which vertex I is adjacent 2. Pointer to the next node in the list 47 Example: For above graph G adjacency list: Vi V2 V2 V3 NULL V4 NULL NULL V3 Vi V4 V2 V3 NULL 7.2 Graph Traversal Methods In many problems we wish to investigate all the vertices in a graph in some systematic order, just as with binary trees we developed several systematic traversals methods. In tree traversal, we had w root as a starting vertex; in graph we often do not have any one vertex as a special, and therefore the traversal may start at an arbitrary vertex. This lecture focus on graph traversal techniques _ DFS, BFS. 1. Depth First Traversal/Search: Depth first traversal of a graph is roughly analogous to preorder traversal of an ordered tree. Suppose that the traversal has just visited a vertex v, and let w1,w2…….wk be the vertices adjacent to v. Then we shall visit w1 and keep w2……wk waiting. After visiting w1 we traverse all the vertices to which it is adjacent before returning to traverse w2…..…wk. 1. 2. 3. 4. 5. 6. 7. 8. 9. Algorithm Initialize visited array to 0 v is the starting vertex visited [v] = 1 display v Search for w which is an unvisited vertex adjacent to v if w is found Visited [w] =1 Display w Push w into stack Go to 5 v=pop Continue from 5 till stack becomes empty Stop. 2. Breadth First Traversal/Search: Breadth first traversal of a graph is roughly analogous to level_by_level traversal of an ordered tree. If the traversal has just visited a vertex v, then it next visits all the vertices adjacent to v, putting the vertices adjacent to these in a waiting list to be traversed after all the vertices adjacent to v have been visited. 48 1. 2. 3. 4. 5. 6. 7. 8. Algorithm Initialize visited array to 0 v is the starting vertex Queue is initialized visited [r] =1 add v to queue Remove v from queue and display to v for all vertices w adjacent to v if visited [w]=1 add w to queue visited [w] =1 Continue from 6 till queue becomes empty 7.3 Applications of Graph Topological Sort Graphs are commonly used for project planning which consists of many interdependent activities. These activities are represented as vertices and the directed edges represent the order of activities. Such graph is called an Activity On Vertex (AOV). The process of converting a set of precedence represented by an AOV network into a linear list in which no later activity precedes an earlier one is called topological sorting. 1. 2. 3. 4. 5. 6. 7. 8. 9. Algorithm Accept AOV network in adjacency list form S is an empty stack Search for vertex v whose in_degree is 0 if v is not found if stack is empty go to 9 else go to 5 if not found if stack is empty go to 8 else go to 5 if found make in_degree of v = _1 push v into stack pop v from the stack and display Reduce the in_degree of all vertices adjacent to v by 1 Repeat from step 3 till all vertices have been visited Stop. Shortest Path Algorithm Graphs are often used to represent the road network of a state or country with the vertices representing cities and the edges representing the connecting roads. Each edge may be assigned a weight which may be the 49 distance between the two vertices or the time taken to go from one vertex to another. An algorithm devised by Dijkstra is a ‘single source all destinations’ algorithm which gives the shortest path from a given vertex to all other vertices in the network. Algorithm 1. V is the starting vertex 2. Initialize visited array to 0 3. Initialize all the elements of distance array as Dist [i] = cost [v] [i] 4. visited [v] =1 5. num=1 6. while (num <n) { u=choose (dist, n); num=num+1 !* choose is the function which returns u such that Dist [u] = min{ dist[w]I where visited [w] is false *! For w= 1 to n_1 { If (!visited[w] ) If (dist[u]+cost[u][w]<dist[w]) Dist[w]=dist[u]+cost[u][w] I I 7. dist array contains the shortest paths from V to all other destinations 8. Stop Practical Assignments SET A 1. Write a program to read a graph as adjacency matrix. Calculate indegree,outdegree and total degree of each vertex. Also write functions to implement BFS and DFS. (Use recursive DFS function.) 2. Write a program to read a graph as adjacency matrix and convert it into adjacency list. Write BFS and non_recursive DFS functions. 50 SET B 1. Write a program to represent following graph as an adjacency multi_ list form. B D A C 2. Write a program to represent following graph as an Orthogonal list. B D A C 3. Implement a graph using an array of adjacency lists. Under this representation, a graph of n nodes consists of n header nodes, each containing an integer from 0 to n_1 and a pointer. The pointer is to a list of list nodes each of which contains the node number of a node adjacent to the node represented by the header node. Implement Dijkstra’s algorithm using this graph representation. SET C 1. Write a program to implement Prim’s algorithm using an adjacency matrix. 2. Write a program to implement Kruskal’s algorithm using an adjacency matrix I adjacency list. 3. There may be more than one way to organize set of subtasks in a minimum number of time periods. For example, the subtask in following figure may be completed in six time periods in one of three different methods: 51 Period 1 2 3 4 5 6 Method 1 A, F B, H I C D E A Method 2 F A, H B, I C D E D Method 3 A, F H B, J C D E F G B E C Write a program to generate all possible methods of organizing the subtasks in the minimum number of time periods. Assignment Evaluation 0: Not Done [ ] 1:Incomplete [ ] 2.Late Complete [ ] 3:Needs Improvement [ ] 4:Complete [ ] 5:Well Done [ ] Signature of the Instructor Date of Completion ! ! End of Session 5i