Open navigation menu
Close suggestions
Search
Search
en
Change Language
Upload
Sign in
Sign in
Download free for days
0 ratings
0% found this document useful (0 votes)
143 views
205 pages
DSA BCA Final PRO
Uploaded by
Avash Shrestha
AI-enhanced title
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content,
claim it here
.
Available Formats
Download as PDF or read online on Scribd
Download
Save
Save DSA_BCA_Final_PRO For Later
0%
0% found this document useful, undefined
0%
, undefined
Embed
Share
Print
Report
0 ratings
0% found this document useful (0 votes)
143 views
205 pages
DSA BCA Final PRO
Uploaded by
Avash Shrestha
AI-enhanced title
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content,
claim it here
.
Available Formats
Download as PDF or read online on Scribd
Carousel Previous
Carousel Next
Download
Save
Save DSA_BCA_Final_PRO For Later
0%
0% found this document useful, undefined
0%
, undefined
Embed
Share
Print
Report
Download now
Download
You are on page 1
/ 205
Search
Fullscreen
DATA STRUCTURES AND ALGORITHMS For Bachelor of Computer Application ABSTRACT This book provides a comprehensive introduction to data structures and algorithms, covering both the theoretical foundations and practical implementation of these fundamental tools. Beginning with an overview of basic data structures suchas arrays, linked lists, and trees, the book goes on to explore advanced topics such as sorting and searching algorithms, graph algorithms, and dynamic programming. Throughout the book, the authors provide clear explanations and examples, as well as numerous exercises and programming assignments to help readers solidify their understanding. With its clear and accessible presentation, this book is an essential resource for students and professionals in computer science and related fields. Narayan Sapkota MSc.DISCLAIMER The information contained in this book is for educational and informational purposes only. It is not intended to be used as a substitute for professional advice. The author and publisher make no representations or warranties of any kind, express or implied, about the completeness, accuracy, reliability, suitability or availability with respect to the information, products, services, or related graphics contained in this book for any purpose. The reader should always exercise their own due diligence and seek the advice of a qualified professional before using any information jues described in this book. The author and publisher shall not be liable for any errors ns, or for any actions taken in reliance on the information contained in this book. The Use of any information or techniques described in this book is solely at the reader's own riskPREFACE As the author of this book, | am excited to present a comprehensive guide to the field of data structures and algorithms. This book is designed to provide a thorough understanding of the fundamental concepts and techniques used in the field, as well as to give readers the practical skills necessary to apply these concepts in real-world situations. The book covers a wide range of topics including basic data structures such as arrays, linked lists, and trees, as well as advanced algorithms for sorting, searching, and graph traversal. Each chapter provides a clear and detailed explanation of the concepts, along with examples and exercises to help readers solidify their understanding, have written this book with the intention of making data structures and algorithms accessible to a wide range of readers, from students and beginners to professionals and experts. | believe that a strong understanding of these concepts is essential for anyone working in computer science or a related field, and | hope that this book will serve as a valuable resource for anyone looking to improve their skills in this area. | would like to express my gratitude to all those who have supported me in the creation of this book. From my colleagues and mentors, to the reviewers and editors who have provided invaluable feedback, | am deeply grateful for their contributions. hope that readers will find this book to be informative, engaging, and useful. | look forward to hearing your feedback and thoughts as you work through the material. Narayan SapkotaTable of Contents Unit 1 Introduction to Data Structure. 11 What is Data Structure? 1.1.1 Operations on Data Structure... 1.1.2 Advantages of Data Structure. 2 1.2. Classification of Data Structures. 2 13 Abstract Data Type... 4 1.4 Importance of Data Structures vod Unit 2 The Stack. 6 2.1 Whatis Stack?.... 6 24.1 Stack as an ADT... 6 22 Stack Operations 7 23. Applications of Stack..... von8 2.4 Evaluation of Infix, Postfix, and Prefix Expressions... 9 25 Infix to Post Fix Expression. 10 25.1 _Infix to Prefix Expression nu 25.2. Evaluation of Postfix Expression. 12 Unit 3 Queue... 3.1 What is Queue?.. 3.1.1 Queue as an ADT... 3.2 Operations on Queue... 15 3.3 Circular Queue... 17 3.3.1 Representation of Circular Queue. 18 BA DeqUe rani 20 35 Operations on Deaue... sw 21 36 Priority Queve.... se 23 3.6.1 Implementation of Priority Queue using Array. 24 Unit 4 List nu 4.1 Whatis List?..... 41.1 Why we need list data structure? 26 41.2 Whatisa difference between Array and List? 2742 Static and Dynamic List Structure 43° Array Implementation of Lists. 44 Queue as alist. Unit 5 Linked List. 5.1 Whats Linked List SA.1 Linked List VS Array usm 5.1.2 Linked List vs Dynamic Array. 5.2. Linked List as an ADT 5.3 Types of Linked List... 54 Singly Linked List sss 5.4.1 Insertion in Singly Linked List 54.2 Deletion in Singly Linked List 543 Searching in a Singly Linked List... 544 Displaying a Single Linked List 55 Linked Stacks. 56 Linked Queues... 5.7 Doubly Linked Lists. 5.7.1 Insertion in Doubly Linked List 5.7.2 Deletion in Doubly Linked List. 5.7.3. Searching in a Doubly Linked List 5.74 Displaying a Double Linked List.... Unit 6 Recursion 6.1 Whats recursion? 6.1.1 How does recursion work?, 62 Anatomy of a Recursive Call ne 63 Types of Recursion 63.1 Tail Recursion 63.2 Non-Tail Recursion... 63.3 Direct Recursion. 63.4 Indirect Recursion. 63.5 Nested Recursion... ar 29 30 31 sn 32, 32 on 84 37 a1 eA 42 vA AB 45 49 49 50 50 51 52 oe 5B 53 we 4 oe 5S 5663.6 Excessive Recursion ST 64 — Recursion vs Iteration. se 5B 65 Application of Recursion... 59 66 Tower of Hanoi (TOH) 59 66.1 Tower of Hanoi using RECUrSION 60 67 Backtracking. 62 67.1 How Does a Backtracking Algorithm Work? wenn 62 6.7.2 An Example of Backtracking Algorithm, 68 68 Search Tree..... Unit 7 Trees 71 Whatis Tree? 7.1.1 Why we need tree? 71.2 Tree Terminologies... 7.2 Binary Tree. 72.1 Basic Operations in Binary Tree. 72 73 Binary Tree Traversals. 731 In-order Traversal nuns 73.2 Pre-order Traversalvnrnrnnnnnnnnn 733 Post-order Traversal 7.34 Breadth-First traversal (BFS) 735 Depth-First Traversal (DFS). 74 Binary Tree Insertion. 75 Binary Tree Deletion 16 7.6 _ Binary Search Tree (BST)... 7 7.6.1 Operations on Binary Search Tree (BST) sn 7B 7.6.2 Creating a BST. 78 7.63 Insertion in Binary Search tree. 80 7.64 Searching in Binary Search Tree. 81 7.65 Deletion in Binary Search Tree... sn 82 7.66 — The Complexity of BST. 84 7.7 Balanced Trees...7.8 Balanced Binary Tree. as 79 AVL Balanced Trees. se 85 79.1 Operations on AVL Tree... on 86 7.9.2 AVL Tree Rotations. 87 7.10 The Huffman Algorithm... 92 7.10.1 Why do we use Huffman coding algorithm?.. 92 7.10.2 Example of Huffman Coding Algorithm...... 93 7.103 How efficient is Huffman coding? 96 7.11 Game Tree... 712 B-Tree. 7.12.1 Operations on B-Tree. Unit 8 Sorting 8.1 Whatis Sorting?.... 82 Types of Sorting Techniques... 83 Bubble Sort. 83.1 Working of Bubble Sort. 83.2 Complexity of Bubble Sort... 84 Exchange Sort 85 _ Insertion Sort. 85.1 Working of Insertion Sort. 85.2 Complexity of Insertion Sort... 86 Selection Sort 8.6.1 Working of Selection Sort Algorithm, 86.2 Complexity of Selection Sort. 2 87 Shell Sort. 87.1 Working of Shell Sort Algorithm 113, 115 87.2 Complexity of Shell Sort. 88 — Radix Sort...... 88.1 Working of Radix Sort Algorithm nnn 11S 88.2 Complexity of Radix Sort 89 Quick Sort..... rn89.1 Working of Quick Sort Algorithm, 119 89.2 Quicksort Complexity...... 122 8.10 Merge Sort 123 8.10.1 Working of Merge Sort... 125 8.10.2 Complexity of Merge SOft unum on 12S 8.11 Heap Sort as Priority Queue... 126 8.11.1 Working of Heap Sort Algorithm... 8.112 Heap Sort Complexity. 131 Unit 9 Searching nnn 132 9.1 Whatiis searching?.... 132 9.4.1 Essential of Search... 132 9.2 Sequential Search 132 92.1 Working of Sequential Search nnn so TB 92.2 Complexity of Sequential Search... 134 93 Binary Search 135, 93.1 Working of Binary Search. 135 93.2 Binary Search Compledity em 137 94 Tree Search.. 138 95 General Search Tree 138 96 Hashing..... 9.6.1 Hash Function Calculation. soe 139 962 Coll 140 9.7 Open Hashing. son 140, 98 Closed Hashing... son M3 98.1 Linear Probing. oo 4B 982 — Quadratic Probing 144 98.3 Double Hashing. Unit 10 Graphs...... 10.1. Whatis graph... 10.1.1 Types of Graph... 10.2. Graph Terminology... 150 son 15510.3. Graphs as an ADT. 156 104 Graph Representation. 156 104.1 Sequential Representation. 187 10.4.2 Linked list Representation sou 159 10.5. Transitive Closure nn 160 10.6 Warshall's Algorithm 161 10.6.1 Example of Transitive closure. 162 10.6.2 _ Example of Warshall’s algorithm to the directed graph 163 10.7 Graph Traversal... 165 10.7.1 DFS (Depth First Search) 166 10.7.2 BFS (Breadth First Search) 171 10.8 Spanning Trees. 175 10.8.1. Minimum Spanning Trees... son 76 10.9. Prim’s Algorithm 17 10.10. Kruskal's Algorithm, 179 10.11 Round-Robin Algorithms. 180 10.12 Dijkstra’s Algorithm. 180 10.13 Greedy Algorithm 183 Unit 11 Algorithms 186 TL Deterministic and Non-deterministic Algorithm 186 11.1.1 Deterministic Algorithm... so 186 11.1.2 Nondeterministic algorithm 186 11.2. Divide and Conquer Algorithm 187 11.2.1 Applications of Divide and Conquer Approach 188 11.2.2 Advantages of Divide and Conquer... 11.23 _ Disadvantages of Divide and Conquer. 189 11.3 Series and Parallel Algorithm 189 11.4 Heuristic and Approximate Algorithms. 191 11.4.1 Heuristic Algorithms... sont 11.42 Approximate Algorithm 192Data Structures and Algorithms | Narayan Sapkota M.Sc. Unit 1 Introduction to Data Structure 1.1 What is Data Structure? In computer science, a data structure is a specific way to store and organize data in a computer's memory so that these data can be used efficiently later. Data may be arranged in many ways such as the logical or mathematical model for a particular organization of data is termed as a data structure. The variety of a particular data model depends on the two factors; firstly, it must be loaded enough in structure to reflect the actual relationships of the data with the real-world object and secondly, the formation should be simple enough so that anyone can efficiently process the data each time it is necessary. Data structure involves two complementary goals- ‘+ The first goal is to identify and develop useful mathematical entities and operations to determine what class of problems can be solved by using these entities and operations. ‘© The second goal is to determine representation for those abstract entities to implement abstract operations on this concrete representation. A well-designed data structure allows a variety of critical operations to be performed, using as few resources, both execution time and memory space, as possible. A data structure should be seen as a logical concept that must address two fundamental concerns; how the data will be stored, and what operations will be performed on it. For example, we can store a list of items having the same datatype using the array data structure as shown in figure. soy senene — ve —> vnrbond tmp 1.1.1, Operations on Data Structure Following operations can be performed on the data structures: 1. Traversing It is used to access each data item exactly once so that it can be processed. 2. Searching It is used to find out the location of the data item if it exists in the given collection of data items. 3. Inserting It is used to add a new data item in the given collection of data items. Narayan Sapkota M.Sc. fa]Data Structures and Algorithms | Narayan Sapkota M.Sc. 4. Deleting It is used to delete an existing data item from the given collection of data items. 5. Sorting Itis used to arrange the data items in some order ie, in ascending or descending order in case of numerical data and in dictionary order in case of alphanumeric data 6. Merging It is used to combine the data items of two sorted files into single file in the sorted form. 1.1.2 Advantages of Data Structure 1. Abstraction Data structures are often implemented as abstract data types. The users only access its outer interface without worrying about the underlying implementation. Thus, data structure provides a layer of abstraction. 2. Efficiency Proper organization of data results in efficient access of data thereby making programs more efficient. Secondly, we can select the proper data structure depending on our requirements. 3. Reusability We can reuse the data structures that we have designed. They can be compiled into a library as well and distributed to the client. 2 Cla n of Data Structures Data Structures Narayan Sapkota MScData Structures and Algorithms | Narayan Sapkota M.Sc. Primitive data types are classified as basic data and consists of Boolean, characters, integers, and floating-point numbers. These data types are the building blocks of data structures. The other data structures are nonprimitive and the user must define them before using them in a program. The non-primitive data structures can further divide into two categories: linear and non-liner. Linear data Structures have all their elements arranged in a linear or sequential fashion. Each element in a linear data structure has a predecessor (previous element) and a successor (next element). Linear data structures are further divided into static and dynamic data structures. Static data structures usually have a fixed size and once their size is declared at compile time it cannot be changed whereas dynamic data structures can change their size dynamically and accommodate themselves. The most popular example of linear static data structure is an array.in non-linear data structures, data is not arranged sequentially, instead, itis arranged in a non-linear fashion. Elements are connected to each other in a non-linear arrangement. Example An array is a sequential collection of elements of the same type. Each element of the array can be accessed using its position in the array called an index or subscript of the array. The name of the array points to the first element in the array. The above shown Figure is an array ‘a’ of n elements. The elements are numbered from 0 to n-1. The size of the array EI al2] Bey (n in this case) is also called the dimension of the array. As shown in the above figure, the name a tn) of the array points to the first element of the array. The array is the simplest data structure and is efficient as elements can be accessed using subscripts directly. For example, to access the third element of array we use a [2]. Difference between Linear and Nonlinear Data Structures Main difference between linear and nonlinear data structures lies in the way they organize data elements. In linear data structures, data elements are organized sequentially and therefore they are easy to implement in the computer's memory. In nonlinear data structures, a data element can be attached to several other data elements to represent specific relationships that exist among them, Due to this nonlinear structure, they might be difficult to be implemented in computer's linear memory compared to implementing linear data structures. Selecting one data structure type over the other should be done carefully by considering the relationship among the data elements that needs to be stored, Narayan Sapkota MSc 3 |Data Structures and Algorithms | Narayan Sapkota M.Sc. 1.3 Abstract Data Type Abstract Data type (ADT) is a type (or class) for objects whose behavior is defined by a set of values and a set of operations. The definition of ADT only mentions what operations are to be performed but not how these operations will be implemented. It does not specify how data will be organized in memory and what algorithms will be used for implementing the operations. It is called “abstract” because it gives an implementation-independent view. The abstract data type (ADT) is a data type that focuses on what it does by ignoring how it does. The best example of this abstract data type is stack and queue. Stack having its push and pop operations, but itis implemented using the array or linked list. There is also a complex logic behind the push and pop operations of the stack, but we never focus on that. Furthermore, for example, integers are an ADT, defined as the values ... -2, -1, 0, 1, 2, .. and by the operations of addition, subtraction, multiplication, and division, together with greater than, less than, etc,, which behave according to familiar mathematics, independently of how the integers are represented by the computer, Similarly, boolean is also an ADT since the carrier set of the boolean ADT is the set true, false. The operations on these values are negation, conjunction, disjunction, conditional, is equal to, and pethaps some others. ‘An ADT consists of two parts: declaration of data and declaration of operations. ADT is a logical description of how we view the data and the operations that are allowed without regard to how they will be implemented. This means that we are concerned only with what data is representing and not with how it will eventually be constructed. By providing this level of abstraction, we are creating an encapsulation around the data. The idea is that by encapsulating the details of the implementation, we are hiding them from the user's view. This is called information hiding. 1.4. Importance of Data Structures Data Structures are a crucial part of several computer algorithms as they allow programmers to do data management efficiently. A wise selection of data structures can improve the performance of a computer program or algorithm in a more useful way. Data structure provides basic stuff to resolve problems. Its importance can be understood by the following: 1. Handling complexity Increase in complexities in computer algorithms, the volume of data usage is rising; this can affect the execution of the application and can create remarkable areas of concer like processing speed, data search, and multiple requests. To counter these data structures are used. 2. Systematic memory use Narayan Sapkota M.Sc. oHData Structures and Algorithms | Narayan Sapkota M.Sc. Systematic application of data structure memory usage can be optimized, e.g, we can use linked list vs. arrays when we are not particular about the data size. When there is no longer use of memory, it can be cleared. 3. Ability to reuse Once we have executed a particular data structure, we can reuse it in any distinct position. Implementation of data structures can be assembled into libraries that can be utilized by various clients. 4. Abstraction Data structure acts as the foundation of abstract data types; the data structure describes the physical form of Abstract Data Type. In ADT, the set of operations is supposed to be understood, and the data structure provides physicality to them. Narayan Sapkota MSc | |Data Structures and Algorithms | Narayan Sapkota M.Sc. Unit 2 The Stack 2.1. What is Stack? Stack is a linear data structure in which the insertion and deletion operations are performed at only one end. In a stack, adding and removing of elements are performed at single position which is known as top. That means, new element is added at top of the stack and an element is removed from the top of the stack. In stack, the insertion and deletion operations are performed based on LIFO (Last in First Out) principle. Real life examples of stacks are shown in figure below. “Ss ‘ei = stack of Coins Canof Tennis Balls ——_Stackof Books In a stack, the insertion operation is performed using a function called push and deletion operation is performed using a function called pop. In the figure below, PUSH and POP operations are performed at top position in the stack. That means, both the insertion and deletion operations are performed at one end ie, at top. While performing push and pop operations we must check whether stack is empty or not and stack is full or not. oS <— ss 2.1.1 Stack as an ADT A stack S of elements of type Tis a finite sequence of elements of T together with the operations. 1. MakeEmpty(S) To create an empty stack. 2. push (S, x) Insert x at one end of the stack, called its top. 3. stackTop(S) If stack S is not empty; then retrieve the element at its top. 4. pop(S) If stack $ is not empty; then delete the element at its top. Narayan Sapkota MSc oData Structures and Algorithms | Narayan Sapkota M.Sc. 5. IsFull(S) Determine if $ is full or not, Return true if S is full stack; return false otherwise. 6. IsEmpty(S) Determine if S is empty or not. Return true if S is an empty stack; return false otherwise. 7. traverse () It displays the elements of the stack. 2.2. Stack Opera The two basic operations associated with stacks are Push and Pop. All insertions and deletions take place at the same end, so the last element added to the stack will be the first element removed from the stack. When a stack is created, the stack base remains fixed while the stack top changes as elements are added and removed. The most accessible element is the top and the least accessible element is the bottom of the stack. 1. IsEmpty( and IsFull() |sEmpty( is used to check whether the stack is empty or not. If top == -1, then stack is empty and otherwise stck is non-empty. Similarly, isFulld is used to check whether the stack is full or not. If the top > size-1, then stack is full otherwise stack is not full. sEmpty() and IsFull() are opposite to each other in nature 2. Push operation Push operation is used to add new elements into the stack. At the time of insertion, first check the stack is full or not. If the stack is full, it generates an error message “stack overflow’, The push () operation goes through the following steps: 1. Check whether the stack is full or not. 2. Ifthe stack is already full and we try to insert more elements into it it will return an overflow error. 3. Ifthe stack is not full, increment the ‘top’ to point to the next empty space and insert the new element there. 4, When the stack is empty ie. top == -T. Once we add a new element, the top points to that element and has a value of 0. 5. The stack can accommodate elements if it does not reach its maximum capacity, Narayan Sapkota M.Sc. 7AData Structures and Algorithms | Narayan Sapkota M.Sc. Push Operation ane Push(B) _Push(c) Push(0) Top. Top. __| top. Top. Empty Stack ——_(Top=0) (op (op?) Stack Full (Top=-1) Top= 3) 3. Pop operation Pop operation is used to delete elements from the stack. At the time of deletion first check the stack is empty or not. If the stack is empty, it generates an error message “stack underflow’ The steps involved in the pop operation are: 1. The first step is to check whether the stack is empty or not 2. Ifthe stack is already empty, we cannot remove any element from it. So, we will return an underflow error. 3. Ifthe stack is not empty, remove the topmost element of the stack 4, Decrement the position of ‘top’ by 1 Pop operation Pop) Pop() Pop() Pop() too — soa N aN mn on Top Te. Te: om) vera vert om=0) Tom) Sack sey 4, Traverse Operation This operation performed display the elements in the stack. We display the element in the stack check the condition is stack is empty or not ie, top==-1. Otherwise display the list of elements in the stack 2.3 Applications of Stack 1. Evaluation of Arithmetic Expres: ns There are 3 types of expression we use in programming, which are infix expression, prefix expression and postfix expression. Infix expression is represented as x + y. Prefix expression is Narayan Sapkota M.Sc. oiData Structures and Algorithms | Narayan Sapkota M.Sc. represented as +xy and postfix expression is represented as xy+. To evaluate these expressions in programming, a stack is used. Similarly, stack is also used for converting one expression into another. For example, converting infix to postfix or infix to prefix. 2. Backtracking Backtracking is a recursive algorithm which is used for solving the optimization problem. So, to find the optimized solution of a problem with backtracking, we must find each and every possible solution of the problem, doesn't matter if it is correct or not. In backtracking, while finding every possible solution of a problem, we store the solution of a previously calculated problem in stack and use that solution to solve the upcoming problems. 3. Parenthesis Checking In programming, we make use of different type of parenthesis, like - (), (,}, which are used for opening and closing a block of code. So, these parentheses get stored in stack and control the flow of our program. Reverse a data processing function call 4. Function Call In programming, whenever you make a call from one function to another function. The address of the calling function gets stored in the stack. So, when the called function gets terminated. The program control moves back to the calling function with the help of the address which was stored in the stack. So, stack plays the main role when it comes to calling a function from other function. 5. String Reversal String reversal is another amazing application of stack. Here, one by one each character of the stack gets inserted into the stack. So, the first character of the stack is on the bottom of the stack and the last character of the string is on the top of the stack. After performing the pop operation in stack, we get the string in reverse order. 6. Memory Management The assignment of memory takes place in contiguous memory blocks. We call this stack memory allocation because the assignment takes place in the function call stack. The size of the memory to be allocated is known to the compiler. When 2 function is called, its variables get memory allocated on the stack. When the function call is completed, the memory for the variables is released. All this happens with the help of some predefined routines in the compiler. The user does not have to worry about memory allocation and release of stack variables 2.4 Evaluation of Infix, Postfix, and Prefix Expressions An algebraic expression is a legal combination of operators and operands. Operand is the quantity on which a mathematical operation is performed. Operand may be a variable like x, y, z or a Narayan Sapkota M.Sc. |Data Structures and Algorithms | Narayan Sapkota M.Sc. constant like 5, 4, 6 etc. Operator is a symbol which signifies a mathematical or logical operation between the operands. Examples of familiar operators include +, -,*,/, * etc. {An algebraic expression can be represented using three different notations. They are infix, postfix, and prefix notations: 1. Infix It is the form of an arithmetic expression in which we fix (place) the arithmetic operator in between the two operands. For example, A +B 2. Prefix itis the form of an arithmetic notation in which we fix (place) the arithmetic operator before (pre) its two operands. The prefix notation is called as polish notation. For example, +AB 3. Postfix It is the form of an arithmetic expression in which we fix (place) the arithmetic operator after (post) its two operands. The postfix notation is called as suffix notation and is also referred to reverse polish notation. For example, AB+. The three important features of postfix expression are: + The operands maintain the same order as in the equivalent infix expression. + The parentheses are not needed to designate the expression unambiguously * While evaluating the postfix expression the priority of the operators is no longer relevant. Operator Precedency Operators Bans Parenthesi 0.0.0 | Exponential notation Aor$ Multiplication and Division M7 Addi n and Subtraction 2.5. Infix to Post Fix Expression Algorithm 1. Read the element in the input. 2. Ifit is operand, display it 3. Ifitis opening parenthesis, insert it on stack. 4, If itis an operator, then * If stack is empty, insert operator on stack. * Ifthe top of stack is opening parenthesis, insert the operator on stack * [fit has higher priority than the top of stack, insert the operator on stack. * Else, delete the operator from the stack and display it, repeat Step 4. 5. If it is a closing parenthesis, delete the operator from stack and display them until an opening parenthesis is encountered, delete the opening parenthesis. 6. If there is more input, go to Step 1. Narayan Sapkota MSc7 Data Structures and Algorithms | Narayan Sapkota M.Sc. If there is no more input, delete the remaining operators to output. Example Convert the (X - ¥ / (Z + U) * V) infix expression into postfix expression. Input ee iis ( ( x x - x Y xy / xy ( xy a XYZ + XYZ U xYZU ) XYZU+ E XYZU+/ v XYZU+/V ) XYZU+/V*- 2.5.1. Infix to Prefix Expression Algorithm 1 2 3 4, First, reverse the infix expression given in the problem. . Scan the expression from left to right. Whenever the operands arrive, print them. If the operator arrives and the stack is found to be empty, then simply push the operator into the stack. If the incoming operator has higher precedence than the TOP of the stack, push the incoming operator into the stack. If the incoming operator has the same precedence with a TOP of the stack, push the incoming operator into the stack. If the incoming operator has lower precedence than the TOP of the stack, pop, and print the top of the stack. Test the incoming operator against the top of the stack again and pop the operator from the stack till it finds the operator of a lower precedence or same precedence. If the incoming operator has the same precedence with the top of the stack and the incoming operator is *, then pop the top of the stack till the condition is true. If the condition is not true, push the © operator. When we reach the end of the expression, pop, and print all the operators from the top of the stack. 10. If the operator is, then push it into the stack. Narayan Sapkota MSc oiData Structures and Algorithms | Narayan Sapkota M.Sc. 11. If the operator is '(, then pop all the operators from the stack tilit finds ) opening bracket in the stack. 12. Ifthe top of the stack is‘), push the operator on the stack. 13, At the end, reverse the output. Example Convert K + L-M*N + (OP) * W/U/V*T + Q into prefix equivalent expression. The Reverse expression would be: Q + T* V/UMW *) PAO[+ N*M -L + K Input expression a ix expression iQ [+ + (r + ic ” v eo a +) uv + arvu au +i aqvu iw vil aivuw [+ cael Qrvuw Db vir) arvuw iP yp) QTVUWwP: ls eurys arvuwe (0 eupys QTvuwPO. in au QtvuwPo* [+ ++ QTVUWPO**//* LN + QTVUWPO**//"N [* +e QTVUWPO**//*N M + QTVUWPO**//*NM. [- QTVUWPO**//*NIM* {c QTVUWPO**//*NMML [+ QTVUWPOA*//*NMPL | K QTVUWPO**//*NM*LK LQTVUWPO*//*NMPLK+-++ 2.5.2 Evaluation of Postfix Expression Algorithm 1. When an operand is encountered, itis pushed onto the stack 2. When an operator is seen, the operator is applied to the two numbers that are popped from the stack and the result is pushed onto the stack. Example Evaluate the given postfix expression 6 2 3+-3 8 2/+#243+ Narayan Sapkota MScOPERAND 1 Data Structures and Algorithms | Narayan Sapkota M.Sc. OPERAND 2 VALUE STACK 6,2 6, 2,3 6,5 {33 1,3,8 1,3,8,2 1,3,4 + [r]rfolo 1,7 * 7,2 49 siwfelelufolalalalalnr 49,3 +lololr 49 wlriniwiwfalrlalalalale 52 Narayan Sapkota MSc 3 |Data Structures and Algorithms | Narayan Sapkota M.Sc. Unit 3 Queue 3.1 What is Queue? Queue is a linear data structure in which the insertion and deletion operations are performed at two different ends. The insertion is performed at one end and deletion is performed at another end, In a queue data structure, the insertion operation is performed at a position which is known as ‘rear’ and the deletion operation is performed at a position which is known as ‘front’. In queue data structure, the insertion and deletion operations are performed based on FIFO (First in First Out) principle. rear front A real-world example of queue can be a single-lane one-way road, where the vehicle enters first, exits first. UasTIN FIRST IN Lasrour Sul FIRST OUT 3.1.1. Queue as an ADT A queue q of type Tis a finite sequence of elements with the operations: 1. MakeEmpty(q): To make q as an empty queue 2. IsEmpty(q): To check whether the queue q is empty. Return true if q is empty, return false otherwise. 3, IsFull(q): To check whether the queue q otherwise. full, Return true in q is full, return false 4, Enqueue (q, x): To insert an item x at the rear of the queue, if and only if q is not full 5. Dequeue(q): To delete an item from the front of the queue q. if and only if q is not empty. 6. Traverse (q): To read entire queue that is display the content of the queue. Narayan Sapkota MScData Structures and Algorithms | Narayan Sapkota M.Sc. Thus, by using a queue we can perform above operations thus a queue acts as an ADT. 3.2 Operations on Queue A queue is an object or more specifically an abstract data structure (ADT) that allows the following operations: 1. Enqueue or insertion which inserts an element at the end of the queue. 2. Dequeue or deletion which deletes an element at the start of the queue. Two pointers called FRONT and REAR are used to keep track of the elements in the queue. When initializing the queue, we set the value of FRONT and REAR to 0. On enqueuing an element, we increase the value of REAR index and place the new element in the position pointed to by REAR. Before enqueuing, we check if queue is already full On dequeuing an element, we return the value pointed to by FRONT and increase the FRONT index. Before dequeuing, we check if queue is already empty. When dequeuing the last element, we reset the values of FRONT and REAR to 0. Example Let us consider a queue, which can hold maximum of five elements. Initially the queue is empty. oy 2h gw tt Now, insert 11 to the queue. Then queue status will be: aa REAR = REAR = 1=1 FRONT = 0 er Next, insert 22 to the queue. Then the queue status is: a ae 7 REAR = REAR +1 4422 FRONT F R Again, insert another element 33 to the queue. The status of the queue is: Narayan Sapkota M.Sc.Data Structures and Algorithms | Narayan Sapkota M.Sc. 11 | 22 | 23 REAR = REAR + 1= 3 Fronr =o Now, delete an element, The element deleted is the element at the front of the queue. So, the status of the queue is: @.9.9 5 REAR = 2 tii FRONT = FRONT +1 = F R Again, delete an element. The element to be deleted is always pointed to by the FRONT pointer. So, 22 is deleted. The queue status is as follows: oa pe a Prot =FRonT +t #2 atey FOR ‘Now, insert new elements 44 and 55 into the queue. The queue status is: al“ [ss] Bate? : ‘ Next insert another element, say 66 to the queue. We cannot insert 66 to the queue as the rear crossed the maximum size of the queue (i, 5). There will be queue full signal. The queue status is as follows oe 2 Fe 3a | 44 | 55 REAR FRONT Now it is not possible to insert an element 66 even though there are two vacant positions in the linear queue. To overcome this problem the elements of the queue are to be shifted towards the beginning of the queue so that it creates vacant position at the rear end. Then the FRONT and Narayan Sapkota M.Sc.Data Structures and Algorithms | Narayan Sapkota M.Sc. REAR are to be adjusted properly. The element 66 can be inserted at the rear end. After this operation, the queue status is as follows: é This difficulty can overcome if we treat queue position with index 0 as a position that comes after position with index 4 ie, we treat the queue as a circular queve. 3.3 Circular Queue ‘Amore efficient queue representation is obtained by regarding the array Q(MAX] as circular. Any number of items could be placed on the queue. This implementation of a queue is called a circular queue because it uses its storage array as if it were a circle instead of a linear list. It is also called "Ring Buffer". There are two problems associated with linear queue. They are: * Time consuming: linear time to be spent in shifting the elements to the beginning of the queue. ‘© Signalling queue full: even if the queue is having vacant position. Example Let consider a linear queue status as follows: cS Sig REAR = 5 ah | | 58 FRONT = 2 F R Next insert another element, say 66 to the queue. We cannot insert 66 to the queue as the rear crossed the maximum size of the queue (ie, 5). There will be queue full signal. The queue status is as follows o a 2 3 4 REAR = 5 a3: | SF | Be FRONT = 2 » Narayan Sapkota M.Sc. |Data Structures and Algorithms | Narayan Sapkota M.Sc. This difficulty can be overcome if we treat queue position with index zero as a position that comes after position with index four then we treat the queue as a circular queue. In circular queue if we reach the end for inserting elements to it it is possible to insert new elements if the slots at the beginning of the circular queue are empty. 3.3.1. Representation of Circular Queue Let us consider a circular queue, which can hold maximum (MAX) of six elements. Initially the queue is empty. it, 1 uous Emer 4 Sages emery FRONT = REAR = 0 couNT =0 > 2 Circular Queue Now, insert 11 to the circular queue. Then circular queue status will be: 3 9 1 FRONT = 90 4 REAR = (REAR ~ 4) % 5 = 1 count Sf 5 2 Cweular Quewe Insert new elements 22, 33, 44 and 55 into the circular queue. The circular queue status is: mA 1 FRONT = 0. REAR = (REAR +1)%6=5 Cy Cireular Queue Narayan Sapkota M.Sc.Data Structures and Algorithms | Narayan Sapkota M.Sc. Now, delete an element. The element deleted is the element at the front of the circular queue. So, 11 is deleted. The circular queue status is as follows: R - ° Pa 1 FRONT = (FRONT = 1) % 6 4 ig REAR : COUNT = couNT-1=4 44733 : 2 Circular Queue Again, delete an element. The element to be deleted is always pointed to by the FRONT pointer. So, 22 is deleted. The circular queue status is as follows: Rg . 0 1 FRONT = (FRONT + 1) % 6 =2 4 REAR COUNT = cCoUNT-1=3 44 a3 JK > 2 Cirevlar Queue Again, insert another element 66 to the circular queue. The status of the circular queue is: R + es a 66. a 4 FRONT = 2 REAR = (REAR = 1) % 6 =0 Count scount +a = 4 aT > 2 te Cireular Queue Now, insert new elements 77 and 88 into the circular queue. The circular queue status is: Narayan Sapkota MSc 3 |Data Structures and Algorithms | Narayan Sapkota M.Sc. " ° es | 77 3 4 FRONT = 2, REAR REAR = REAR % 6 = 2 count = 6 43 2 ZR > aOR Circular Queue Now, if we insert an element to the circular queue, as COUNT = MAX we cannot add the element to circular queue. So, the circular queue is full. 3.4 Deque In the preceding section we saw that a queue in which we insert items at one end and from which we remove items at the other end. In this section we examine an extension of the queue, which provides a means to insert and remove items at both ends of the queue. This data structure is a deque. The word deque is an acronym derived from double-ended queue. Below figure shows the representation of a deque. Deque Data Structure There are two variations of deque. They are: 1. Input restricted deque (IRD) 2. Output restricted deque (ORD) front rear input restricted double ended queue Narayan Sapkota MScData Structures and Algorithms | Narayan Sapkota M.Sc. front rear Insert mm oe =) delete Output restricted double ended queue An Input restricted deque is a deque, which allows insertions at one end but allows deletions at both ends of the list. An output restricted deque is a deque, which allows deletions at one end but allows insertions at both ends of the list. 3.5 Operations on Deque 1. Check empty This operation is performed to check whether the deque is empty or not. If front = -1, it means that the deque is empty. 2. Check full This operation is performed to check whether the deque is full or not. If front = rear + 1, or front =O and rear = n- 1 it means that the deque is full 3. Insertion at the front end In this operation, the element is inserted from the front end of the queue. Before implementing the operation, we first must check whether the queue is full or not. If the queue is not full, then the element can be inserted from the front end by using the below conditions ‘+ If the queue is empty, both rear and front are initialized with 0. Now, both will point to the first element. ‘+ Otherwise, check the position of the front if the front is less than 1 (front < 1), then reinitialize it by front = n - 1, ie., the last index of the array. BEBE Si" Narayan Sapkota MSc BiData Structures and Algorithms | Narayan Sapkota M.Sc 4. Insertion at the rear end In this operation, the element is inserted from the rear end of the queue. Before implementing the operation, we first must check again whether the queue is full or not. If the queue is not full, then the element can be inserted from the rear end by using the below conditions ‘© If the queue is empty, both rear and front are initialized with 0, Now, both will point to the first element. ‘© Otherwise, increment the rear by 1. If the rear is at last index (or size - 1), then instead of increasing it by 1, we must make it equal to 0. ee BeOS == 2 Beni ~~~: t * z eta Bd ERE = -"~~ roa : = oe 5. Deletion at the front end In this operation, the element is deleted from the front end of the queue. Before implementing the operation, we first have to check whether the queue is empty or not If the queue is empty, ie, front = -1, itis the underflow condition, and we cannot perform the deletion. Ifthe queue is not full, then the element can be inserted from the front end by using the below conditions © Ifthe deque has only one element, set rear = -1 and front = -1 ‘© Else if front is at end (that means front = size - 1), set front = 0. ‘© Else increment the front by 1, (ie, front = front + 1). ‘ EE oo. ne Ena 2: * front rear Narayan Sapkota MSc BData Structures and Algorithms | Narayan Sapkota M.Sc. 6. Deletion at the rear end In this operation, the element is deleted from the rear end of the queue. Before implementing the operation, we first must check whether the queue is empty or not © Ifthe queue is empty, ie, front = -1, itis the underflow condition, and we cannot perform the deletion. If the deque has only one element, set rear = -1 and fron If rear = 0 (rear is at front), then set rear = n- 1. Else, decrement the rear by 1 (or rear = rear -1) oO 1 2 3 4 Bene front rear oO 1 2 3 4 a After deleting element 1 from rear end tt front rear 3.6 Priority Queue A priority queue is an abstract data type that behaves similarly to the normal queue except that each element has some priority, i, the element with the highest priority would come first ina priority queue. The priority of the elements in a priority queue will determine the order in which elements are removed from the priority queue In other words, @ priority queue is a collection of elements such that each element has been assigned a priority. We can insert an element in priority queue at the rear position, We can delete an element from the priority queue based on the element's priority and such that the order in which elements are deleted and processed comes from the following rules: = Anelement of higher priority is processed before any element of lower priority, ‘© Two elements with same priority are processed according to the order in which they were added to the queue. It follows FIFO rules. ‘© We always remove an element with the highest priority, which is given by the minimal integer priority assigned, For example, suppose we have some values like 5, 10, 30, 25, 40 has to be inserted in a priority queue and their priority order is 3, 1, 4, 2, 5 respectively. Therefore, the 10 number would be having the highest priority while 40 will be having the lowest priority. Narayan Sapkota MSc BData Structures and Algorithms | Narayan Sapkota M.Sc. Elements Priority order Index of Array Elements in Pri fear 5 3 0 10 10 if 1 (25 30 4 2 5 (25 2 3 | 30 40 5 4 40 Priority queues are two types: 1. Ascending order priority queue 2. Descending order priority queue Ascending order priority queue: It is Lower priority number to high priority number. Examples: order is 2,6,7,10,11 ‘element with the lowest priority 7 BeBoo ‘element with the highest priority Descending order priority queue: It is high priority number to lowest priority number. Examples: Order is 10,9,8,7,6 ‘element with the lowest priority nog ‘element with the highest priority 3.6.1. Implementation of Priority Queue using Array The element is simply added at the rear end as usual. For deletion, the element with highest priority is searched and then deleted. Narayan Sapkota MScData Structures and Algorithms | Narayan Sapkota M.Sc. Insert 40 priority 1 [3] [2] (4) [2] =~ priority (3) (1) £4) (21) = priority 5]10]30]25| __]~— Queue 5] 10]30]25]40] =— Queue (0) (2) (2) {3} [4]+— index {0} (2) [2] [3] [4] +~ index rear=3 rear=4 Delete Delete {31 (4) (21) = priority {3} (4) {2} <—Ppriority 5/30} 25| 40) = Queue 5 30|25 —=— Queue {0} (2) (2) {3} [4] =— index (0) (1) (2) £3) [4] = index rear=3 rear=2 Note: Priority queue can be implemented using an array, a linked list, a heap data structure, or a binary search tree. Among these data structures, heap data structure provides an efficient implementation of priority queues. Narayan Sapkota MSc. BData Structures and Algorithms | Narayan Sapkota M.Sc. Unit 4 List 4.1. Whatis List? A list is a linear data structure that stores a collection of items in a specified order. Lists are a fundamental data structure in many programming languages and are used to store and manipulate data in a variety of applications. Lists are dynamic data structures, which means that they can grow and shrink as needed. In most programming languages, lists are implemented as arrays, which are contiguous blocks of memory that hold a fixed number of elements of the same data type. Arrays have a fixed size, which means that the size of the list is determined when the list is created and cannot be changed later. However, many programming languages also provide dynamic list data structures, such as linked lists, which can grow and shrink as elements are added or removed. Linked lists are composed of nodes, which are structures that contain the element itself and a pointer to the next node in the list. This allows the list to be modified by adding or removing nodes without the need to move or copy the elements in the list. Lists are very versatile data structures and can be used to store and manipulate data in many different ways. They are commonly used in programming tasks such as storing data in a database, generating lists of items in a user interface, and implementing data structures such as stacks, queues, and graphs. Most programming languages provide built-in functions and methods for manipulating lists, such as adding, deleting, and updating elements, searching for specific elements, and sorting the list. 4.1.1 Why we need list data structure? Lists are an essential data structure in many programming languages and are used to store and manipulate data in a variety of applications. Some of the main reasons why lists are useful include: '* Lists allow you to store and manipulate collections of data in a single place. This makes it easier to manage and access the data, as you can manipulate the list as @ whole instead of dealing with the individual elements separately. '* Lists are dynamic data structures, which means that they can grow and shrink as needed. This is especially useful when you don't know how much data you need to store or when the size of the data is likely to change over time. ‘+ Lists allow you to store elements of different data types in the same collection. This is useful when you need to store a mix of data types, such as numbers, strings, and objects, in single data structure. Narayan Sapkota M.Sc. BiData Structures and Algorithms | Narayan Sapkota M.Sc. ‘* Lists provide many built-in functions and methods for manipulating the data, such as adding, deleting, and updating elements, searching for specific elements, and sorting the list. This makes it easy to perform common operations on the data stored in the list ‘© Lists are often used in combination with looping constructs, such as for loops, to perform operations on all the elements in the list. This allows you to perform the same operation on multiple elements of the list without having to write the same code multiple times. Ina nutshell lists are a very useful data structure that can help you organize and manipulate data ina variety of applications 4.1.2, What is a difference between Array and List? In many programming languages, the terms “array” and “list” are used interchangeably to refer to a collection of items that can be accessed by an index. However, in some languages and contexts, the two terms may have distinct meanings. An array is typically a fixed-size collection of items, where each item has the same data type and the array has a specific amount of memory allocated to it, Arrays are often implemented as a block ‘of memory where each element is placed at a specific location, and these locations can be accessed directly using their index In languages such as C or C++, arrays have a strict size that needs to be defined during declaration and can't be resized during runtime. A list, on the other hand, is typically a dynamic collection of items that can grow or shrink as needed. Lists are often implemented as a linked list, where each element contains a reference to the next element, and the last element points to null. This structure enables dynamic resizing but often at a cost of performance overhead. For example, Python has both "lists" and “arrays” as built-in types, but they are implemented differently: a Python list is a dynamic array, while a NumPy array is a more efficient, fixed-size array. In summary: ‘+ Arrays have a fixed size and stores data in contiguous memory. ‘© Lists are Dynamic in size and uses linked-list based memory allocation ‘+ Arrays are more efficient than list when it comes to memory and retrieval time and are preferred when we know that size of data that needs to be stored. ‘+ Lists are more flexible as compared to array, it does not have a fixed size and data can be added, removed or modified during runtime. 42. Static and Dynamic List Structure In computer science, a static list is a data structure that has a fixed size and cannot be modified once it is created, An example of a static list is an array, which is a contiguous block of memory Narayan Sapkota M.Sc. BData Structures and Algorithms | Narayan Sapkota M.Sc. that holds a fixed number of elements. On the other hand, a dynamic list is a data structure that can change in size as the program is running. An example of a dynamic list is a linked list, which consists of a series of nodes that are linked together by pointers. The size of a linked list can change as nodes are added or removed from the list. In G a static list can be implemented using an array, which is a contiguous block of memory that holds a fixed number of elements of the same data type. Here is an example of a static list of integers in c: ftdefine SIZE 5 int static_list[SIze] = (0, 1, 2, 3, 4}; int main() { // Trying to add an element to the list will result in an error static_list[SIZE] = 5; // Output: array bounds exceeded return @ A dynamic list can be implemented using a linked list, which consists of a series of nodes that are linked together by pointers. In C, a linked list can be implemented using a struct to represent each node and a pointer to link the nodes together. Here is an example of a dynamic list of integers in c Hinclude
#include
/{ Define a struct to represent each node in the list struct Node { int data; struct Node* next; ue int main() { // Create the head of the list struct Node* head = NULL; // Add elements to the list for (int i= 0; i < 53 it) { // Create a new node struct Node* new_node = (struct Node*) malloc(sizeof(struct Node)); new_node->data = i; new_node->next = head; head = new_node; + // Traverse the list and print the elements struct Node* current = head; Narayan Sapkota M.Sc. BiData Structures and Algorithms | Narayan Sapkota M.Sc. while (current != NULL) { print#("%d ", current->data); current = current->next; + printf("\n"); return 5 Here are some key differences between static and dynamic lists: 1. Size: Static lists have a fixed size, which means that the size of the list is determined when the list is created and cannot be changed later. Dynamic lists, on the other hand, can grow or shrink as needed. 2. Memory usage: Static lists use @ contiguous block of memory to store the elements of the list. This means that the size of the list has to be determined in advance and the memory has to be allocated upfront. Dynamic lists, on the other hand, can allocate and deallocate memory as needed, which makes them more efficient when the size of the list is unknown or may change frequently. 4.3 Array Implementation of Lists ‘An array is a data structure that stores a fixed-size sequential collection of elements of the same data type. In many programming languages, including C and Python, arrays can be used to implement lists, which are ordered collections of items that can be of any data type. #include
#include
define SIZE 5 int main() { // Declare an array with 5 elements int array _list[SIZE] = {@, 1, 2, 3, 4}; // Access an element of the list printf("%d\n", array list(2]); // Output: 2 // Modify an element of the list array_list[(3] = 10; for (int i = 0; i < SIZE; it) { print#("%d ", array list[i]); // Output: @ 1210 4 + printf("\n"); // Trying to add an element to the list will result in an error array_list[SIZE] = 5; // Output: array bounds exceeded return 83 Narayan Sapkota M.Sc. BData Structures and Algorithms | Narayan Sapkota M.Sc. AAs with other programming languages, one advantage of using an array to implement a list in C is that the elements can be accessed and modified directly using their index, which makes it easy to implement common operations such as inserting, deleting, and updating elements. However, arrays have a fixed size and cannot grow or shrink dynamically, so they are not well-suited for scenarios where the size of the list is unknown or may change frequently. In those cases, it is usually more efficient to use a dynamic list data structure, such as a linked list, which can grow and shrink as needed. 4.4 Queue asa list [Refer Unit Queue] Narayan Sapkota MSc BiData Structures and Algorithms | Narayan Sapkota M.Sc. Unit 5 Linked List 5.1 What is Linked List? A linked list is a linear collection of data elements, called nodes, each pointing to the next node by means of a pointer. itis a data structure consisting of a collection of nodes which together represent a sequence. A node contains two fields ie. data stored at that particular address and the pointer which contains the address of the next node in the memory. The last node of the list contains pointer to the null Data Next The first node also known as HEAD is always used as a reference to traverse the list. Linked list can be visualized as a chain of nodes, where every node point to the next node. | Data wet -|_—+ Data wext-|—+ Data west |» NULL HEAD 5.1.1 Linked List Vs Array Here are a few advantages of linked lists over arrays: 1. Dynamic size: A linked list can grow or shrink in size during the execution of a program, while the size of an array is fixed once it is created. 2. Efficient insertion and deletion: inserting or deleting an element in a linked list is a relatively quick operation because only the links need to be adjusted, as opposed to shifting elements in an array. 3. No wasted space: In a linked list, the memory is used efficiently as there is no wasted space as in the case of array where there can be "holes" if elements are deleted. 4. Efficient implementation of stacks and queues: Linked lists can be easily used to implement stack and queue data structures. Narayan Sapkota M.Sc. HiData Structures and Algorithms | Narayan Sapkota M.Sc. 5. No need to know the size in advance: With an array, you have to know the maximum size of the array in advance, whereas with a linked list, you can start with an empty list and add elements to it as needed. 6. Memory allocation: Linked list elements are stored in non-contiguous memory locations, which means that it can be allocated in any order and not necessarily in contiguous manner. 5.1.2. Linked List vs Dynamic Array A linked list and a dynamic list are similar in that they both can grow or shrink in size during the execution of a program. However, there are a few key differences between the two! 1. Implementation: A linked list is a data structure that consists of a collection of nodes, where each node stores a reference to an object and a reference to the next node in the list. A dynamic list, on the other hand, is a more general term that refers to a list that can grow or shrink in size, but the implementation of the list can vary. 2, Memory allocation: A linked list elements are stored in non-contiguous memory locations, which means that it can be allocated in any order and not necessarily in contiguous manner. A dynamic list can be implemented as an array, which is stored in contiguous memory locations. 3. Efficient insertion and deletion: Linked lists are often more efficient than arrays at insertion and deletion operations, because only the links need to be adjusted, whereas with an array all elements need to be shifted. Linked list is less efficient in terms of memory usage as it needs to store extra memory for next pointer. 5.2 Linked List as an ADT The basic operations to be performed on the linked list are as follows: 1. Creat : This operation is used to create a linked list 2. Insertion: This operation is used to insert a new nose in a kinked listin a specified position. Anew node may be inserted * Atthe beginning of the linked list + Atthe end of the linked list + Athe specified position in a linked list Narayan Sapkota M.Sc. BData Structures and Algorithms | Narayan Sapkota M.Sc. 3. Deletion: The deletion operation is used to delete a node from the linked list. Anode may, be deleted from © The beginning of the linked list © the end of the linked list * the specified position in the linked list. 4, Traversing: The list traversing is a process of going through all the nodes of the linked list from on end to the other end, The traversing may be either forward or backward. 5. Searching or find: This operation is used to find an element in a linked list. In the desired element is found then we say operation is successful otherwise unsuccessful. 6. Concatenation: Its the process of appending second list to the end of the first list. 5.3 Types of Linked List The types of linked list are mentioned below: Singly Linked List: can be traversed only in forward direction. Doubly Linked List: can be traversed in forward and backward directions. Circular Singly Linked List: Last element contains link to the first element as next. Circular Doubly Linked List: Last element contains link to the first element as next and awe the first element contains link of the last element as previous 5.4 Singly Linked List Singly linked list can be defined as the collection of ordered set of elements. The number of elements may vary. A node in the singly linked list consist of two parts: data part and link part. Data part of the node stores actual information that is to be represented by the node while the link part of the node stores the address of its immediate successor. (One-way chain or singly linked list can be traversed only in one direction. In other words, we can say that each node contains only next pointer, therefore we cannot traverse the list in the reverse direction Consider an example where the marks obtained by the student in three subjects are stored in a linked list as shown in the figure. Narayan Sapkota M.Sc. BiData Structures and Algorithms | Narayan Sapkota M.Sc. Head Node Tail Data Address In the above figure, the arrow represents the links. The data part of every node contains the marks obtained by the student in the different subject. The last node in the list is identified by the null pointer which is present in the address part of the last node. 5.4.1 Insertion in Singly Linked List Ina single linked lst, the insertion operation can be performed in three ways. They are as follows... 1._ Inserting at Beginning of the list 2. Inserting at End of the list 3. Inserting at Specific location in the list Inserting at Beginning of the list Narayan Sapkota MScyRuens Data Structures and Algorithms | Narayan Sapkota M.Sc. Create a newNode with given value and newNode ~ next as NULL Check whether list is Empty (hea ULL). If itis Empty then, set head = newNode. If itis Not Empty then, define a node pointer temp and initialize with head. Keep moving the temp to its next node until it reaches to the last node in the list (until temp + next is equal to NULL). Set temp — next = newNode. 19 at End of the list Narayan Sapkota MScData Structures and Algorithms | Narayan Sapkota M.Sc. or _ Nowy Ee BBs. store memery 1000 Saeed suis node t A Insert a new Node at the end — BBS 7 ptr Nodet mey 1000, cimeertta| myer node ‘ A Create a newNode with given value and newNode ~ next as NULL Check whether list is Empty (hea ULL). |f itis Empty then, set head = newNode. If itis Not Empty then, define a node pointer temp and initialize with head. Keep moving the temp to its next node until it reaches to the last node in the list (until temp + next is equal to NULL). 6. Set temp — next = newNode. vane Inserting at Specific location in the list (After a Node) Narayan Sapkota MScData Structures and Algorithms | Narayan Sapkota M.Sc. ptr lode1 Node2 Node3 Noded Insert New Node at the middle, ———> Ovtracucecom Create a newNode with given value, Check whether list is Empty (hea If itis Empty then, set newNode — next = NULL and head = newNode. If itis Not Empty then, define a node pointer temp and initialize with head. Keep moving the temp to its next node until it reaches to the node after which we want to insert the newNode (until temp1 — data is equal to location, here location is the node value after which we want to insert the newNode).. 6. Every time check whether temp is reached to last node or not. If itis reached to last node then display "Given node is not found in the list. Insertion not possible!!!" and terminate the function, Otherwise move the temp to next node. 7. Set ‘newNode — next = temp — next’ and ‘temp — next = newNode’ vane 5.4.2 Deletion in Singly Linked List Ina single linked list, the deletion operation can be performed in three ways. They are as follows- 1. Deleting from Beginning of the list 2. Deleting from End of the list 3. Deleting a Specific Node Deleting from Beginning of the list Narayan Sapkota MScData Structures and Algorithms | Narayan Sapkota M.Sc. Nodet Node2 Node3 Node4 (5; 2 ee ee ee a sr Re a ec eo Node3 saint ett han bon deed im Leesan | a Meas Peon Owirensucecom 1. Check whether list is Empty (hea If it is Empty then, display ‘List is Empty!!! Deletion is not possible’ and terminate the function. If itis Not Empty then, define a Node pointer "temp! and initialize with head. Check whether list is having only one node (temp ~ next ULL) If itis TRUE then set head = NULL and delete temp (Setting Empty list conditions) 6. Ifitis FALSE then set head = temp ~ next, and delete temp. yay Deleting from End of the list Narayan Sapkota MScData Structures and Algorithms | Narayan Sapkota M.Sc. ptr Node1 Node3 me a Aa ee. t = 1 ' } | last node ' a soot 1000! 2000 ! 3000 _— = adaress of ! Memory Address! Memory Address! | Memory Address | = tstrode | See Leth oe | tobe deleted | ptr Node1 Node2 1. Check whether list is Empty (head == NULL) 2. If itis Empty then, display ‘List is Empty!!! Deletion is not possible’ and terminate the function. 3. If it is Not Empty then, define two Node pointers ‘tempt’ and ‘temp2' and initialize ‘temp1' with head 4, Check whether list has only one Node (temp1 ~ next == NULL) 5. If it is TRUE. Then, sethead = NULL and delete tempt. And terminate the function. (Setting Empty list condition) 6. If itis FALSE, Then, set temp2 = tempt and move temp! to its next node. Repeat the same until it reaches to the last node in the list. (until temp1 — next == NULL) 7. Set temp2 ~ next = NULL and delete tempt Deleting a Specific Node from the list Narayan Sapkota MScData Structures and Algorithms | Narayan Sapkota M.Sc. Check whether list is Empty (head NULL) . If itis Empty then, display ‘List is Empty!!! Deletion is not possible’ and terminate the function. If it is Not Empty then, define two Node pointers ‘tempt’ and ‘temp2' and initialize ‘temp1' with head. . Keep moving the temp1 until it reaches to the exact node to be deleted or to the last node. And every time set 'temp2 = tempt’ before moving the ‘tempt’ to its next node. If itis reached to the last node then display “Given node not found in the list! Deletion not possible!!! And terminate the function. . fit is reached to the exact node which we want to delete, then check whether list is having only one node or not If list has only one node and that is the node to be deleted, then set head = NULL and delete temp! (free(temp!)). If list contains multiple nodes, then check whether temp1 is the first node in the list (temp1 == head). If temp1 is the first node then move the head to the next node (head = head ~ next) and delete temp1 Narayan Sapkota MScData Structures and Algorithms | Narayan Sapkota M.Sc. 10. if temp1 is not first node then check whether it is last node in the list (temp — next NULL). 11. If temp1 is last node then set temp2 — next = NULL and delete temp! (free(temp!)) 12, If temp1 is not first node and not last node then set temp2 — next = temp1 — next and delete tempt (free(temp1)) 5.4.3. Searching in a Singly Linked List ptr Node1 Node2 Node3 Node4 me BR Ba ey ee---- ay 1000 | 2000 3000 | 5000 = Bites eek ek en search value: 30 Found tr 1430 Yes 20#30) Node2 20290 Mies Noded me BR Be Bey ee =r 1000 tre pant sn 009, 5000 1. Initialize a current pointer = head 2. Check if the current pointer is null, if it is, return “Value not found” as the value is not in the list. Compare the value stored in the current node to the search value. If the values are equal, return the current node as the value is found. If the values are not equal, set the current pointer to the next node and repeat step 3-4. Repeat step 3-5 until the current pointer is null. ona 5.4.4 Displaying a Single Linked List Check whether list is Empty (head == NULL) If itis Empty then, display ‘List is Empty!" and terminate the function. If itis Not Empty then, define a Node pointer ‘temp’ and initialize with head. Keep displaying temp — data with an arrow (--->) until temp reaches to the last node Finally display temp ~ data with arrow pointing to NULL (temp ~ data ---> NULL). yawns Narayan Sapkota MScData Structures and Algorithms | Narayan Sapkota M.Sc. 5.5. Linked Stacks A linked stack is a stack data structure that is implemented using a singly linked list. A stack is a Last in First Out (LIFO) data structure, which means that the last element added to the stack is the first one to be removed. Ina linked stack, each element is represented by a node, and each node contains a reference to the next node in the list. The last node in the list is the top of the stack, and the first node in the list is the bottom of the stack. The main operations that can be performed ona linked stack are push and pop. 1. Push: The push operation is used to add an element to the top of the stack. To push an element onto a linked stack, a new node is created with the element and its next pointer is set to the current top of the stack. Then the head pointer is updated to point to the new node, which becomes the new top of the stack. 2. Pop: The pop operation is used to remove the top element from the stack. To pop an element from a linked stack, the head pointer is updated to point to the next node in the list, and the current top element is removed from the stack linked stack is more dynamic than an array-based stack, as elements can be added and removed without having to worry about array size. It also allows faster insertion and deletion at the head, as it only involves changing the reference of the head pointer and not the entire array. 5.6 Linked Queues A linked queue is a type of queue data structure that is implemented using linked list. A queue is a linear data structure that follows the First in First Out (FIFO) principle, meaning that the first element added to the queue will be the first one to be removed. A linked queue consists of a head and a tail pointer, pointing to the front and rear of the queue, respectively. The head pointer points to the first element in the queue and the tail pointer points to the last element in the queue. Insertions in a linked queue occur at the rear end, and deletions occur at the front end. The operations that can be performed on a linked queue include enqueue (adding an element to the rear end of the queue), dequeue (removing an element from the front end of the queue), and display (printing the elements of the queue). A singly linked list can be used to implement linked queue, where enqueue operation is performed at the end and dequeue operation is performed at the front. A doubly linked list can also be used, where insertion and deletion can be performed at both ends. A linked queue is useful when the size of the queue is not fixed, and can change dynamically, as it does not have a fixed size and the memory is allocated dynamically. Narayan Sapkota M.Sc.Data Structures and Algorithms | Narayan Sapkota M.Sc. 5.7 Doubly Linked Lists A doubly linked list is a linear data structure, in which the elements are stored in the form of a node. Each node contains three sub-elements. A data part that stores the value of the element, the previous part that stores the pointer to the previous node, and the next part that stores the pointer to the next node as shown in the below image: Prev Data Next The first node also known as HEAD is always used as a reference to traverse the list. The previous of head node and next of last node points to NULL. A doubly linked list can be visualized as a chain of nodes, where every node point to previous and next node. NULL =e HEAD Data wo Prev Data Next |. NULL 5.7.1 Insertion in Doubly Linked List Ina double linked list, the insertion operation can be performed in three ways as follows... 1. Inserting at Beginning of the list 2. Inserting at End of the list 3. Inserting at Specific location in the list Inserting at Beginning of the list Narayan Sapkota MScData Structures and Algorithms | Narayan Sapkota M.Sc. Ovteeeesen Create a newNode with given value and newNode — previous as NULL. Check whether list is Empty (hea¢ NULL) If it is Empty then, assign NULL to newNode ~ next and newNode to head. If itis not Empty then, assign head to newNode ~ next and newNode to head. Inserting at End of the list 1 2 3 4, 5. Nodet Create a newNode with given value and newNode ~ next as NULL Check whether list is Empty (head == NULL) If itis Empty, then assign NULL to newNode — previous and newNode to head. If it is not Empty, then, define a node pointer temp and initialize with head. Keep moving the temp to its next node until it reaches to the last node in the list (until temp — next is equal to NULL). Narayan Sapkota MScData Structures and Algorithms | Narayan Sapkota M.Sc. 6. Assign newNode to temp ~ next and temp to newNode ~ previous. location in the (After a Node) Sate, Node2 Tyo 400 1. Create a newNode with given value. 2. Check whether list is Empty (head NULL) 3. If itis Empty then, assign NULL to both newNode ~ previous & newNode ~ next and set newNode to head. 4. If it isnot Emptythen, define two node pointers temp1 & temp2 and initialize temp1 with head. 5. Keep moving the temp to its next node until it reaches to the node after which we want to insert the newNode (until temp1 — data is equal to location, here location is the node value after which we want to insert the newNode) 6. Every time check whether tempt is reached to the last node. If it is reached to the last node then display ‘Given node is not found in the list!!! Insertion not possible!!!" and terminate the function. Otherwise move the temp! to next node. 7. Assign temp1 — next to temp2, newNode to temp1 — next, temp! to newNode ~ previous, temp2 to newNode — next and newNode to temp2 — previous. 5.7.2 Deletion in Doubly Linked List Ina double linked list, the deletion operation can be performed in three ways as follows- 1. Deleting from Beginning of the list 2. Deleting from End of the list 3. Deleting a Specific Node Deleting from Beginning of the list Narayan Sapkota MScData Structures and Algorithms | Narayan Sapkota M.Sc. tobedeleted | 1. Check whether list is Empty (hea If itis Empty then, display ‘List is Empty!!! Deletion is not possible’ and terminate the function. If itis not Empty then, define a Node pointer 'temp' and initialize with head. Check whether list is having only one node (temp ~ previous is equal to temp ~ next) If itis TRUE, then set head to NULL and delete temp (Setting Empty list conditions) If it isFALSE, then assign temp — next to head, NULL to head ~ previous and delete temp. p ed Deleting from End of the list. Narayan Sapkota M.Sc.Data Structures and Algorithms | Narayan Sapkota M.Sc. 7. Nodes (GBooTs, ‘Sil 80) /B001s; , [$300)|60)/760Ts: , |$500) [76] [nls - Nodet Node2 we Ovireurcecom Check whether list is Empty (hea¢ If it is Empty, then display ‘List is Empty! function. If itis not Empty then, define a Node pointer 'temp' and initialize with head. Check whether list has only one Node (temp — previous and temp — next both are NULL) Ifitis TRUE, then assign NULL to head and delete temp, And terminate from the function (Setting Empty list condition) If it is FALSE, then keep moving temp until it reaches to the last node in the list (until temp — next is equal to NULL) Assign NULL to temp — previous — next and delete temp. Deletion is not possible’ and terminate the Deleting a Specific Node from the list Narayan Sapkota MScData Structures and Algorithms | Narayan Sapkota M.Sc. ' Node3 Owiresourcecom = 1. Check whether list is Empty (head 2. If itis Empty then, display ‘List is Empty!!! Deletion is not possible’ and terminate the function. 3. Ifitis not Empty, then define a Node pointer ‘temp’ and initialize with head, 4, Keep moving the temp until it reaches to the exact node to be deleted or to the last node. 5. If itis reached to the last node, then display ‘Given node not found in the list! Deletion not possible!!!" and terminate the fuction. 6. Ifitis reached to the exact node which we want to delete, then check whether list is having only one node or not 7. if list has only one node and that is the node which is to be deleted then set head to NULL and delete temp (free(temp)). 8. Iflist contains multiple nodes, then check whether temp is the first node in the list (temp head). 9. if temp is the first node, then move the head to the next node (head = head ~ next), set head of previous to NULL (head —- previous = NULL) and delete temp. 10, If temp is not the first node, then check whether it is the last node in the list (temp ~ next NULL. 11. If temp is the last node then set temp of previous of next to NULL (temp — previous ~ next = NULL) and delete temp (free(temp)) Narayan Sapkota MScData Structures and Algorithms | Narayan Sapkota M.Sc. 12.\ftempis not the first node and not the last node, then set temp of previous of next to temp of next (temp ~ previous — next = temp — next), temp of next of previous to temp of previous (temp ~ next ~- previous = temp ~ previous) and delete temp (free(temp)) 5.7.3. Searching in a Doubly Linked List 1. Initialize a pointer, current, to the head of thelist. 2. While current is not null a. Compare the data of the current node to the target data b. If the data matches, retum the current node. cc. If the data does not match, set current to the next node in the list (current.next). 3. If the end of the list is reached without finding a match, return nul to indicate that the target data was not found in the list. 5.7.4 Displaying a Double Linked List Check whether list is Empty (head == NULL) If it is Empty, then display ‘List is Empty!!!" and terminate the function. If tis not Empty, then define a Node pointer ‘temp’ and initialize with head. Display ‘NULL <--- *. Keep displaying temp — data with an arrow (<===>) until temp reaches to the last node Finally, display temp — data with arrow pointing to NULL (temp — data ---> NULL). oy eens Narayan Sapkota MScData Structures and Algorithms | Narayan Sapkota M.Sc. Unit 6 Recursion 6.1 What is recursion? Recursion is the process of calling the function by itself as its subroutine to solve the complex program. Recursion uses the method of dividing the program into sub-tasks and calling it repeatedly instead of the iterative method which takes lots of effort and time to solve the same problem. Therefore, the function which calls itself is called the recursive function, and the process of calling a function by itself is called recursion. The most important thing about the recursion is it should have the base case to terminate the recursion. As the recursive function calls itself continuously, itis always possible that the program goes into the infinite loop. So, if we create the terminate base case using the if..else statement, the program will check the base case condition every time and prevent going into the infinite loop. Recursive function has two different parts 1. Base case: The base case is used to terminate the task of recurring, If a base case is not defined, then the function will recur an infinite number of times. The base case gives the conditions in which the recursive calls will halt means collapse the recursion when you hit the base case, 2. Recursive case: In the Recursive case, the problem space is made smaller and smaller dive deeper into the recursion in the recursive case. Recursive case simplifies a bigger problem into several simpler sub-problems and then calls them. Example int factorial (int n) { if ( ) return 1; //base case, as we know that factorial of 1 is 1 else return n*factorial(n-1); //recursive case 6.1.1 How does recursion work? The function of the recursion approach is to solve the problem effectively in comparison to another problem-solving approach. The recursion process divides the problem into the subtask as a function and continuously calls the same function again to get one step closer to the final solution. This process continues until we find the final solution to the problem. Each time the part of the solution is found, it is stored in the form of stack data structure in the memory and at last, popped out to get the final solution, As we approach the final solution, there is a base condition that should be checked to get out of the recursion process. This base condition is checked using the conditional statement and hence avoids the recursion process to get into the infinite loop. If Narayan Sapkota M.Sc.Data Structures and Algorithms | Narayan Sapkota M.Sc. for any reason the base case fails to work, the program will fall into an infinite loop, and we will never reach the solution of the program. Vold recursion (¢ ~ Recursive : call recursion (;. ——J } int main 0 ¢ recursion 0; a Function ‘ call 6.2 Anatomy of a Recursive Call Recursive definitions are frequently used to define functions and sequences of numbers, For instance, the factorial function, nl, can be defined in the following manner: Fa ifn=0 n(n-)! ifn>0 The code for computing factorial of an integer n can be written directly from the definition of a factorial is: int factorial (int n) return 1; //base case, as we know that factorial of @ is 1 else return n*factorial(n-1); //recursive case The below figure shows anatomy of the recursive call. For simplicity we are calculating the factorial of integer 4 Narayan Sapkota MSc HiData Structures and Algorithms | Narayan Sapkota M.Sc. return 4 #6 = 24 \ Y_— )retum 32s X return 2+ 12 \ a= return 1 6.3 Types of Recursion There are two main types of recursion techniques: tail recursion and non-tail recursion, Tail recursion is 2 specific form of recursion where the recursive call is the last operation performed by the function. In other words, the function does not have any instructions to execute after the recursive call returns. When a function is tail recursive, the compiler or interpreter can optimize the recursive call by reusing the current function cal's stack frame, rather than creating anew one. This can significantly reduce the overhead of the recursion and prevent stack overflow errors On the other hand, non-tail recursion is when the recursive call is not the last operation performed by the function. After the recursive call returns, the function still has some instructions to execute. This means that the compiler or interpreter cannot optimize the recursive call by reusing the current stack frame, and a new stack frame must be created for each recursive call This can lead to a higher overhead and a greater risk of stack overflow errors. Another classification of recursion is direct and indirect recursion. Direct recursion is when a function calls itself directly. Indirect recursion occurs when a function calls a second function, which in turn calls the original function. Additionally, Recursion can be classified as linear and tree recursion as well. Linear recursion occurs when the function calls itself one or more times in a linear sequence. Tree recursion occurs when the function calls itself multiple times in a branching pattern, creating a tree-like structure of recursive calls. In summary, recursion can be classified based on the following categories: 1. Tail and non-tail recursion 2. Direct and Indirect Recursion 3. Linear and Tree Recursion Narayan Sapkota M.Sc.Data Structures and Algorithms | Narayan Sapkota M.Sc. It's worth noting that some recursion can be optimized by converting them into a loop (iteration) and this process is known as recursion to iteration conversion. 6.3.1 Tail Recursion Tail recursion is a specific form of recursion where the recursive call is the last operation performed by the function. in other words, the function does not have any instructions to execute after the recursive call returns. When a function is tail recursive, the compiler or interpreter can optimize the recursive call by reusing the current function call's stack frame, rather than creating a new one. This can significantly reduce the overhead of the recursion and prevent stack overflow errors. Example long factorial(long n, long result) { if (n == 0) { return result; + else { return factorial(n - 1, n * result); t } int main() { Jong num long result printf("%1d! return factorial (num, 1); ld\n", num, result); + In this example, the factorial function takes two arguments: the number n for which we want to calculate the factorial, and an additional argument result which is used to keep track of the intermediate results. The function checks if n is zero and, if so, returns the final result. If n is not zero, the function makes a recursive call to itself with m- 1 and n * result as the arguments. The recursive call is the last operation performed by the function, so itis a tail-recursive call. It is worth noting that while the above example will work as a tail recursion and will not cause stack overflow issues but not all compilers would optimize tail recursion by default and thus the recursive function will consume stack memory on each recursion. This optimization technique is known as Tail call optimization (TCO) and it is optional in most of the compilers. 6.3.2. Non-Tail Recursion A non-tail recursion is when the recursive call is not the last operation performed by the function. After the recursive call returns, the function still has some instructions to execute. This means that Narayan Sapkota M.Sc. BiData Structures and Algorithms | Narayan Sapkota M.Sc. the compiler or interpreter cannot optimize the recursive call by reusing the current stack frame, and a new stack frame must be created for each recursive call, This can lead to a higher overhead and a greater risk of stack overflow errors. Example int factorial (int n) { if (n == @) { return 15 + return n * factorial (n-1); } In this example, the function checks if the input number is 0, and if so, it returns 7, Otherwise, it makes a recursive call to the same function with the input number decremented by 1, and then multiplies the result of the recursive call by the input number and returns the result. 6.3.3 Direct Recursion Direct recursion is a type of recursion where a function calls itself directly. Ths is the most common type of recursion. In direct recursion, a function makes a call to itself, typically as the last action in the function, Example int factorial(int n) { if (n == @) { return 1 + return n * factorial(n-1); } This function is a direct recursive function because it calls itself directly. The function calls itself with the input number decremented by 1, and then multiplies the result of the recursive call by the input number and returns the result Another example can be calculating fibonacci series, where fib(n) = fib(n-1) + fib(n-2) int fibonacci(int n) { if (nm <= 1) { return nj + return fibonacci(n-1) + Fibonacci (n-2); + In this example, the fibonacci function is directly recursive because it calls itself twice with the input number decremented by 1 and 2 respectively. Narayan Sapkota M.Sc. BiData Structures and Algorithms | Narayan Sapkota M.Sc. Direct recursion can be a simple way to solve a problem, but it can also be inefficient or lead to stack overflow errors if the recursive calls are not in tail position and not optimized. It is important to understand that not all recursions are direct recursions, there are also Indirect recursions, where function A calls function B and function B calls function A, in such scenario: always better to check whether it's a direct or an Indirect recursion and optimize accordingly. 6.3.4 Indirect Recursion In Indirect recursion, a function calls another function, which in turn calls the original function. This creates a chain of function calls, where each function calls another function, which ultimately leads to the original function being called again. Example void A(int n) { if (n > @) { print#("A called with %d\n", n); B(n-1); + + void B(int n) { if (n> 8) { print#("B called with %d\n", n)5 A(n-1) 3 + + In this example, function A calls function B, and function 8 calls function A, creating a chain of function calls If we call A(3) it will call B(2) , B will call A(1) and A will call 8(0) then 8 will return and A will return and this continues in the same fashion till the n becomes 0. A called with 3 8 called with 2 A called with 1 B called with @ Indirect recursion can be a bit more complex to understand and debug than direct recursion, and it can also lead to stack overflow errors if the recursive calls are not in tail position and not optimized, Narayan Sapkota M.Sc. BiData Structures and Algorithms | Narayan Sapkota M.Sc. As Indirect recursion involve multiple function calls and can be quite complex, it's very important to keep an eye on the recursive calls in the chain and the number of calls being made, So as to avoid any stack overflow errors. It’s always a good idea to check for the termination condition and keep a check on the stack size when working with Indirect recursion. 6.3.5 Nested Recursion Nested recursion is a specific type of recursion where a function calls another recursive function to solve a problem. One example of nested recursion is the function to calculate the n-th Fibonacci number. The Fibonacci sequence is a sequence of numbers where each number is the sum of the two preceding ones, usually starting with 0 and 1. The Fibonacci sequence can be defined recursively as follows: + FO)=0 FQ) © F(a) = F(n-t) + F(n-2) form > 1 int fib(int n) { if (n == 0) return @3 elseif (n == 1) return 13 else return fib(n-1) + fib(n-2); + In this example, the fib function is defined to be recursive. It takes an argument n, and returns the n-th Fibonacci number. The function has two base cases: ifn is 0, it returns 0; ifn is 1, it returns 1 For any other value of n, the function calls itself twice: once with the argument n-1, and once with the argument n-2. This is known as nested recursion, because the function is calling itself within itself. Each recursive call to the function reduces the value of n by 1, until nis 0 or 1, at which point the base case is reached and the recursion stops. The final value returned by the last call to the function is the n-th Fibonacci number. This is a simple example, but nested recursion can also be used to solve more complex problems. Be aware however, that nested recursion can also increase the computational complexity of the problem, so its usage should be used with caution. Narayan Sapkota M.Sc. BiData Structures and Algorithms | Narayan Sapkota M.Sc. 6.3.6 Excessive Recursion Excessive recursion occurs when a function calls itself too many times, leading to a stack overflow. This can happen when the recursion doesn't have a proper exit condition, or the exit condition is not met. Here's an example of a function that uses excessive recutsion in C Example void recurse() { recurse(); // This line calls the recurse() function again, leading to infinite recursion } int main() { recurse(); // This call to recurse() will cause a stack overflow return ; In this example, the recurse() function calls itself indefinitely, causing a stack overflow. Since the call stack keeps growing with each call to recurse(, the program eventually runs out of stack space, resulting in the overflow. To fix this, you would need to add an exit condition to the function that would allow it to stop calling itself. For example: void recurse(int n) { if (n> @) { print#("%d\n", n); recurse(n-1); + Now the recursion will stop when n <= 0, You should also be careful when you are working with infinite recursion on large input as it may lead to crash the program. Here is the corrected version where recursion have the base case void recurse(int n) { if (n> @) { print#("%d\n", n); recurse(n-1); + int main() { recurse(1@); // This calls recurse function to 10 return 0; + In the above example, the recursion will stop after it reaches the value of 0, avoiding stack overflow. Narayan Sapkota M.Sc. |Data Structures and Algorithms | Narayan Sapkota M.Sc 6.4 Recursion vs Iteration The following table summarizes the differences between recursion and iteration. There is a termination con is specified. EIB The termination condition is defined within the recursive function. The code size in recursion is smaller than the code size in iteration. Ifthe recursive function does not meet to a termination condition, it leads to an infinite recursion. There is a chance of system crash in infinite recursion. Itis always applied to functions. Itis slower than iteration. Recursion is generally used where there is no issue of time complexity, and code size requires being small. Ithas high time complexity. ni Ta tng It must update and maintain the stack. It uses more memory as compared to iteration. There is an extensive overhead due to updating and maintaining the stack. In iteration, there is a repeated execution of the set of instructions. In Iteration, loops are used to execute the set of instructions repetitively until the condition is false. The format of iteration _ includes initialization, condition, and increment/decrement of a variable. Here, the termination condition is defined in the definition of the loop. The code size in iteration is larger than the code size in recursion Iteration will be infinite if the control condition of the iteration statement never becomes false. On infinite loop, it repeatedly used CPU cycles. Itis applied to loops. Itis faster than recursion. It is used when we must balance the time complexity against a large code size. The time complexity in iteration is relatively lower. We can calculate its time complexity by finding the no. of cycles being repeated ina loop. There is no utilization of stack. It uses less memory as compared to recursion. There is no overhead in iteration. Narayan Sapkota M.Sc BiData Structures and Algorithms | Narayan Sapkota M.Sc. 6.5 Application of Recursion Some common applications of recursion in computer science include: 1 Tree traversals: Recursion is a natural fit for tree traversals, such as depth-first search (DFS) and breadth-first search (BFS). In both of these algorithms, the current node is processed and then the algorithm recursively visits its children Graph traversals: Recursion is also used in graph traversals, such as DFS and BFS. These algorithms can be implemented using recursion in the same way as tree traversals. Divide and conquer algorithms: Many algorithms, such as merge sort and quick sort, use a divide-and-conquer approach to solve a problem. These algorithms break the problem down into smaller subproblems and recursively solve each of these subproblems. Backtracking: Recursion is commonly used to implement backtracking algorithms, which are used to find all possible solutions to a problem. Examples of backtracking algorithms include the classic "N-Queens problem" and "knight's Tour problem’, Recursive function calls: Recursive function calls are often used for generating sequence, such as the Fibonacci series, which can be defined recursively as F(n) = F(n-1) + F(n-2) Functional programming: In functional programming recursion is used as a way to do iteration, where recursion replaces loops. 6.6 Tower of Hanoi (TOH) Tower of Hanoi is a mathematical puzzle where we have three rods (A, 8, and C) and N disks. Initially, all the disks are stacked in decreasing value of diameter ie, the smallest disk is placed on the top and they are on rod A, The objective of the puzzle is to move the entire stack to another rod (here considered C), obeying the following simple rules: 1 2 Only one disk can be moved at a time. Each move consists of taking the upper disk from one of the stacks and placing it on top of another stack ie, a disk can only be moved if it is the uppermost disk on a stack No disk may be placed on top of a smaller disk. Narayan Sapkota M.Sc. BiData Structures and Algorithms | Narayan Sapkota M.Sc. Towers Smallest largest Note: To clear a concept, play a game following this link https://www.mathsisfun.com/games/towerofhanoi,htm| 6.6.1 [Tower of Hanoi using Recursion The idea is to use the helper node to reach the destination using recursion. Below is the pattern for this problem: ‘© Shift (N-1" disks from ‘A’ to’B’, using C. ‘© Shift last disk from ‘A’ to'C: © Shift 'N-1' disks from 'B’ to 'C’, using A. Narayan Sapkota MSc BiData Structures and Algorithms | Narayan Sapkota M.Sc. N Disks STEP1 . move N-1 _ as Recusively Source Destination STEP2 | last disk | Source“. Auxiliary Destination STEP3 > a a a = . Source Auxiliary | Destination ' move N-1 Recusively 4 STEP4 a Source Auxiliary Destination Narayan Sapkota M.Sc. Hi
You might also like
Data Sructure - Schaum's Series
PDF
80% (20)
Data Sructure - Schaum's Series
462 pages
DST Nirali Publication
PDF
No ratings yet
DST Nirali Publication
85 pages
Data Structure PDF
PDF
No ratings yet
Data Structure PDF
4 pages
Dsa Sppu PDF
PDF
No ratings yet
Dsa Sppu PDF
617 pages
Foundatios of Data Structures by E. Hari, Assistant Professor Dept. of Computer Science and Engineering
PDF
No ratings yet
Foundatios of Data Structures by E. Hari, Assistant Professor Dept. of Computer Science and Engineering
133 pages
Data Structure & Algorithm
PDF
No ratings yet
Data Structure & Algorithm
3 pages
OceanofPDF - Com DATA STRUCTURES Through C PROBLEMS AND S - Rashmi V
PDF
No ratings yet
OceanofPDF - Com DATA STRUCTURES Through C PROBLEMS AND S - Rashmi V
319 pages
CSD3009 - DATA-STRUCTURES-AND-ANALYSIS-OF-ALGORITHMS - LTP - 1.0 - 29 - CSD3009-DATA-STRUCTURES-AND-ANALYSIS-OF-ALGORITHMS - LTP - 1.0 - 1 - Data Structures and Analysis of Algorithms
PDF
No ratings yet
CSD3009 - DATA-STRUCTURES-AND-ANALYSIS-OF-ALGORITHMS - LTP - 1.0 - 29 - CSD3009-DATA-STRUCTURES-AND-ANALYSIS-OF-ALGORITHMS - LTP - 1.0 - 1 - Data Structures and Analysis of Algorithms
3 pages
Data Structures and Algorithms - C and Python
PDF
No ratings yet
Data Structures and Algorithms - C and Python
3 pages
DS Prev
PDF
No ratings yet
DS Prev
6 pages
DS Book
PDF
No ratings yet
DS Book
375 pages
Lesson Plan New
PDF
No ratings yet
Lesson Plan New
6 pages
Data Structures and Algorithms Syllabus
PDF
100% (1)
Data Structures and Algorithms Syllabus
2 pages
Data Structures
PDF
No ratings yet
Data Structures
2 pages
Rafay Abbasi
PDF
No ratings yet
Rafay Abbasi
17 pages
Dsa Part 2
PDF
No ratings yet
Dsa Part 2
18 pages
Data Structures and Algorithms (Python)
PDF
60% (5)
Data Structures and Algorithms (Python)
13 pages
Data Structures and Algorithms Note
PDF
No ratings yet
Data Structures and Algorithms Note
72 pages
Practice Questions For - DSA
PDF
100% (1)
Practice Questions For - DSA
3 pages
Ds Assignment 1
PDF
No ratings yet
Ds Assignment 1
3 pages
DSA Unit 1
PDF
No ratings yet
DSA Unit 1
76 pages
Data Structures by M S
PDF
No ratings yet
Data Structures by M S
227 pages
Introduction To Data Structures Notes
PDF
No ratings yet
Introduction To Data Structures Notes
100 pages
Algo DS Book PDF
PDF
50% (2)
Algo DS Book PDF
525 pages
Microsyllabus Data Structure - Algorithms
PDF
No ratings yet
Microsyllabus Data Structure - Algorithms
8 pages
Report 1 Coderindeed PDF
PDF
No ratings yet
Report 1 Coderindeed PDF
15 pages
Overview of Course
PDF
No ratings yet
Overview of Course
22 pages
Syllabus CSD201
PDF
No ratings yet
Syllabus CSD201
17 pages
Data Structures Lecture Notes
PDF
No ratings yet
Data Structures Lecture Notes
143 pages
DSA Tutorial - 2025
PDF
No ratings yet
DSA Tutorial - 2025
22 pages
Unit I
PDF
No ratings yet
Unit I
36 pages
Data Structure Book by Yandyesh
PDF
No ratings yet
Data Structure Book by Yandyesh
159 pages
Dsa Course File
PDF
No ratings yet
Dsa Course File
161 pages
Data Structures & Algorithms Using C and C++
PDF
No ratings yet
Data Structures & Algorithms Using C and C++
5 pages
Done Classic - Data - Structures - by - D. - Samanta PDF
PDF
No ratings yet
Done Classic - Data - Structures - by - D. - Samanta PDF
99 pages
01 Intro To Course DSA
PDF
No ratings yet
01 Intro To Course DSA
35 pages
DSA Report
PDF
No ratings yet
DSA Report
33 pages
7BCE3C1 Data Structures and Computer Algorithms
PDF
No ratings yet
7BCE3C1 Data Structures and Computer Algorithms
137 pages
DSA Ch1 (Introduction) (Recovered)
PDF
No ratings yet
DSA Ch1 (Introduction) (Recovered)
30 pages
DST Nirali Publication
PDF
No ratings yet
DST Nirali Publication
85 pages
How To Pass Data Structure in One Day
PDF
No ratings yet
How To Pass Data Structure in One Day
20 pages
Data Structures and Algorithms
PDF
No ratings yet
Data Structures and Algorithms
228 pages
Introduction
PDF
No ratings yet
Introduction
15 pages
Dsa Get Set Go
PDF
No ratings yet
Dsa Get Set Go
93 pages
Viva
PDF
No ratings yet
Viva
32 pages
Data Structures Roadmap
PDF
No ratings yet
Data Structures Roadmap
50 pages
1.introduction
PDF
No ratings yet
1.introduction
12 pages
Data Structures & Algorithms - Faisal's Notes
PDF
No ratings yet
Data Structures & Algorithms - Faisal's Notes
3 pages
Rauf Khan DSA Notes
PDF
No ratings yet
Rauf Khan DSA Notes
6 pages
BCA203CO Data Structure Algorithm
PDF
No ratings yet
BCA203CO Data Structure Algorithm
4 pages
DSA Army ICTO
PDF
No ratings yet
DSA Army ICTO
10 pages
Data Structures and Algorithms
PDF
No ratings yet
Data Structures and Algorithms
4 pages
Cse Ug DS
PDF
No ratings yet
Cse Ug DS
2 pages
Sos Midterm Report
PDF
No ratings yet
Sos Midterm Report
18 pages