diff --git a/Linked List/Hard/Add two numbers in linked list/Addsll.cpp b/Linked List/Hard/Add two numbers in linked list/Addsll.cpp new file mode 100644 index 00000000..f610532c --- /dev/null +++ b/Linked List/Hard/Add two numbers in linked list/Addsll.cpp @@ -0,0 +1,116 @@ +/*Copyrights to venkys.io +For more information, visite https://venkys.io"/ + +C++ program to add two numbers in a linked list*/// Stable : Yes +// Inplace : Yes +// Adaptive : Yes + +// Space complexity: (max(N, M)), where N and M are the lengths of the input linked lists. +//The extra space is used to store the resulting linked list. + +//Time Complexity:O(max(N, M)), where N and M are the lengths of the input linked lists. + +#include // It is a standard C++ header file that includes declarations for the standard input/output stream objects like cout, cin, etc. +#include // Includes the Standard Template Library (STL) vector header for dynamic arrays. +#include // Include the header for numeric_limits + +using namespace std; // Using the standard namespace for simplifying code + +// Node class representing a node in a linked list +class Node { +public: + int data; + Node* next = NULL; // Pointer to the next node in the linked list, initially set to NULL + + // Constructor to initialize a node with the given value + Node(int val) { + data = val; + } +}; + +//Function to print the linked list in reverse without arrows +void printReverse(Node* head){ + // Base case: If the current node is NULL (end of the list), return + if (head==NULL){ + return; + } + // Recursive call: Move to the next node in the list + printReverse(head->next); + // Print the data of the current node + cout << head->data << ""; +} + +/*// Function to print the linked list +void print(Node* head) { + Node* temp = head; + while (temp != NULL) { + cout << temp->data << "->"; + temp = temp->next; + } + cout << endl; +} +*/ + +// Function to build a linked list with a single node +Node* buildSingleNode(int val) { + return new Node(val); +} + +// Function to add two numbers represented as linked lists +Node* addTwoNumbers(Node* l1, Node* l2) { + // Create a temporary node to serve as the dummy head of the result linked list + Node* temp = new Node(0); + // Pointer to the head of the result linked list + Node* head = temp; + // Variable to store the carry during addition + int c = 0; + + // Loop until there are elements in either l1 or l2, or there is a carry + while (l1 != NULL || l2 != NULL || c != 0) { + // Add corresponding digits from l1 and l2, along with the carry + if (l1 != NULL) { + c += l1->data; + l1 = l1->next; + } + if (l2 != NULL) { + c += l2->data; + l2 = l2->next; + } + + // Create a new node with the sum % 10 and update carry + temp->next = new Node(c % 10); + c = c / 10; + temp = temp->next; + } + // Return the result linked list starting from the second node (as the first node is the dummy head) + return head->next; +} + +int main() { + int num1, num2; + + // Input the first number + cout << "Enter the first number: "; + cin >> num1; + + // Input the second number + cout << "Enter the second number: "; + cin >> num2; + + // Create linked lists with a single node for each number + Node* l1 = buildSingleNode(num1); + Node* l2 = buildSingleNode(num2); + + // Add the two numbers and print the result + Node* ans = addTwoNumbers(l1, l2); + cout << "Sum of the two numbers: "; + printReverse(ans); + cout << endl; + + // Cleanup: Release memory + delete l1; + delete l2; + delete ans; + + return 0; +} diff --git a/Linked List/Hard/Add two numbers in linked list/Addsll.py b/Linked List/Hard/Add two numbers in linked list/Addsll.py new file mode 100644 index 00000000..aa032d65 --- /dev/null +++ b/Linked List/Hard/Add two numbers in linked list/Addsll.py @@ -0,0 +1,89 @@ +'''Copyrights to venkys.io +For more information, visit https://venkys.io"/ + +Python program to add two numbers in a linked list''' + +# Stable : Yes +# Inplace : Yes +# Adaptive : Yes + +# Space complexity: O(max(N,M)), where N and M are the lengths of input linked lists. + +#Time Complexity: O(max(N,M)), where N and M are the lengths of input linked lists. + +# Constructor method for the Node class +class Node: + def __init__(self,data): + self.data=data # Store the provided data in the 'data' attribute of the node + self.next=None # Initialize the 'next' attribute to None, as this node is not yet connected to another node. + +def printLLReverse(head): + #Function to print linked list in reverse order + stack=[] + # Traverse the linked list and push each node's data onto the stack + while head: + stack.append(head.data) + head=head.next + # Pop each element from the stack and print it in reverse order + while stack: + print(stack.pop(),end="") + # Print a newline to separate the reversed data from the rest of the output + print() + +'''def printLL(head): +#Function to print the linked list + while head: + print(head.data,end="-->") + head=head.next + print()''' + +def buildLL(arr): + #Function to build a linked list from an array + temp=Node(0) + head=temp + for i in arr: + # Create a new node with the current array element + temp.next=Node(i) + # Move the temporary pointer to the newly created node + temp=temp.next + return head.next + +def addTwoNumbers(l1,l2): +#Function to add two numbers represented as linked lists + temp=Node(0) + head=temp + c=0 + # loop until there are elements in either l1,;2 or there is carry. + while l1 or l2 or c: + # add corresponding digits from l1,l2 along with carry + if l1: + c+=l1.data + l1=l1.next + if l2: + c+=l2.data + l2=l2.next + #Create a new node with sum%10 and update carry + temp.next=Node(c%10) + c=c//10 + temp=temp.next + return head.next + + +def main(): + # Prompt the user to enter the first number + print("Enter first number:", end=" ") + num1 = input() + l1 = buildLL([int(x) for x in num1.split()]) + + # Prompt the user to enter the second number + print("Enter Second number:", end=" ") + num2 = input() + l2 = buildLL([int(x) for x in num2.split()]) + + # Print the reverse of the linked list representing the sum (result) + print("Sum of two numbers: ", end=" ") + ans = addTwoNumbers(l1, l2) + printLLReverse(ans) + +if __name__ == "__main__": + main() diff --git a/Linked List/Hard/Add two numbers in linked list/Linkedlistsum.java b/Linked List/Hard/Add two numbers in linked list/Linkedlistsum.java new file mode 100644 index 00000000..dfb4798d --- /dev/null +++ b/Linked List/Hard/Add two numbers in linked list/Linkedlistsum.java @@ -0,0 +1,117 @@ +/*Copyrights to venkys.io +For more information, visit https://venkys.io"/ + +Java program to add two numbers in a linked list*/ + +// Stable : Yes +// Inplace : Yes +// Adaptive :Yes + +// Space complexity: (max(N, M)), where N and M are the lengths of the input linked lists. +//The extra space is used to store the resulting linked list. + +//Time Complexity:O(max(N, M)), where N and M are the lengths of the input linked lists. + +import java.util.Scanner; //Importing scanner class from java.util package for user input + +//Node class representing a node in linked list +class Node{ + int data; + Node next; + + //Constructor to initialize a node with given data + Node(int data){ + this.data=data; + } +} + +public class Linkedlistsum{ + // Function to print the linked list in reverse order + static void printReverse(Node head) { + // Base case: If the current node is null, return + if (head == null) { + return; + } + // Recursive call: Move to the next node and print it in reverse order + printReverse(head.next); + // Print the data of the current node + System.out.print(head.data); + } + + /* This function displays the actual data order stored in linked list + static void print(Node head){ + Node temp=head; + while(temp!=null){ + System.out.print(temp.data+"->"); + temp=temp.next; + } + System.out.println(); + }*/ + + // Function to build a linked list from an array + static Node buildll(int[] arr){ + Node temp=new Node(0); // Create a dummy node to serve as the head of the linked list + Node head=temp; // Store the reference to the head of the linked list + + for(int i=0;i 4 -> 3 + Number 2: 5 -> 6 -> 4 + + ``` + +2. **Addition Process:** + - Start iterating through both linked lists, node by node. + - At each step, add the corresponding digits along with any carry from the previous step. + + ``` + + Explain + Iteration 1: + - Digits: 2 + 5 = 7 (no carry) + - Result: 7 -> None + + Iteration 2: + - Digits: 4 + 6 = 10 (carry 1) + - Result: 7 -> 0 -> None + + Iteration 3: + - Digits: 3 + 4 + 1 (carry from previous step) = 8 (no carry) + - Result: 7 -> 0 -> 8 -> None + + ``` + +3. **Final Result:** + - The final result linked list is (7 → 0 → 8), which represents the number 807. + +### Conclusion: + +Adding two numbers in a single linked list involves iterating through both lists, performing digit-wise addition, and considering any carry that might arise. The resulting linked list represents the sum of the two numbers. + +# Working Principle: + +--- + +### 1. Initialization: + +- **Initialize a Dummy Head:** + - Create a dummy head node to simplify the addition process. This dummy head is not part of the final result but helps in handling edge cases at the head of the resulting linked list. +- **Initialize Pointers:** + - Initialize pointers for the current node in the result, as well as pointers for the current nodes in the two input linked lists (`l1` and `l2`). + +### 2. Iterative Addition: + +- **Iterate Through the Linked Lists:** + - Use a loop to iterate through both linked lists (`l1` and `l2`) until both lists and any carry are exhausted. +- **Extract Digits:** + - Extract the values of the current nodes in both linked lists (`x` from `l1` and `y` from `l2`). If a node is `None`, consider the value as 0. +- **Perform Addition:** + - Add the values of the current nodes along with any carry from the previous step. + - Calculate the sum (`total_sum`) and the carry for the next iteration. +- **Create Result Node:** + - Create a new node with the digit of the current sum and append it to the result linked list. +- **Move to the Next Nodes:** + - Move the pointers to the next nodes in both linked lists (`l1` and `l2`). + +### 3. Finalization: + +- **Handle Any Remaining Carry:** + - After the loop, if there is still a carry, create an additional node with the carry. +- **Return Result:** + - Return the next node of the dummy head, as the dummy head was used to simplify the process and is not part of the final result. + +Conclusion: + +The working principle involves a systematic traversal of the linked lists, digit-wise addition, and careful consideration of carry at each step. The dummy head simplifies the addition process, and the result is a new linked list representing the sum of the two input numbers. The provided Python code blog encapsulates this working principle in the `add_two_numbers` function. + +# Advantages of Addition in Single Linked List: + +--- + +### Advantages of Addition in Single Linked List: + +1. **Dynamic Size:** + - Single linked lists allow for dynamic sizing. Elements can be added or removed without the need to predefine the size of the data structure. This flexibility is advantageous when dealing with varying amounts of data. +2. **Efficient Insertion and Deletion:** + - Adding elements to or removing elements from a single linked list is more efficient compared to arrays. Insertion and deletion operations involve updating references, which can be done in constant time if the position of the node is known. +3. **Memory Efficiency:** + - Single linked lists can be more memory-efficient than arrays, especially when the size of the data structure changes frequently. This is because nodes can be allocated and deallocated individually without the need for contiguous memory blocks. +4. **No Pre-allocation of Memory:** + - Unlike arrays, there's no need to pre-allocate memory for a single linked list. Memory is allocated on-the-fly as nodes are added, which is particularly beneficial when the size of the data structure is unknown or varies. +5. **Ease of Implementation:** + - Implementing addition in a single linked list is often simpler compared to dynamic arrays or other complex data structures. The structure of a linked list allows for straightforward traversal and manipulation. +6. **Support for Infinite Size:** + - In theory, a single linked list can support an infinite number of elements. As long as there is available memory, nodes can be added to the list, making it suitable for scenarios where the size of the data set is not known in advance. +7. **No Wasted Memory:** + - Memory is used more efficiently in a single linked list compared to dynamic arrays, where memory needs to be pre-allocated. In a linked list, memory is allocated precisely for the elements that are present, reducing wasted space. +8. **Simplified Algorithm Design:** + - Algorithms for addition or other operations on single linked lists can be simplified due to the sequential nature of the structure. There's no need to worry about shifting elements or resizing memory blocks, as is often the case with arrays. +9. **Ease of Rearrangement:** + - Rearranging elements in a single linked list is relatively straightforward. It involves updating the `next` references, allowing for efficient reordering of elements without the need to move large chunks of memory. +10. **Adaptability to Changing Requirements:** + - Single linked lists are well-suited for scenarios where the data structure requirements may change frequently. They provide adaptability to dynamic data sets and can accommodate modifications without significant overhead. + +In summary, the advantages of performing addition in a single linked list lie in its dynamic nature, efficient insertion and deletion, memory efficiency, and adaptability to varying data sizes. These characteristics make single linked lists a suitable choice for certain applications and algorithmic scenarios. + +# Disadvantages of Adding two numbers in Single Linked List : + +--- + +1. **Sequential Access:** + - Single linked lists require sequential access to reach a specific node. This can be inefficient when direct access to elements is needed, as it involves traversing the list from the head to the desired node. +2. **Memory Overhead:** + - Each node in a single linked list requires additional memory to store the data and the reference to the next node. This can result in higher memory overhead compared to contiguous memory structures like arrays. +3. **No Random Access:** + - Unlike arrays, single linked lists do not support direct access to elements by index. Accessing an element requires traversing the list from the head, which can be inefficient for certain operations. +4. **Increased Cache Misses:** + - Due to non-contiguous memory allocation, traversing a single linked list may result in increased cache misses compared to arrays. This can impact the performance, especially in scenarios where memory access patterns are crucial. +5. **Traversal Overhead:** + - Traversing a linked list involves following references from one node to the next. This introduces additional traversal overhead, which can impact the efficiency of algorithms, particularly when dealing with large datasets. +6. **Limited Parallelism:** + - Operations on single linked lists may have limited parallelism, as each operation often depends on the completion of the previous one. This can be a disadvantage in scenarios where parallel processing is critical. +7. **Not Cache-Friendly:** + - The non-contiguous nature of linked lists can lead to poor cache locality, resulting in less efficient use of the CPU cache. This can adversely affect the performance of certain operations. +8. **Extra Storage for References:** + - Storing references to the next node in addition to the actual data consumes extra storage. In scenarios with tight memory constraints, this additional overhead may be a drawback. +9. **Complexity in Reverse Traversal:** + - Performing operations in reverse order, such as traversing the list from the tail to the head, can be less efficient and more complex than forward traversal. +10. **Potential for Memory Fragmentation:** + - Frequent node allocation and deallocation in a linked list may lead to memory fragmentation, especially in languages without automatic memory management. This fragmentation can affect the overall system performance. + +# Real World Scenarios of Adding two numbers in a Single Linked List: + +--- + +The addition of two numbers in a single linked list can be encountered in various real-world scenarios. + +1. **Arbitrary Precision Arithmetic:** + - In cryptography, numerical calculations, or any scenario where precision matters, addition of large numbers might be performed using linked lists. This is especially true when the numbers are too large to be stored in standard data types like integers. +2. **Financial Transactions:** + - In financial applications, when dealing with currency or accounting, it's common to represent monetary values with linked lists. Adding transaction amounts or performing financial calculations may involve adding two numbers stored in linked lists. +3. **Scientific Computing:** + - Scientific simulations or computations might involve working with numbers of varying precision. Linked lists can be used to represent and manipulate these numbers, and adding them may be a part of the simulation process. +4. **Representation of Polynomials:** + - Polynomials can be represented using linked lists, where each node represents a term in the polynomial. Adding two polynomials involves adding corresponding terms, and the result can be represented as a new linked list. +5. **Large Data Processing:** + - In data processing applications dealing with very large datasets, the use of linked lists might be more efficient due to their dynamic nature. Adding values or performing calculations on large datasets can be more manageable with linked lists. +6. **Network Packet Processing:** + - In networking, linked lists may be used to represent and process data packets. When aggregating or combining information from multiple packets, the addition of numerical values might be necessary. +7. **Symbolic Mathematics:** + - Systems that deal with symbolic mathematics, such as computer algebra systems, might use linked lists to represent mathematical expressions. Adding two expressions or symbolic numbers involves manipulating the linked list structure. +8. **Resource Management in Operating Systems:** + - Operating systems often manage resources using linked data structures. When tracking resource usage or managing quotas, adding resource values in a linked list can be part of the resource management algorithms. +9. **Game Development:** + - In game development, especially in simulations or strategy games, linked lists might be employed to manage game resources or perform calculations involving various attributes. Adding numerical values can be a common operation in such scenarios. +10. **GPS Navigation:** + - In GPS navigation systems, coordinates and distances might be stored using linked lists. Calculations involving these geographical values, such as adding distances or finding the next location, could involve adding two numbers stored in linked lists. + +# Code in Python: + +``` +'''Copyrights to venkys.io +For more information, visite https://venkys.io"/ + +Python program to add two numbers in a linked list''' + +# Stable : Yes +# Inplace : Yes +# Adaptive : Yes + +# Space complexity: O(max(N,M)), where N and M are the lengths of input linked lists. + +#Time Complexity: O(max(N,M)), where N and M are the lengths of input linked lists. + +# Constructor method for the Node class +class Node: + def __init__(self,data): + self.data=data # Store the provided data in the 'data' attribute of the node + self.next=None # Initialize the 'next' attribute to None, as this node is not yet connected to another node. + +def printLLReverse(head): + #Function to print linked list in reverse order + stack=[] + # Traverse the linked list and push each node's data onto the stack + while head: + stack.append(head.data) + head=head.next + # Pop each element from the stack and print it in reverse order + while stack: + print(stack.pop(),end="") + # Print a newline to separate the reversed data from the rest of the output + print() + +'''def printLL(head): +#Function to print the linked list + while head: + print(head.data,end="-->") + head=head.next + print()''' + +def buildLL(arr): + #Function to build a linked list from an array + temp=Node(0) + head=temp + for i in arr: + # Create a new node with the current array element + temp.next=Node(i) + # Move the temporary pointer to the newly created node + temp=temp.next + return head.next + +def addTwoNumbers(l1,l2): +#Function to add two numbers represented as linked lists + temp=Node(0) + head=temp + c=0 + # loop until there are elements in either l1,;2 or there is carry. + while l1 or l2 or c: + # add corresponding digits from l1,l2 along with carry + if l1: + c+=l1.data + l1=l1.next + if l2: + c+=l2.data + l2=l2.next + #Create a new node with sum%10 and update carry + temp.next=Node(c%10) + c=c//10 + temp=temp.next + return head.next + +def main(): + # Prompt the user to enter the first number + print("Enter first number:", end=" ") + num1 = input() + l1 = buildLL([int(x) for x in num1.split()]) + + # Prompt the user to enter the second number + print("Enter Second number:", end=" ") + num2 = input() + l2 = buildLL([int(x) for x in num2.split()]) + + # Print the reverse of the linked list representing the sum (result) + print("Sum of two numbers: ", end=" ") + ans = addTwoNumbers(l1, l2) + printLLReverse(ans) + +if __name__ == "__main__": + main() +``` + +1. The **`Node`** class is defined to create nodes for the linked list. Each node has a **`data`** attribute representing a digit and a **`next`** attribute pointing to the next node in the list. +2. The **`printLLReverse`** function is defined to print the linked list. It takes the head of the linked list as an argument and traverses the list in reverse order, printing each node's data. +3. The **`buildLL`** function is defined to build a linked list from an input array. It creates a dummy node, iterates through the array, and appends nodes with array elements as data to the linked list. +4. The **`addTwoNumbers`** function takes two linked lists representing two numbers and returns a new linked list representing their sum. It uses a temporary dummy node (**`head`**) to build the result linked list. +5. Inside the **`addTwoNumbers`** function: + - A temporary node **`temp`** is initialized as the head of the result linked list. + - A variable **`c`** is initialized to 0, representing the carry. + - A while loop runs until there are elements in either of the input linked lists (**`l1`** or **`l2`**) or there is a carry (**`c`**). + - Inside the loop, the code adds the corresponding digits from **`l1`** and **`l2`**, along with the carry, and updates **`c`** and the result digit in the new linked list. + - The carry is updated as the floor division of the sum by 10. + - The new digit is appended to the result linked list. + - Move to the next node in the result linked list. + +# Code in C++: + +``` +/*Copyrights to venkys.io +For more information, visite https://venkys.io"/ + +C++ program to add two numbers in a linked list*/// Stable : Yes +// Inplace : Yes +// Adaptive : Yes + +// Space complexity: (max(N, M)), where N and M are the lengths of the input linked lists. +//The extra space is used to store the resulting linked list. + +//Time Complexity:O(max(N, M)), where N and M are the lengths of the input linked lists. + +#include // It is a standard C++ header file that includes declarations for the standard input/output stream objects like cout, cin, etc. +#include // Includes the Standard Template Library (STL) vector header for dynamic arrays. +#include // Include the header for numeric_limits + +using namespace std; // Using the standard namespace for simplifying code + +// Node class representing a node in a linked list +class Node { +public: + int data; + Node* next = NULL; // Pointer to the next node in the linked list, initially set to NULL + + // Constructor to initialize a node with the given value + Node(int val) { + data = val; + } +}; + +//Function to print the linked list in reverse without arrows +void printReverse(Node* head){ + // Base case: If the current node is NULL (end of the list), return + if (head==NULL){ + return; + } + // Recursive call: Move to the next node in the list + printReverse(head->next); + // Print the data of the current node + cout << head->data << ""; +} + +/*// Function to print the linked list +void print(Node* head) { + Node* temp = head; + while (temp != NULL) { + cout << temp->data << "->"; + temp = temp->next; + } + cout << endl; +} +*/ + +// Function to build a linked list with a single node +Node* buildSingleNode(int val) { + return new Node(val); +} + +// Function to add two numbers represented as linked lists +Node* addTwoNumbers(Node* l1, Node* l2) { + // Create a temporary node to serve as the dummy head of the result linked list + Node* temp = new Node(0); + // Pointer to the head of the result linked list + Node* head = temp; + // Variable to store the carry during addition + int c = 0; + + // Loop until there are elements in either l1 or l2, or there is a carry + while (l1 != NULL || l2 != NULL || c != 0) { + // Add corresponding digits from l1 and l2, along with the carry + if (l1 != NULL) { + c += l1->data; + l1 = l1->next; + } + if (l2 != NULL) { + c += l2->data; + l2 = l2->next; + } + + // Create a new node with the sum % 10 and update carry + temp->next = new Node(c % 10); + c = c / 10; + temp = temp->next; + } + // Return the result linked list starting from the second node (as the first node is the dummy head) + return head->next; +} + +int main() { + int num1, num2; + + // Input the first number + cout << "Enter the first number: "; + cin >> num1; + + // Input the second number + cout << "Enter the second number: "; + cin >> num2; + + // Create linked lists with a single node for each number + Node* l1 = buildSingleNode(num1); + Node* l2 = buildSingleNode(num2); + + // Add the two numbers and print the result + Node* ans = addTwoNumbers(l1, l2); + cout << "Sum of the two numbers: "; + printReverse(ans); + cout << endl; + + // Cleanup: Release memory + delete l1; + delete l2; + delete ans; + + return 0; +} +``` + +# Code in Java: + +``` +/*Copyrights to venkys.io +For more information, visit https://venkys.io"/ + +Java program to add two numbers in a linked list*/ + +// Stable : Yes +// Inplace : Yes +// Adaptive :Yes + +// Space complexity: (max(N, M)), where N and M are the lengths of the input linked lists. +//The extra space is used to store the resulting linked list. + +//Time Complexity:O(max(N, M)), where N and M are the lengths of the input linked lists. + +import java.util.Scanner; //Importing scanner class from java.util package for user input + +//Node class representing a node in linked list +class Node{ + int data; + Node next; + + //Constructor to initialize a node with given data + Node(int data){ + this.data=data; + } +} + +public class Linkedlistsum{ + // Function to print the linked list in reverse order + static void printReverse(Node head) { + // Base case: If the current node is null, return + if (head == null) { + return; + } + // Recursive call: Move to the next node and print it in reverse order + printReverse(head.next); + // Print the data of the current node + System.out.print(head.data); + } + + /* This function displays the actual data order stored in linked list + static void print(Node head){ + Node temp=head; + while(temp!=null){ + System.out.print(temp.data+"->"); + temp=temp.next; + } + System.out.println(); + }*/ + + // Function to build a linked list from an array + static Node buildll(int[] arr){ + Node temp=new Node(0); // Create a dummy node to serve as the head of the linked list + Node head=temp; // Store the reference to the head of the linked list + + for(int i=0;i3) - Swap needed. Array=[4,3,6,7,9] +10. (6<7) and (7<9) no swap needed. +11. Third Pass: (4>3) Swap needed. Array=[3,4,6,7,9] +12. The array is sorted by this time. and it would compare all the other elements to check whether they are in sorted order to complete the third pass. + +# Advantages of Bubble Sort: + +--- + +1. **Simplicity:** + - Bubble Sort is one of the simplest sorting algorithms to understand and implement. This makes it an excellent educational tool for introducing the concept of sorting to beginners and students. +2. **In-Place Sorting:** + - Bubble Sort is an in-place sorting algorithm, meaning it doesn't require additional memory space to perform the sorting. This can be advantageous in situations where memory is a critical resource. +3. **Adaptive:** + - It is adaptive, which means that it performs well on partially sorted datasets. If a dataset is already partially sorted, Bubble Sort can have a linear time complexity in the best-case scenario. +4. **Stable Sorting:** + - Bubble Sort is a stable sorting algorithm. Stability in sorting means that the relative order of equal elements is preserved in the sorted output. This can be important in certain applications. +5. **Ease of Implementation:** + - The algorithm is straightforward to implement, and the logic is easy to understand. It consists of a few basic steps, making it accessible for teaching purposes and for situations where a simple sorting algorithm is sufficient. +6. **Small Dataset Sorting:** + - For very small datasets or datasets that are nearly sorted, the overhead of more complex algorithms may outweigh the benefits. In such cases, the simplicity of Bubble Sort might make it a reasonable choice. + +# Disadvantages of Bubble Sort: + +--- + +1. **Inefficiency for Large Datasets:** + - Bubble Sort has a worst-case and average-case time complexity of O(n^2), making it highly inefficient for sorting large datasets. As the size of the dataset increases, the number of comparisons and swaps grows quadratically. +2. **Lack of Adaptability:** + - The algorithm doesn't adapt well to the existing order of elements. Even if the array is partially sorted, Bubble Sort performs the same number of comparisons and swaps as it would for a completely unsorted array. +3. **Poor Performance on Reverse-Ordered Data:** + - In its basic form, Bubble Sort performs poorly on datasets that are in reverse order. In such cases, it requires a large number of passes to bring the largest element to the correct position. +4. **Unstable Sorting:** + - While being stable can be an advantage in certain situations, Bubble Sort's stability comes at the cost of additional comparisons. This can make it less efficient compared to other stable sorting algorithms. +5. **Redundant Passes:** + - Bubble Sort continues to make passes through the entire list, even if the list is already sorted. This leads to unnecessary iterations and makes the algorithm less efficient. +6. **Not Suitable for Real-Time Applications:** + - Due to its quadratic time complexity, Bubble Sort is generally not suitable for real-time applications where quick responses are required. +7. **Limited Use in Professional Software Development:** + - In professional software development, where efficiency is crucial, Bubble Sort is rarely used for sorting large datasets. More advanced sorting algorithms like QuickSort or MergeSort are preferred. +8. **Comparisons and Swaps Overhead:** + - The algorithm involves a significant number of comparisons and swaps, even for small datasets. This overhead becomes impractical for larger datasets and is less efficient than more sophisticated algorithms. + +# Real Scenarios of Bubble Sort: + +--- + +1. **Educational Purposes:** + - Bubble Sort is often used as an introductory algorithm to teach students the fundamental concepts of sorting algorithms. Its simplicity makes it an excellent starting point for beginners to understand the basic principles of sorting. +2. **Small Datasets:** + - In situations where the dataset is small and efficiency is not a critical factor, Bubble Sort can be employed. The overhead associated with more complex algorithms might outweigh the benefits in such cases. +3. **Partially Sorted Data:** + - If the data is already partially sorted or nearly sorted, Bubble Sort can perform reasonably well in practice. Its adaptive nature in these scenarios can make it a suitable choice. +4. **Embedded Systems with Limited Resources:** + - In environments with limited computational resources, such as certain embedded systems, Bubble Sort might be chosen due to its simplicity and low memory requirements. +5. **Sorting Nearly Sorted Lists:** + - When dealing with lists that are almost sorted, Bubble Sort can require fewer swaps compared to more sophisticated algorithms. In scenarios where minimizing swaps is crucial, Bubble Sort might be considered. +6. **In Situations with Strict Memory Constraints:** + - If the memory is a significant constraint and in-place sorting is required, Bubble Sort can be a suitable choice as it doesn't require additional memory space. +7. **Toy or Prototype Applications:** + - Bubble Sort may be used in situations where a quick-and-dirty solution is needed for a small-scale or temporary application, and the simplicity of the algorithm is more advantageous than its inefficiency. + +# Python code for Bubble Sort: + +--- + +``` +# Copyrights to venkys.io +# For more programs visit venkys.io +# Python program for Bubble sort + +# Stable: Yes +# Inplace: Yes +# Adaptive: No +# Time Complexity: Best case - O(n), Average and worst case - O(n^2) +# Space Complexity: O(1) + +# Function to perform Bubble Sort on given array +''' +Parameters: + - array (list): The list to be sorted. + +Returns: + - list: The sorted list. +''' +def bubbleSort(array): + n = len(array) + + # Traverse through all elements + for i in range(n): + # Last i elements are already sorted, so we don't check them + for j in range(0, n - i - 1): + # Compare adjacent elements, Swap if the elements found is greater than the next element + if array[j] > array[j + 1]: + array[j], array[j + 1] = array[j + 1], array[j] + + # The sorted array is returned + return array + +def main(): + try: + # Taking input from the user + array = list(map(int, input("Enter the array elements separated by space:").split())) + + # Check if the array is empty + if not array: + print("Array is empty. No elements to sort.") + return + + # Calling the bubble Sort Function + sorted_array = bubbleSort(array) + + # Printing the sorted array + print("Sorted Array:", sorted_array) + + except ValueError as ve: + print(f"Error: {ve}") + +if __name__ == "__main__": + main() +``` + +- Bubble Sort is not adaptive. Its performance remains the same regardless of the initial order of elements. It performs the same number of comparisons and swaps in every pass through the array. + +### **Explanation:** + +**def bubbleSort(array):** + +This defines a function called `bubbleSort` that takes a single argument, `array`. + +**for i in range(len(array)):** + +A `for` loop is used to iterate through each element in the `array`. The loop variable `i` is used to keep track of the current element being processed. + +**for j in range(i,len(array)-1-i):** + +A nested `for` loop is used within the `bubbleSort` function to compare adjacent elements in the `array`. The outer variable `i` is used to keep track of the current element being processed, and the inner variable `j` is used to compare adjacent elements starting from the next element after the one currently being processed. The expression `len(array)-1-i` is used to subtract the current index (`i`) from the total length of the array (`len(array)`). + +**if array[j]>array[j+1]: array[j],array[j+1]=array[j+1],array[j]** + +An `if` statement is used to compare adjacent elements in the `array`. If the element at index `j` is greater than the element at index `j+1`, the two elements are swapped using the tuple unpacking assignment operator `=`. + +### Example Test Cases: + +1. **Basic Test Case:** + - Input: **`5 2 9 1 5`** + - Output: **`Sorted Array: [1, 2, 5, 5, 9]`** +2. **Empty Array Test Case:** + - Input: (empty array) + - Output: **`Array is empty. No elements to sort.`** + - Explanation: The program correctly handles the case when the input array is empty. +3. **Already Sorted Test Case:** + - Input: **`1 2 3 4 5`** + - Output: **`Sorted Array: [1, 2, 3, 4, 5]`** + +# C++ code for Bubble Sort: + +--- + +```cpp +/*Copyrights to venkys.io*/ +/*For more programs visit venkys.io */ +/*C++ program for Bubble sort*/ +//Stable: Yes +//Inplace: Yes +//Adaptive: No +//Time Complexity: Best case - O(n), Average and worst case - O(n^2) +//Space Complexity: O(1) + +#include +// Include the input/output stream header file + +using namespace std; +// Namespace identifies the code is part of the standard library + +void swap(int array[], int i, int j) +// Swapping function to swap two elements when compared adjacently through a temporary variable 'temp' +{ + int temp = array[i]; + array[i] = array[j]; + array[j] = temp; +} + +// Function to perform bubble sort on an array +void bubbleSort(int array[], int n) +{ + // Check for null or negative array size + if (array == NULL || n <= 0) + { + cerr << "Error: Invalid array size or null pointer. Exiting.\n"; + return; + } + + // Outer loop: Iterate through each element in the array (except the last one) + for (int i = 0; i < n - 1; i++) + { + // Inner loop: Compare and swap adjacent elements to move the largest element to the end + for (int j = 0; j < n - i - 1; j++) + { + // Check for null pointer in array + if (array == NULL) + { + cerr << "Error: Null pointer in array. Exiting.\n"; + return; + } + + // Check if the current element is greater than the next element + if (array[j] > array[j + 1]) + { + // Swap the current and next elements if they are in the wrong order + swap(array, j, j + 1); + } + } + } + + // Display the sorted array + cout << "Sorted Array: "; + for (int k = 0; k < n; k++) + { + cout << array[k] << " "; // Print each element of the sorted array + } + cout << endl; // Move to the next line after printing the sorted array +} + +int main() +{ + // Prompt the user to enter the size of the array + cout << "Enter the size of the array: "; + int n; // Declare a variable 'n' to store the size of the array + + // Check for invalid input (non-numeric or negative size) + if (!(cin >> n) || n <= 0) + { + cerr << "Error: Invalid input for array size. Exiting.\n"; + return 1; + } + + // Dynamically allocate memory for an integer array of size 'n' + int *array = new int[n]; + + // Prompt the user to enter the elements of the array + cout << "Enter the elements of the array: "; + // Loop to read 'n' elements and store them in the dynamically allocated array + for (int i = 0; i < n; i++) + { + // Check for invalid input (non-numeric) + if (!(cin >> array[i])) + { + cerr << "Error: Invalid input for array element. Exiting.\n"; + delete[] array; // Free dynamically allocated memory before exiting + return 1; + } + } + + // Calling the bubble Sort function to sort the array + bubbleSort(array, n); + + delete[] array; // Freeing allocated memory + + return 0; +} +``` + +### Example Test Cases: + +**Test case 1: Normal Input** +Enter the size of the array: 5 +Enter the elements of the array: 3 1 5 4 2 + +Output: +Sorted Array: 1 2 3 4 5 + +**Test case 2: Empty Array** +Enter the size of the array: 0 + +Output: +Error: Invalid array size or null pointer. Exiting. + +**Test case 3: Non-Numeric Input for Array Size** +Enter the size of the array: abc + +Output: +Error: Invalid input for array size. Exiting. + +# Java code for Bubble sort: + +--- + +```java +/*Copyrights to venkys.io*/ +/*For more programs visit venkys.io */ +/*Java program for Bubble sort*/ + +//Stable: Yes +//Inplace: Yes +//Adaptive: No +//Time Complexity: Best case - O(n), Average and worst case - O(n^2) +//Space Complexity: O(1) + +import java.util.InputMismatchException; // Import the InputMismatchException class for handling input errors +import java.util.Scanner; // Importing the Scanner class from java.util package for user input +public class bubbleSort{// Declaration of the bubbleSort class + public static void VSDsort(int n,int[] a) + { + // Declaration of a static method named VSDsort that takes an integer n and an integer array a as parameters + // Null check for the array + if (a == null) { + System.out.println("Error: Input array is null."); + return; + } + for(int i=0;ia[j+1]) { + // Checking if the current element is greater than the next element + VSDswapElementsAt(a,j+1,j);} // Calling a method to swap elements if necessary + } + } + } + + // Method to swap elements at two specified positions in the array + public static void VSDswapElementsAt(int[] a,int t1,int t2) + { + { + int temp = a[t1]; + a[t1] = a[t2]; + a[t2] = temp; + + } + } + //Function to print output + public static void VSDprintOutput(int n,int a[]) { + // Null check for the array + if (a == null) { + System.out.println("Error: Input array is null."); + return; + } + System.out.println("The sorted order is:"); + for(int i=0;ia[j+1]) { + // Checking if the current element is greater than the next element + VSDswapElementsAt(a,j+1,j);} // Calling a method to swap elements if necessary + } + } + } + + // Method to swap elements at two specified positions in the array + public static void VSDswapElementsAt(int[] a,int t1,int t2) + { + { + int temp = a[t1]; + a[t1] = a[t2]; + a[t2] = temp; + + } + } + //Function to print output + public static void VSDprintOutput(int n,int a[]) { + // Null check for the array + if (a == null) { + System.out.println("Error: Input array is null."); + return; + } + System.out.println("The sorted order is:"); + for(int i=0;i +// Include the input/output stream header file + +using namespace std; +// Namespace identifies the code is part of the standard library + +void swap(int array[], int i, int j) +// Swapping function to swap two elements when compared adjacently through a temporary variable 'temp' +{ + int temp = array[i]; + array[i] = array[j]; + array[j] = temp; +} + +// Function to perform bubble sort on an array +void bubbleSort(int array[], int n) +{ + // Check for null or negative array size + if (array == NULL || n <= 0) + { + cerr << "Error: Invalid array size or null pointer. Exiting.\n"; + return; + } + + // Outer loop: Iterate through each element in the array (except the last one) + for (int i = 0; i < n - 1; i++) + { + // Inner loop: Compare and swap adjacent elements to move the largest element to the end + for (int j = 0; j < n - i - 1; j++) + { + // Check for null pointer in array + if (array == NULL) + { + cerr << "Error: Null pointer in array. Exiting.\n"; + return; + } + + // Check if the current element is greater than the next element + if (array[j] > array[j + 1]) + { + // Swap the current and next elements if they are in the wrong order + swap(array, j, j + 1); + } + } + } + + // Display the sorted array + cout << "Sorted Array: "; + for (int k = 0; k < n; k++) + { + cout << array[k] << " "; // Print each element of the sorted array + } + cout << endl; // Move to the next line after printing the sorted array +} + +int main() +{ + // Prompt the user to enter the size of the array + cout << "Enter the size of the array: "; + int n; // Declare a variable 'n' to store the size of the array + + // Check for invalid input (non-numeric or negative size) + if (!(cin >> n) || n <= 0) + { + cerr << "Error: Invalid input for array size. Exiting.\n"; + return 1; + } + + // Dynamically allocate memory for an integer array of size 'n' + int *array = new int[n]; + + // Prompt the user to enter the elements of the array + cout << "Enter the elements of the array: "; + // Loop to read 'n' elements and store them in the dynamically allocated array + for (int i = 0; i < n; i++) + { + // Check for invalid input (non-numeric) + if (!(cin >> array[i])) + { + cerr << "Error: Invalid input for array element. Exiting.\n"; + delete[] array; // Free dynamically allocated memory before exiting + return 1; + } + } + + // Calling the bubble Sort function to sort the array + bubbleSort(array, n); + + delete[] array; // Freeing allocated memory + + return 0; +} diff --git a/Sorting/Easy/Bubble Sort/bubblesort.py b/Sorting/Easy/Bubble Sort/bubblesort.py new file mode 100644 index 00000000..9f29ab6d --- /dev/null +++ b/Sorting/Easy/Bubble Sort/bubblesort.py @@ -0,0 +1,54 @@ +# Copyrights to venkys.io +# For more programs visit venkys.io +# Python program for Bubble sort + +# Stable: Yes +# Inplace: Yes +# Adaptive: No +# Time Complexity: Best case - O(n), Average and worst case - O(n^2) +# Space Complexity: O(1) + +# Function to perform Bubble Sort on given array +''' +Parameters: + - array (list): The list to be sorted. + +Returns: + - list: The sorted list. +''' +def bubbleSort(array): + n = len(array) + + # Traverse through all elements + for i in range(n): + # Last i elements are already sorted, so we don't check them + for j in range(0, n - i - 1): + # Compare adjacent elements, Swap if the elements found is greater than the next element + if array[j] > array[j + 1]: + array[j], array[j + 1] = array[j + 1], array[j] + + # The sorted array is returned + return array + + +def main(): + try: + # Taking input from the user + array = list(map(int, input("Enter the array elements separated by space:").split())) + + # Check if the array is empty + if not array: + print("Array is empty. No elements to sort.") + return + + # Calling the bubble Sort Function + sorted_array = bubbleSort(array) + + # Printing the sorted array + print("Sorted Array:", sorted_array) + + except ValueError as ve: + print(f"Error: {ve}") + +if __name__ == "__main__": + main() diff --git a/Sorting/Easy/Insertion Sort/InsertionSort.java b/Sorting/Easy/Insertion Sort/InsertionSort.java new file mode 100644 index 00000000..13b89576 --- /dev/null +++ b/Sorting/Easy/Insertion Sort/InsertionSort.java @@ -0,0 +1,100 @@ +/* Copyrights to venkys.io +For more information, visit https://venkys.io */ +//Java program to sort a given array in order using Insertion sort algorithm.*/ + +// Stable : Yes +// Inplace : Yes +// Adaptive : Yes + +// Space complexity: O(1) + +//Time Complexity:O(n^2) in the worst-case scenario, and O(n) in the best-case scenario. + +import java.util.InputMismatchException; // Importing InputMismatchException class for handling input errors +import java.util.Scanner; // Importing scanner class from java.util package for user input + +public class InsertionSort { + + // Function to perform Insertion Sort on the given array + public static void insertionSort(int[] array) { + int n = array.length; + // Traverse through each element of the array + for (int i = 1; i < n; ++i) { + int key = array[i];// Store the current element to be inserted + int j = i - 1; + // Move elements greater than key to the right until a smaller or equal element is found, + // or until the beginning of the array is reached. + while (j >= 0 && array[j] > key) { + array[j + 1] = array[j]; // Shift the current element to the right, creating space for key. + j = j - 1;// Move to the previous position in the array to compare and potentially shift again. + } + array[j + 1] = key; // Insert the stored element at its correct position + } + } + + + // Function to print the elements of the array + public static void printArray(int[] array) { + int n = array.length; + for (int i = 0; i < n; ++i) + System.out.print(array[i] + " "); + System.out.println(); + } + + public static void main(String[] args) { + Scanner scanner = new Scanner(System.in); + + try { + // Input the size of the array + Integer n = null; + // Keep prompting the user until a valid positive integer is entered for the array size + while (n == null || n <= 0) { + System.out.print("Enter the size of the array: "); + try { + // Attempt to read an integer from the user input + n = scanner.nextInt(); + // Check if the entered size is not positive + if (n <= 0) { + System.out.println("Invalid size. Please enter a positive integer."); + } + } catch (InputMismatchException e) { + // Handle the case where a non-integer value is entered + System.out.println("Invalid input. Please enter a valid integer."); + scanner.nextLine(); // Clear the buffer to prevent an infinite loop + } + } + // Create an array to store the elements of the array. + int[] array = new int[n]; + + // Prompt the user to enter the elements of the array. + System.out.println("Enter the elements of the array:"); + // Iterate through each element of the array and input values from the user. + for (int i = 0; i < n; i++) { + // Use a loop to handle invalid input until a valid integer is entered. + while (true) { + if (scanner.hasNextInt()) { + // If the entered value is an integer, assign it to the array. + array[i] = scanner.nextInt(); + break; // Exit the loop as a valid integer is obtained. + } else { + // Display an error message for invalid input and clear the buffer. + System.out.println("Invalid input. Please enter valid integers."); + scanner.nextLine(); // Clear the buffer to avoid an infinite loop. + } + } + } + + // Perform Insertion Sort + insertionSort(array); + + // Print the sorted array + System.out.println("Sorted Array:"); + printArray(array); + } finally { + // Close the scanner to avoid resource leak + if (scanner != null) { + scanner.close(); + } + } + } +} diff --git a/Sorting/Easy/Insertion Sort/README.md b/Sorting/Easy/Insertion Sort/README.md new file mode 100644 index 00000000..5c465bb5 --- /dev/null +++ b/Sorting/Easy/Insertion Sort/README.md @@ -0,0 +1,472 @@ +# Introduction to Insertion Sort: + +--- + +Insertion sort is a simple sorting algorithm that builds the final sorted array or list one item at a time. It is an in-place comparison-based algorithm that works by dividing the input list into two parts: the sorted part and the unsorted part. The algorithm iterates over the unsorted part, selecting one element at a time and inserting it into the correct position in the sorted part. This process is repeated until the entire list is sorted. + +Due to its simplicity and ease of implementation, insertion sort is commonly used in educational contexts to teach the concept of sorting algorithms and is also utilized in certain scenarios where the dataset is expected to be nearly sorted or very small in size. + +# What is an In-place comparison based Sort? + +--- + +An in-place comparison-based algorithm is a sorting algorithm that rearranges the elements of a list using only a constant amount of additional memory space, regardless of the size of the input. In other words, it operates directly on the input data without requiring any auxiliary data structures proportional to the input size. + +In the context of sorting algorithms, "in-place" means that the algorithm doesn't create a separate copy of the input list to perform the sorting. Instead, it rearranges the elements within the original list itself. + +# Understanding Insertion Sort through an Example: + +--- + +Let's take the array [5, 2, 4, 6, 1, 3] as an example. + +Step 1: Initial State + +- Original Array: [5, 2, 4, 6, 1, 3] +- Sorted (Initial): [] + +No Sorting is needed for element with index 0 as it is the first element. + +Step 2: First Pass (i=1) + +- We start with the second element (index 1) which is 2. +- We compare 2 with the elements to its left (5 in this case) and swap them if necessary, resulting in [2, 5, 4, 6, 1, 3]. +- Here sorted part is [2,5] and unsorted part is [4,6,1,3]; original array is [2,5,4,6,1,3] + +Step 3: Second Pass (i=2) + +- Now, we consider the third element (index 2) which is 4. +- 4 is compared with 5 and since 4 is less than 5, we shift 5 to the right and insert 4 in its place: [2, 4, 5, 6, 1, 3]. +- sorted part [2,4,5], unsorted part [6,1,3], original array [2,4,5,6,1,3] + +Step 4: Third Pass (i=3) + +- Moving to the next element, which is 6, we find that 6 is greater than its preceding element (5), so no swap is needed at this point: [2, 4, 5, 6, 1, 3]. + +Step 5: Fourth Pass (i=4) + +- Considering the fifth element (index 4) which is 1, we compare 1 with 6, then 5, and finally 4, shifting each one to the right until 1 finds its correct position: [1, 2, 4, 5, 6, 3]. +- sorted part [1,2,4,5,6], unsorted part [3] + +Step 6: Fifth Pass (i=5) + +- Lastly, we evaluate the sixth element (index 5) which is 3. We compare 3 with 6, shift 6, [1,2,4,5,3,6] then compare 3 with 5, shift 5, [1,2,4,3,5,6] and finally compare 3 with 4, resulting in the final sorted array: [1, 2, 3, 4, 5, 6]. + +After these steps, the array has been sorted using the insertion sort algorithm. Each element was inserted into its correct position within the sorted part of the array. + +# Advantages of Insertion Sort: + +--- + +Insertion Sort has several advantages: + +1. Simplicity: Insertion Sort is a simple algorithm to understand and implement. It has a straightforward logic that makes it easy to grasp and implement correctly. +2. Efficiency for small lists or partially sorted lists: Insertion Sort performs well when the input list is already partially sorted or contains a small number of elements. In such cases, the algorithm can take advantage of the partially sorted nature, resulting in improved efficiency compared to other sorting algorithms. +3. Space efficiency: Insertion Sort is an in-place sorting algorithm, meaning it sorts the input list by rearranging the elements within the original list itself. It does not require additional memory space proportional to the input size, making it memory-efficient. +4. Adaptive: Insertion Sort is an adaptive algorithm, which means it performs well when the input list is almost sorted or contains elements that are already in the correct order. In such cases, the algorithm requires fewer comparisons and swaps, resulting in improved performance. +5. Online sorting: Insertion Sort is suitable for online sorting scenarios where the input list is continuously updated or new elements are added incrementally. It can efficiently maintain a sorted list by inserting new elements at the appropriate position without the need to re-sort the entire list. +6. Stable sorting: Insertion Sort is stable, meaning it preserves the relative order of elements with equal keys. If there are multiple elements with the same value, their original order will be maintained after sorting. + +Despite these advantages, Insertion Sort has a time complexity of O(n^2) in the worst and average case, which makes it less efficient for large input sizes compared to more advanced sorting algorithms like Merge Sort or Quick Sort. + +# Disadvantages of Insertion Sort: + +--- + +Insertion Sort also has some disadvantages: + +1. Quadratic time complexity: Insertion Sort has a time complexity of O(n^2) in the worst and average case, where n is the number of elements in the input list. This means that the algorithm's runtime grows quadratically with the size of the input. As a result, Insertion Sort becomes inefficient for large lists, making it impractical for sorting large datasets compared to more efficient algorithms like Merge Sort or Quick Sort. +2. Lack of scalability: Due to its quadratic time complexity, Insertion Sort does not scale well with increasing input sizes. As the number of elements grows, the number of comparisons and swaps required by the algorithm increases significantly, leading to longer execution times. +3. Performance sensitivity to initial order: Insertion Sort's performance can be highly dependent on the initial order of the elements. If the input list is already sorted or nearly sorted, Insertion Sort performs efficiently with fewer comparisons and swaps. However, if the list is in reverse order or contains elements that are far from their correct positions, the algorithm requires a larger number of comparisons and swaps, resulting in decreased performance. +4. Lack of parallelism: Insertion Sort does not naturally lend itself to parallelization. Since the algorithm operates by iteratively inserting elements into their correct positions, the order of operations is crucial. It is challenging to parallelize the process effectively, which limits its potential for leveraging parallel computing architectures. +5. Limited use in certain scenarios: While Insertion Sort can be suitable for small lists or partially sorted lists, it may not be the best choice for sorting larger datasets or in scenarios where time efficiency is critical. Other sorting algorithms, such as Merge Sort or Quick Sort, can provide better performance in those cases. + +Overall, while Insertion Sort has its advantages in terms of simplicity, space efficiency, and adaptivity, its quadratic time complexity and limited scalability make it less preferable for large-scale sorting tasks. + +# Real Scenarios of Insertion Sort: + +--- + +Insertion Sort, despite its limitations, can still find practical uses in certain real-world scenarios. Here are a few examples: + +1. Small or partially sorted lists: Insertion Sort performs well when the input list is small or already partially sorted. In scenarios where the list size is relatively small or the data is already partially ordered, Insertion Sort can be a reasonable choice due to its simplicity and efficiency in such cases. This could apply to tasks like sorting a small number of names, sorting a deck of cards, or maintaining a sorted list as new elements are added incrementally. +2. Online sorting: Insertion Sort is suitable for scenarios where elements are added to a list incrementally, and the list needs to remain sorted in real-time. For example, in applications that involve continuously receiving and sorting incoming data streams, such as log processing or event-driven systems, Insertion Sort can efficiently maintain the sorted order as new elements arrive. +3. Partial sorting or selection algorithms: Insertion Sort can be used as a component or subroutine in more complex algorithms. For example, in algorithms like Quick Select or Introselect, which are used to find the kth smallest element in a list, Insertion Sort can be employed as part of the partitioning process for small sublists. In these cases, Insertion Sort's efficiency for small lists can contribute to overall algorithmic performance. +4. Teaching and learning purposes: Due to its simplicity and ease of implementation, Insertion Sort is often used as a teaching tool to introduce the concepts of sorting algorithms. It helps students understand the basic principles of sorting and serves as a foundation for learning more advanced sorting algorithms. + +It's important to note that while Insertion Sort has its practical applications, there are generally more efficient sorting algorithms available for most real-world scenarios involving larger datasets. However, in specific contexts where the characteristics of the data align with the strengths of Insertion Sort, it can still be a viable option. + +# Python code for Insertion Sort: + +--- + +``` +'''Copyrights to venkys.io +For more information, visite https://venkys.io"/ + +Python program to sort a given array in order using Insertion sort algorithm.''' + +# Stable : Yes +# Inplace : Yes +# Adaptive : Yes + +# Space complexity: O(1) + +#Time Complexity:O(n^2) in the worst-case scenario, and O(n) in the best-case scenario. + +def VSDInsertionSort(arr,n): + ''' + Function to perform Insertion Sort on the given array. + + Parameters: + arr (list): The input list to be sorted. + n (int): The length of the array. + + Returns: + None. Prints the sorted array. + ''' + for i in range(1,n): + temp=arr[i] + j=i + while j>0 and arr[j-1]>temp: + arr[j]=arr[j-1] + j-=1 + arr[j]=temp + #Print the Sorted array + print("Sorted Array:", *arr,sep=" ") + +def main(): + ''' + Main function to take user input and call the Insertion Sort function. + ''' + try: + n = int(input("Enter the size of the array: ")) + if n <= 0: + print("Invalid size. Please enter a positive integer.") + return + + arr = list(map(int, input("Enter the elements of the array separated by space: ").split())) + + if len(arr) != n: + print("Number of elements entered does not match the specified size.") + return + + VSDInsertionSort(arr, n) + + except ValueError: + print("Invalid input. Please enter valid integers.") + +if __name__ == "__main__": + # Running the main function + main() +``` + +Explanation: + +1. Begin a loop iterating through each element in the array, starting from the second element (index 1) and ending at the last element (index n-1). +2. Store the value of the current element being evaluated in a temporary variable called temp. +3. Set up a pointer j to keep track of the current position in the array.(index) +4. Start a while loop that continues as long as j is greater than 0 and the previous element (arr[j-1]) is greater than the value stored in temp. +5. Shift the element at position j-1 to the position j. +6. Decrement the value of j by 1 to continue comparing with the previous elements. +7. Place the value stored in temp at the position j, effectively inserting the value in its correct place. +8. Print the sorted array, separated by spaces. + +Test Cases: + +### Example 1: + +**Input:** + +Enter the size of the array: 5 + +Enter the elements of the array seperated by space: 4 2 7 1 9 + +**Output:** + +Sorted Array: 1 2 4 7 9 + +### Error Cases: + +### Example 2: + +**Input :** + +Enter the size of the array: -2 + +**Output:** + +Invalid size. Please enter a positive integer. + +### Example 3: + +**Input:** + +Enter the size of the array : d + +**Output:** + +Invalid input. Please enter valid integers + +### Example 4: + +**Input :** + +Enter the size of the array : 3 + +Enter the elements of the array seperated by space: 60 48 + +**Output:** + +Number of elements entered does not match the specified size. + +# C++ code for Insertion Sort: + +--- + +``` +/* Copyrights to venkys.io +For more information, visit https://venkys.io */ + +// C++ program to sort a given array in order using Insertion sort algorithm. + +// Stable: Yes +// Inplace: Yes +// Adaptive: Yes +// Space complexity: O(1) +// Time Complexity: O(n^2) in the worst-case scenario, and O(n) in the best-case scenario. + +#include +// Include the input/output stream header file + +using namespace std; +// Define the standard namespace for input/output operations + +// Function to perform Insertion Sort on an array +void VSDInsertionSort(int arr[], int n) { + // Iterate through each element of the array + for (int i = 1; i < n; i++) { + int temp = arr[i]; // Store the current element to be inserted + int j = i; + + // Move elements greater than temp to the right until a smaller or equal element is found, + // or until the beginning of the array is reached. + while (j > 0 && arr[j - 1] > temp) { + arr[j] = arr[j - 1]; // Shift the current element to the right, creating space for temp. + j--;// Move to the previous position in the array to compare and potentially shift again. + } + arr[j] = temp; // Insert the stored element at its correct position + } + + // Print the sorted array + for (int i = 0; i < n; i++) { + cout << arr[i] << " "; + } + cout << endl; + // Move to the next line after printing all elements +} + +int main() { + int n; + + cout << "Enter the size of the array: "; + if (!(cin >> n)) { + // Check if the input for array size is not an integer + cout << "Error: Please enter a valid integer for the array size." << endl; + return 1; + // Return 1 to indicate an error + } + + if (n <= 0) { + // Check for non-positive array size + cout << "Error: Array size must be a positive integer." << endl; + return 1; + // Return 1 to indicate an error + } + + int arr[n]; + + cout << "Enter the elements of the array: "; + for (int i = 0; i < n; i++) { + if (!(cin >> arr[i])) { + // Check if the input for array elements is not an integer + cout << "Error: Please enter valid integers for array elements." << endl; + return 1; + // Return 1 to indicate an error + } + } + + VSDInsertionSort(arr, n); + // Call the VSDInsertionSort function to sort the array + return 0; + // Return 0 to indicate successful execution of the program +} +``` + +In summary, the program defines an "VSDInsertionSort" function to implement the insertion sort algorithm and a "main" function that initializes an array, calls the "VSDInsertionSort" function to sort the array, and then prints the sorted array. + +This C++ program uses an iterative approach to implement the insertion sort algorithm, sorting the array in ascending order and outputting the sorted array to the console. + +The "VSDInsertionSort" function sorts the elements of the array using the insertion sort algorithm and then prints the sorted array. + +The "main" function initializes an array, calls the "VSDInsertionSort" function to sort the array, and returns 0 to signify successful completion of the program. + +## Sample Test Cases + +**Test Case 1: Basic Input** +Enter the size of the array: 5 +Enter the elements of the array: 4 2 7 1 5 +Sorted Array: 1 2 4 5 7 + +**Test Case 2: Empty Array** +Enter the size of the array: 0 +Error: Array size must be a positive integer. + +**Test Case 3: Non-Integer Array Size Input** +Enter the size of the array: abc +Error: Please enter a valid integer for the array size. + +**Test Case 4: Non-Integer Array Element Input** +Enter the size of the array: 3 +Enter the elements of the array: 1 xyz 3 +Error: Please enter valid integers for array elements. + +# Java code for insertion sort: + +--- + +``` +/* Copyrights to venkys.io +For more information, visit https://venkys.io */ +//Java program to sort a given array in order using Insertion sort algorithm.*/ + +// Stable : Yes +// Inplace : Yes +// Adaptive : Yes + +// Space complexity: O(1) + +//Time Complexity:O(n^2) in the worst-case scenario, and O(n) in the best-case scenario. + +import java.util.InputMismatchException; // Importing InputMismatchException class for handling input errors +import java.util.Scanner; // Importing scanner class from java.util package for user input + +public class InsertionSort { + + // Function to perform Insertion Sort on the given array + public static void insertionSort(int[] array) { + int n = array.length; + // Traverse through each element of the array + for (int i = 1; i < n; ++i) { + int key = array[i];// Store the current element to be inserted + int j = i - 1; + // Move elements greater than key to the right until a smaller or equal element is found, + // or until the beginning of the array is reached. + while (j >= 0 && array[j] > key) { + array[j + 1] = array[j]; // Shift the current element to the right, creating space for key. + j = j - 1;// Move to the previous position in the array to compare and potentially shift again. + } + array[j + 1] = key; // Insert the stored element at its correct position + } + } + + + // Function to print the elements of the array + public static void printArray(int[] array) { + int n = array.length; + for (int i = 0; i < n; ++i) + System.out.print(array[i] + " "); + System.out.println(); + } + + public static void main(String[] args) { + Scanner scanner = new Scanner(System.in); + + try { + // Input the size of the array + Integer n = null; + // Keep prompting the user until a valid positive integer is entered for the array size + while (n == null || n <= 0) { + System.out.print("Enter the size of the array: "); + try { + // Attempt to read an integer from the user input + n = scanner.nextInt(); + // Check if the entered size is not positive + if (n <= 0) { + System.out.println("Invalid size. Please enter a positive integer."); + } + } catch (InputMismatchException e) { + // Handle the case where a non-integer value is entered + System.out.println("Invalid input. Please enter a valid integer."); + scanner.nextLine(); // Clear the buffer to prevent an infinite loop + } + } + // Create an array to store the elements of the array. + int[] array = new int[n]; + + // Prompt the user to enter the elements of the array. + System.out.println("Enter the elements of the array:"); + // Iterate through each element of the array and input values from the user. + for (int i = 0; i < n; i++) { + // Use a loop to handle invalid input until a valid integer is entered. + while (true) { + if (scanner.hasNextInt()) { + // If the entered value is an integer, assign it to the array. + array[i] = scanner.nextInt(); + break; // Exit the loop as a valid integer is obtained. + } else { + // Display an error message for invalid input and clear the buffer. + System.out.println("Invalid input. Please enter valid integers."); + scanner.nextLine(); // Clear the buffer to avoid an infinite loop. + } + } + } + + // Perform Insertion Sort + insertionSort(array); + + // Print the sorted array + System.out.println("Sorted Array:"); + printArray(array); + } finally { + // Close the scanner to avoid resource leak + if (scanner != null) { + scanner.close(); + } + } + } +} +``` + +1. Insertion Sort Method: + - The "insertionSort" method implements the insertion sort algorithm to sort an array of integers in ascending order. +2. Print Array Method: + - The "printArray" method is responsible for printing the elements of an array to the console. +3. Main Method: + - The "main" method initializes an array of integers, calls the "insertionSort" method to sort the array, and then prints the sorted array using the "printArray" method. + + ## Test Cases: + + - **Test Case 1:** + Enter the size of the array: 5 + Enter the elements of the array: + 4 2 7 1 9 + Sorted Array: + 1 2 4 7 9 + - **Test Case 2:** + Enter the size of the array: 3 + Enter the elements of the array: + 100 0 -50 + Sorted Array: + -50 0 100 + - **Error Case 1:** + Enter the size of the array: -2 + Invalid size. Please enter a positive integer. + - **Error Case 2:** + Enter the size of the array: 4 + Enter the elements of the array: + a b c d + + Invalid input. Please enter valid integers. + + diff --git a/Sorting/Easy/Insertion Sort/insertionsort.cpp b/Sorting/Easy/Insertion Sort/insertionsort.cpp new file mode 100644 index 00000000..1c9ceb8c --- /dev/null +++ b/Sorting/Easy/Insertion Sort/insertionsort.cpp @@ -0,0 +1,76 @@ +/* Copyrights to venkys.io +For more information, visit https://venkys.io */ + +// C++ program to sort a given array in order using Insertion sort algorithm. + +// Stable: Yes +// Inplace: Yes +// Adaptive: Yes +// Space complexity: O(1) +// Time Complexity: O(n^2) in the worst-case scenario, and O(n) in the best-case scenario. + +#include +// Include the input/output stream header file + +using namespace std; +// Define the standard namespace for input/output operations + +// Function to perform Insertion Sort on an array +void VSDInsertionSort(int arr[], int n) { + // Iterate through each element of the array + for (int i = 1; i < n; i++) { + int temp = arr[i]; // Store the current element to be inserted + int j = i; + + // Move elements greater than temp to the right until a smaller or equal element is found, + // or until the beginning of the array is reached. + while (j > 0 && arr[j - 1] > temp) { + arr[j] = arr[j - 1]; // Shift the current element to the right, creating space for temp. + j--;// Move to the previous position in the array to compare and potentially shift again. + } + arr[j] = temp; // Insert the stored element at its correct position + } + + // Print the sorted array + for (int i = 0; i < n; i++) { + cout << arr[i] << " "; + } + cout << endl; + // Move to the next line after printing all elements +} + +int main() { + int n; + + cout << "Enter the size of the array: "; + if (!(cin >> n)) { + // Check if the input for array size is not an integer + cout << "Error: Please enter a valid integer for the array size." << endl; + return 1; + // Return 1 to indicate an error + } + + if (n <= 0) { + // Check for non-positive array size + cout << "Error: Array size must be a positive integer." << endl; + return 1; + // Return 1 to indicate an error + } + + int arr[n]; + + cout << "Enter the elements of the array: "; + for (int i = 0; i < n; i++) { + if (!(cin >> arr[i])) { + // Check if the input for array elements is not an integer + cout << "Error: Please enter valid integers for array elements." << endl; + return 1; + // Return 1 to indicate an error + } + } + + VSDInsertionSort(arr, n); + // Call the VSDInsertionSort function to sort the array + return 0; + // Return 0 to indicate successful execution of the program +} diff --git a/Sorting/Easy/Insertion Sort/insertionsort.py b/Sorting/Easy/Insertion Sort/insertionsort.py new file mode 100644 index 00000000..bfff5aab --- /dev/null +++ b/Sorting/Easy/Insertion Sort/insertionsort.py @@ -0,0 +1,58 @@ +'''Copyrights to venkys.io +For more information, visite https://venkys.io"/ + +Python program to sort a given array in order using Insertion sort algorithm.''' + +# Stable : Yes +# Inplace : Yes +# Adaptive : Yes + +# Space complexity: O(1) + +#Time Complexity:O(n^2) in the worst-case scenario, and O(n) in the best-case scenario. + +def VSDInsertionSort(arr,n): + ''' + Function to perform Insertion Sort on the given array. + + Parameters: + arr (list): The input list to be sorted. + n (int): The length of the array. + + Returns: + None. Prints the sorted array. + ''' + for i in range(1,n): + temp=arr[i] + j=i + while j>0 and arr[j-1]>temp: + arr[j]=arr[j-1] + j-=1 + arr[j]=temp + #Print the Sorted array + print("Sorted Array:", *arr,sep=" ") + +def main(): + ''' + Main function to take user input and call the Insertion Sort function. + ''' + try: + n = int(input("Enter the size of the array: ")) + if n <= 0: + print("Invalid size. Please enter a positive integer.") + return + + arr = list(map(int, input("Enter the elements of the array separated by space: ").split())) + + if len(arr) != n: + print("Number of elements entered does not match the specified size.") + return + + VSDInsertionSort(arr, n) + + except ValueError: + print("Invalid input. Please enter valid integers.") + +if __name__ == "__main__": + # Running the main function + main() diff --git a/Sorting/Medium/Radix Sort/README.md b/Sorting/Medium/Radix Sort/README.md new file mode 100644 index 00000000..3ca459ca --- /dev/null +++ b/Sorting/Medium/Radix Sort/README.md @@ -0,0 +1,603 @@ +# Exploring Sorting Algorithms: + +--- + +Sorting algorithms are a fundamental part of programming. They are algorithms that rearrange the elements of a collection (such as an array or a list) into a specified order, typically in ascending or descending numerical or lexicographical (alphabetical) order. Sorting is a common operation in many real-world applications, and efficient sorting algorithms are crucial for optimizing the performance of various computer programs. The choice of a sorting algorithm depends on factors such as the size of the data, the nature of the data, and the application’s specific requirements. + +# Introduction to Radix Sort: + +--- + +## Radix sort is a non comparitive integer sorting algorithm. + +A non-comparitive integer sorting algorithm is an algorithm that sorts integers without explicitly comparing them to each other based on magnitude. Traditional sorting algorithms such as quicksort or merge sort, rely on comparisons between elements to establish their order. Non-comparitive integer sorting algorithms, on the other hand, use specific properties of integers to achieve sorting without direct comparisons. Few examples of non-comapritive integer sorting algorithms are Counting sort, Radix sort, Bucket Sort, Pigeonhole Sort and Flash Sort. + +## **How does Radix Sort algorithms sorts numbers?** + +This algorithm sorts numbers by processing individual digits. It sorts the numbers by examining the digits from the least significant digit (LSD) to most significant digit (MSD) or vice versa. In simple words, in a array of integers, it first sorts the numbers basing on their one’s digit placed numbers followed by sorting based on 10’s digit placed numbers and then hundreds and so on. + +## **How is Radix Sort different from Bucket Sort?** + +Radix sort and bucket sort are almost equivalent; bucket sort goes from MSD to LSD, while radix sort is capable of both "direction" (LSD or MSD). + +# **Brief Explanation of Radix Sort Algorithm:** + +--- + +1. **Identify the Maximum Element**: Find the maximum value in the input array. This is needed to determine the number of digits in the largest element, which will determine the number of iterations needed to fully sort the array. For example in an array [10, 178, 827, 9, 12, 73] the largest element is 827 which has 3 digits. This gives us the idea that we need to sort the digits first in units place followed by tens place and then in hundreds place. On the other hand in arrays like [10, 2, 18, 9, 11] we just need to sort two times, First in unit digit and then in 10’s digit. +2. **Initialize Exponential Value**: Set the initial value of the exponent (exp) to 1, representing the least significant digit position. +3. **Iterate Through Digits**: While the maximum value divided by the exponent is greater than 0, perform the following steps for each iteration: + - **Counting Sort**: Use counting sort as a subroutine to sort the elements based on the current digit (specified by the exponent). + - Count the frequency of each digit at the specified position, and then modify the count array to represent the position of elements in the output array. + - Update Exponential Value: Multiply the exponent by 10 to move to the next significant digit position. +4. **Output Sorted Array**: Once all iterations are complete, the array is fully sorted based on the individual digits of the elements. + +# **Understanding how counting sort works** + +--- + +This sort works by counting the number of objects that have distinct key values, and using arithmetic to determine the position of each key in the output sequence. + +1. Counting the Frequency +2. Determining Positions +3. Building the Output Array + +Understanding Counting sort with the help of an example: + +Let's consider an array of 5 values for our example: [4, 2, 4, 1, 3]. + +1. **Identifying the range of input**: First, we identify the range of the input. In our case, the input values range from 1 to 4. +2. **Counting the frequency of each element**: We count the frequency of each element in the input array and store it in a separate count array: + + Input array: [4, 2, 4, 1, 3] Count array: [1, 1, 1, 2] + + Here, the count array indicates that there is 1 occurrence of 1, 1 occurrence of 2, 1 occurrence of 3, and 2 occurrences of 4 in the input array. + +3. **Calculating the positions**: We calculate the positions of each element in the output array based on the count array. + + Count array: [1, 1, 1, 2] Cumulative count array: [1, 2, 3, 5] + + The cumulative count array gives us the positions of each element in the sorted output array. For example, the value 1 will be at position 1, the value 2 will be at position 2, the value 3 will be at position 3, and the value 4 will be at positions 4 and 5 in the output array. + +4. **Creating the sorted array**: Finally, we use the positions from the cumulative count array to place the elements in their sorted positions in the output array. + + Output array: [1, 2, 3, 4, 4] + + # + + ## **Performance of Radix Sort Algorithm** + + worst case time complexity of radix sort is O(n^2) + + Best case time complexity of radix sort is O(a*n) + + Average case time complexity of radix sort is O(p*(n+d)) + + Space complexity of radix sort is O(n+k) + + # Advantages of Radix Sort: + + 1. Linear Time Complexity: Radix sort has a time complexity of O(d * (n + k)), where n is the number of elements, k is the range of input values, and d is the number of digits in the maximum value. In many cases, the time complexity simplifies to O(n + k), making it a linear-time sorting algorithm. + 2. Non-Comparison Based: Unlike comparison-based sorting algorithms (e.g., quicksort, mergesort), radix sort does not rely on comparison operations to arrange elements. Instead, it sorts based on the individual digits or significant places within the numbers, resulting in potentially faster performance for certain types of data. + 3. Stable Sorting: Radix sort is a stable sorting algorithm, meaning it maintains the relative order of elements with equal keys. This property is often valuable when the original ordering of equivalent elements needs to be preserved. + 4. Effective for Large Data Sets: Radix sort can be particularly effective for large data sets, especially when the range of input values is significantly smaller than the number of elements. It can outperform comparison-based sorting algorithms in such scenarios. + + # Disadvantages of Radix Sort: + + 1. Space Complexity: Radix sort requires additional space to hold the intermediate sorting results during each iteration. The space complexity is not constant and is dependent on the input size, which can be a drawback when working with very large data sets. + 2. Limited Applicability: Radix sort is most effective for sorting integers or fixed-length strings with a limited range of values. However, it is not suitable for sorting arbitrary data structures or variable-length strings. + 3. Not In-Place: Radix sort is not an in-place sorting algorithm, as it needs auxiliary space for intermediate results. This can be a drawback in situations where memory usage is a critical concern. + 4. Complexity with Variable-Length Keys: When dealing with variable-length keys (e.g., strings of varying lengths), radix sort may become less efficient due to the need for additional processing to handle varying key lengths. + 5. Limited to Positive Integers: Traditional radix sort algorithms are primarily intended for sorting positive integers and may require modifications to support sorting of negative numbers and floating-point numbers. + + # Real World Scenarios of Radix Sort: + + 1. Computer Graphics: In computer graphics, radix sort is used for various tasks, including depth buffering, which is crucial for rendering scenes accurately. The z-buffer, used for hidden surface removal, can be efficiently implemented using radix sort due to its stable sorting nature, ensuring that the relative depth ordering of objects is preserved. + 2. String Sorting: While radix sort is primarily designed for integers, it can also be adapted for sorting fixed-length strings. It finds applications in databases or file systems for sorting strings with fixed lengths, such as sorting file names or database records based on specific index keys. This use case leverages the non-comparison based approach of radix sort for efficient string sorting. + 3. Data Sorting in External Memory: Radix sort's I/O efficiency makes it suitable for sorting large datasets in external memory systems such as external hard drives or distributed file systems. Its linear time complexity and minimal disk seeks make it a desirable choice for sorting vast amounts of data that cannot fit entirely in main memory. + 4. Network Routing: In networking, radix sort can be applied for IP address lookups in routing tables. The sorting of IP addresses helps in efficiently routing network traffic by quickly accessing the relevant routing information based on the destination IP address. The stable nature of radix sort is particularly beneficial in this context. + 5. Data Compression: Radix sort is used as a crucial part of various data compression algorithms. For example, in Burrows-Wheeler Transform (BWT) based compression algorithms, the sorting step uses variants of radix sort to accomplish reordering and grouping of characters, leading to improved compression ratios and faster encoding/decoding. + + # Code in Python : + + --- + + ``` + '''Copyrights to venkys.io + For more information, visite https://venkys.io"/ + + Python program to sort a given array in order using radix sort algorithm.''' + + # Stable : Yes + # Inplace : Yes + # Adaptive : No + + # Space complexity: O(n+k) where + # n = number of elements in the input array + # k = range of input values (number of unique digits) + + #Time Complexity: O(d*(n+k)) /O(n+k) in simplified version + # n=no. of elements + # k= range of input values + # d= no. of digits in maximum value + + """ + Perform counting sort on the array based on the given exponent. + + Parameters: + arr (list): The input list to be sorted. + exp (int): The exponent used for counting sort. + + Returns: + None. Modifies the input array in-place. + """ + def counting_sort(arr, exp): + n = len(arr) + # Initialize an output array with zeros + output = [0] * n + # Initialize a count array to store the count of occurrences for each digit (0 to 9) + count = [0] * 10 + + # Count occurrences of each digit based on the given exponent + for i in range(n): + index = arr[i] // exp + count[index % 10] += 1 + + # Modify the count array to store the cumulative count of occurrences + for i in range(1, 10): + count[i] += count[i - 1] + + # Build the output array using the count information + i = n - 1 + while i >= 0: + index = arr[i] // exp + output[count[index % 10] - 1] = arr[i] + count[index % 10] -= 1 + i -= 1 + + # Copy the sorted elements from the output array to the original array + for i in range(n): + arr[i] = output[i] + + """ + Perform radix sort on the given array. + + Parameters: + arr (list): The input list to be sorted. + + Returns: + list: The sorted array. + """ + def radix_sort(arr): + # Find the maximum number in the array to determine the number of digits in it + max_num = max(arr) + # Initialize the exponent (exp) to the least significant digit + exp = 1 + # Loop until all digits are processed, from the least significant to the most significant + while max_num // exp > 0: + # Call the counting_sort function to sort the array based on the current exponent + counting_sort(arr, exp) + # Move to the next significant digit by multiplying the exponent by 10 + exp *= 10 + # Return the sorted array + return arr + + def main(): + try: + arr = list(map(int, input("Enter the elements of the array separated by space: ").split())) + # Check if the array is empty, and raise a ValueError if it is + if len(arr) == 0: + raise ValueError("Array is empty.") + + print('The given array is', arr)# Display the original array + sorted_arr = radix_sort(arr.copy()) # Sorting a copy to keep the original array intact + print('The sorted order is:', sorted_arr) # Display the sorted array + + except ValueError as e: + # Handle ValueError exceptions (e.g., empty array) + print(f"Error: {e}") + + # Check if the script is being run as the main program + if __name__ == "__main__": + main() + ``` + + In the above Code, the counting_sort subroutine is used within the radix_sort algorithm to sort the elements based on their individual digits. The counting_sort subroutine counts the frequence of each digit at specified exponential postion and then sorts the elements based on this information. The radix_sort algorithm iterates through each digit position( units, tens, hundreds etc) to fully sort the array. + + ## Sample Test Cases: + + - Test Case 1: + Input: Enter the elements of the array separated by space: 170 45 75 90 802 24 2 66 + Output: The given array is [170, 45, 75, 90, 802, 24, 2, 66] + The sorted order is: [2, 24, 45, 66, 75, 90, 170, 802] + - Test Case 2: + Input: Enter the elements of the array separated by space: 5 4 3 2 1 + Output: The given array is [5, 4, 3, 2, 1] + The sorted order is: [1, 2, 3, 4, 5] + - Edge Case: + Input: Enter the elements of the array separated by space: + Output: Error: Array is empty. + - Error Case: + Input: Enter the elements of the array separated by space: 5 3 d 5 6 + Output: Error: invalid literal for int() with base 10: 'd' + + # Code in C++: + + ``` + /*Copyrights to venkys.io + For more information, visite https://venkys.io"/ + + C++ program to sort a given array in order using radix sort algorithm. */ + // Stable : Yes + // Inplace : No + // Adaptive : No + + // Space complexity: O(n+k) where + // n = number of elements in the input array + // k = range of input values (number of unique digits) + + //Time Complexity: O(d*(n+k)) /O(n+k) in simplified version + // n=no. of elements + // k= range of input values + // d= no. of digits in maximum value + + #include + // This line includes the input/output stream header file + using namespace std; + // This line declares that elements from the C++ Standard Library (std). + // Specifically, it allows the usage of elements, such as cout and cin, without needing to prefix them with std:: + + //function to get the maximum value in arr[] + int max(int arr[],int n){ + # Initialize maxele to the first element of the array + int maxele=arr[0]; + for(int i=0;imaxele){ + # If yes, update maxele to the current element + maxele=arr[i]; + } + } + # Return the maximum element found in the array + return maxele; + } + //function to do counting sort of arr[] according to the digit represented by exp. + void countingSort(int arr[],int n,int decimalplace){ + // Initialize an array to store the count of each digit (0 to 9) + int count[10]; + + // Initialize an array to store the sorted output + int output[n]; + // Initialize count array with zeros + for(int i=0;i<10;i++){ + count[i]=0; + } + //processing count array + for(int i=0;i=0;i--){ + int index=arr[i]/decimalplace; + output[count[index%10]-1]=arr[i]; + count[index%10]-=1; + } + + //Cope the output array to arr[] + for(int i=0;i0){ + countingSort(arr,n,decimalplace); + decimalplace*=10; + } + + //Print the sorted array + for(int i=0;i> n) || n <= 0) { + // Check if the input for array size is not an integer + cout << "Error: Please enter a valid integer for the array size." << endl; + return 1; + // Return 1 to indicate an error + } + int arr[n]; + // Prompt the user to enter the elements of the array + cout << "Enter elements in array: "; + // Iterate through each element of the array and input values from the user + for (int i = 0; i < n; i++) { + // Check if the input for array elements is not an integer + if (!(cin >> arr[i])) { + cout << "Error: Please enter valid integers for array elements." << endl; + return 1; // Return 1 to indicate an error + } + } + // Call the radixSort function to sort the array + radixSort(arr, n); + } + return 0; // Return 0 to indicate successful execution of the program + } + ``` + + ### C++ Radix Sort Algorithm Explanation: + + The C++ implementation of radix sort follows a similar approach to the Python implementation. + + 1. **countingSort() function**: In C++, the counting sort is defined as a separate function. Like in Python, it iterates through the array, calculates the frequency of digits, and distributes the elements into buckets. After processing all digits, it updates the original array with the sorted elements. + 2. **radixSort() function**: The `radixSort` function finds the maximum number in the array and then repeatedly calls the `countingSort` function for each digit place to sort the numbers in the array. + + ## Sample Test Cases: + + - **Test Case 1:** + Input: + Enter no. of elements in array: 5 + Enter elements in array: 12 43 7 9 5 + + Output: + 5 7 9 12 43 + + - **Test Case 2:** + Input: + Enter no. of elements in array: 8 + Enter elements in array: 109 2 301 42 56 17 208 95 + + Output: + 2 17 42 56 95 109 208 301 + + - **Test Case 3:** + Input: + Enter no. of elements in array: -3 + Output: + Error: Please enter a valid integer for the array size. + - **Test Case 4:** + Input: + Enter no. of elements in array: 4 + Enter elements in array: 5 2 d 8 + + Output: + Error: Please enter valid integers for array elements. + + - **Test Case 5:** + Input: + Enter no. of elements in array: 0 + Output: + Error: Please enter a valid integer for the array size. + + # Code in Java: + + +``` +/* Copyrights to venkys.io */ +/* For more programs, visit venkys.io */ +/* Java program for Radix sort */ + +// Stable: Yes +// Inplace: No +// Adaptive: No + +// Space complexity: O(n) where n = number of elements in the input array + +// Time Complexity: O(d*(n+k)) / O(n+k) in simplified version +// n=no. of elements +// k= range of input values +// d= no. of digits in maximum value + +import java.util.InputMismatchException;// Importing InputMismatchException class for handling input errors +import java.util.Scanner; // Importing Scanner class from java.util package for user input + +public class RadixSort { + + static int output[]; // Sorted output array + + // Function to sort radixes + public static void VSDRadix(int n, int[] a, int digits) { + int k = 0;// Initialize the digit position to the least significant digit + int temp[] = new int[n]; // Temporary array to hold radixes + while (k < digits) { // Loop until all digits are processed + for (int i = 0; i < n; i++) { + if (k > 0) + // Extract the k-th digit using modulo and division + temp[i] = (int) ((a[i] / Math.pow(10, k)) % 10); + else + // For the least significant digit, use modulo only + temp[i] = a[i] % 10; + } + // Perform counting sort based on the current digit + VSDcountingsort(n, a, temp); + k++; // Move to the next digit + } + } + + // Function to perform counting sort on radixes + public static void VSDcountingsort(int n, int[] a, int temp[]) { + int[] count = new int[10];// Create an array to store the count of occurrences of each radix. + output = new int[n];// Create an array to store the sorted output. + + // Initializing all the elements of counting array to zero + for (int i = 0; i < count.length; i++) + count[i] = 0; + + // Storing the count of occurrences of each element from the input array to count array + for (int i = 0; i < n; i++) { + count[temp[i]]++; + } + + // Computing cumulative sum from count array + for (int i = 1; i < 10; i++) { + count[i] += count[i - 1]; + } + + // Sorting radixes. Traverse the input array backward. + //For each element, use the count array to determine its position in the sorted output array. + for (int i = n - 1; i >= 0; i--) { + output[count[temp[i]] - 1] = a[i]; + count[temp[i]]--;//Decrease the count of that radix in the count array. + } + + // Copy the sorted output array back to the original array. + for (int i = 0; i < n; i++) { + a[i] = output[i]; + } + } + + // Function to count maximum number of digits + public static int VSDdigitcount(int max) { + int d = 0;// Initialize the digit count to 0 + while (max > 0) { + d++; // Increment the digit count for each digit + max = max / 10; // Remove the last digit by dividing the number by 10 + } + return d; // Return the final count of digits + } + + // Function to get maximum element in the array + public static int VSDMax(int n, int[] a) { + int max = 0; + // Iterate through each element in the array + for (int i = 0; i < n; i++) { + // Check if the current element is greater than the current max + if (a[i] > max) { + // If yes, update max to the current element + max = a[i]; + } + } + // Return the maximum element found in the array + return max; + } + + // Function to print the output + public static void VSDprintOutput(int n, int[] a) { + System.out.println("The sorted array is:"); + for (int i = 0; i < n; i++) + System.out.print(a[i] + " "); + + System.out.println(); + } + + public static void main(String args[]) { + // Create a Scanner object to read user input from the console. + Scanner scanner = new Scanner(System.in); + try { + // Prompt the user to enter the size of the array. + System.out.print("Enter the size of the array: "); + // Initialize n to null to validate user input. + Integer n = null; + // Continue prompting the user until a valid positive integer is entered for the array size. + while (n == null || n <= 0) { + try { + // Attempt to read an integer from the user input. + n = scanner.nextInt(); + // Check if the entered size is not positive. + if (n <= 0) { + System.out.println("Invalid size. Please enter a positive integer."); + } + } catch (InputMismatchException e) { + // Handle the case where a non-integer value is entered. + System.out.println("Invalid input. Please enter a valid integer."); + scanner.nextLine();// Clear the buffer to prevent an infinite loop. + } + } + + // Create an array to store the elements of the array. + int[] a = new int[n]; + + // Prompt the user to enter the elements of the array. + System.out.println("Enter the elements of the array:"); + // Iterate through each element of the array and input values from the user. + for (int i = 0; i < n; i++) { + // Use a loop to handle invalid input until a valid integer is entered. + while (true) { + if (scanner.hasNextInt()) { + // If the entered value is an integer, assign it to the array. + a[i] = scanner.nextInt(); + break; // Exit the loop as a valid integer is obtained. + } else { + // Display an error message for invalid input and clear the buffer. + System.out.println("Invalid input. Please enter valid integers."); + scanner.nextLine();// Clear the buffer to avoid an infinite loop. + } + } + } + // Find the maximum element in the array + int max = VSDMax(n, a); + + // Count the number of digits in the maximum element. + int d = VSDdigitcount(max); + + // Perform Radix Sort on the array. + VSDRadix(n, a, d); + + // Print the sorted array. + VSDprintOutput(n, a); + } finally { + // Close the scanner to avoid resource leaks. + if (scanner != null) { + scanner.close(); + } + } + } +} +``` + +**Java Radix Sort Algorithm Explanation:** + +Few of the functions used in Java are: + +1. VSDMax→ To obtain maximum element from an array +2. VSDdigitcount→ To count number of digits in the maximum value +3. VSDRadix→ To sort numbers based on their radix +4. VSDcountingsort→Performs counting sort algorithm +5. VSDprintOutput→ To print the sorted array through radix sort algorithm. + +## Sample Test Cases: + +- **Test Case 1:** +Enter the size of the array: 5 +Enter the elements of the array: +29 13 55 7 42 +The sorted array is: +7 13 29 42 55 +- **Test Case 2 (Edge Case - Empty Array):** +Enter the size of the array: 0 +Invalid size. Please enter a positive integer. +- **Test Case 3 (Handling Invalid Input - Non-Integer Size):** +Enter the size of the array: abc +Invalid input. Please enter a valid integer. +Enter the size of the array: 5 +Enter the elements of the array: +1 2 3 4 5 +The sorted array is: +1 2 3 4 5 +- **Test Case 4 (Handling Invalid Input - Non-Integer Elements):** +Enter the size of the array: 4 +Enter the elements of the array: +10 a 30 40 +Invalid input. Please enter valid integers. +20 10 40 30 +The sorted array is: +10 20 30 40 diff --git a/Sorting/Medium/Radix Sort/RadixSort.java b/Sorting/Medium/Radix Sort/RadixSort.java new file mode 100644 index 00000000..7bf9dea1 --- /dev/null +++ b/Sorting/Medium/Radix Sort/RadixSort.java @@ -0,0 +1,170 @@ +/* Copyrights to venkys.io */ +/* For more programs, visit venkys.io */ +/* Java program for Radix sort */ + +// Stable: Yes +// Inplace: No +// Adaptive: No + +// Space complexity: O(n) where n = number of elements in the input array + +// Time Complexity: O(d*(n+k)) / O(n+k) in simplified version +// n=no. of elements +// k= range of input values +// d= no. of digits in maximum value + +import java.util.InputMismatchException;// Importing InputMismatchException class for handling input errors +import java.util.Scanner; // Importing Scanner class from java.util package for user input + +public class RadixSort { + + static int output[]; // Sorted output array + + // Function to sort radixes + public static void VSDRadix(int n, int[] a, int digits) { + int k = 0;// Initialize the digit position to the least significant digit + int temp[] = new int[n]; // Temporary array to hold radixes + while (k < digits) { // Loop until all digits are processed + for (int i = 0; i < n; i++) { + if (k > 0) + // Extract the k-th digit using modulo and division + temp[i] = (int) ((a[i] / Math.pow(10, k)) % 10); + else + // For the least significant digit, use modulo only + temp[i] = a[i] % 10; + } + // Perform counting sort based on the current digit + VSDcountingsort(n, a, temp); + k++; // Move to the next digit + } + } + + // Function to perform counting sort on radixes + public static void VSDcountingsort(int n, int[] a, int temp[]) { + int[] count = new int[10];// Create an array to store the count of occurrences of each radix. + output = new int[n];// Create an array to store the sorted output. + + // Initializing all the elements of counting array to zero + for (int i = 0; i < count.length; i++) + count[i] = 0; + + // Storing the count of occurrences of each element from the input array to count array + for (int i = 0; i < n; i++) { + count[temp[i]]++; + } + + // Computing cumulative sum from count array + for (int i = 1; i < 10; i++) { + count[i] += count[i - 1]; + } + + // Sorting radixes. Traverse the input array backward. + //For each element, use the count array to determine its position in the sorted output array. + for (int i = n - 1; i >= 0; i--) { + output[count[temp[i]] - 1] = a[i]; + count[temp[i]]--;//Decrease the count of that radix in the count array. + } + + // Copy the sorted output array back to the original array. + for (int i = 0; i < n; i++) { + a[i] = output[i]; + } + } + + // Function to count maximum number of digits + public static int VSDdigitcount(int max) { + int d = 0;// Initialize the digit count to 0 + while (max > 0) { + d++; // Increment the digit count for each digit + max = max / 10; // Remove the last digit by dividing the number by 10 + } + return d; // Return the final count of digits + } + + // Function to get maximum element in the array + public static int VSDMax(int n, int[] a) { + int max = 0; + // Iterate through each element in the array + for (int i = 0; i < n; i++) { + // Check if the current element is greater than the current max + if (a[i] > max) { + // If yes, update max to the current element + max = a[i]; + } + } + // Return the maximum element found in the array + return max; + } + + // Function to print the output + public static void VSDprintOutput(int n, int[] a) { + System.out.println("The sorted array is:"); + for (int i = 0; i < n; i++) + System.out.print(a[i] + " "); + + System.out.println(); + } + + public static void main(String args[]) { + // Create a Scanner object to read user input from the console. + Scanner scanner = new Scanner(System.in); + try { + // Prompt the user to enter the size of the array. + System.out.print("Enter the size of the array: "); + // Initialize n to null to validate user input. + Integer n = null; + // Continue prompting the user until a valid positive integer is entered for the array size. + while (n == null || n <= 0) { + try { + // Attempt to read an integer from the user input. + n = scanner.nextInt(); + // Check if the entered size is not positive. + if (n <= 0) { + System.out.println("Invalid size. Please enter a positive integer."); + } + } catch (InputMismatchException e) { + // Handle the case where a non-integer value is entered. + System.out.println("Invalid input. Please enter a valid integer."); + scanner.nextLine();// Clear the buffer to prevent an infinite loop. + } + } + + // Create an array to store the elements of the array. + int[] a = new int[n]; + + // Prompt the user to enter the elements of the array. + System.out.println("Enter the elements of the array:"); + // Iterate through each element of the array and input values from the user. + for (int i = 0; i < n; i++) { + // Use a loop to handle invalid input until a valid integer is entered. + while (true) { + if (scanner.hasNextInt()) { + // If the entered value is an integer, assign it to the array. + a[i] = scanner.nextInt(); + break; // Exit the loop as a valid integer is obtained. + } else { + // Display an error message for invalid input and clear the buffer. + System.out.println("Invalid input. Please enter valid integers."); + scanner.nextLine();// Clear the buffer to avoid an infinite loop. + } + } + } + // Find the maximum element in the array + int max = VSDMax(n, a); + + // Count the number of digits in the maximum element. + int d = VSDdigitcount(max); + + // Perform Radix Sort on the array. + VSDRadix(n, a, d); + + // Print the sorted array. + VSDprintOutput(n, a); + } finally { + // Close the scanner to avoid resource leaks. + if (scanner != null) { + scanner.close(); + } + } + } +} diff --git a/Sorting/Medium/Radix Sort/radixsort.cpp b/Sorting/Medium/Radix Sort/radixsort.cpp new file mode 100644 index 00000000..3d6d1c62 --- /dev/null +++ b/Sorting/Medium/Radix Sort/radixsort.cpp @@ -0,0 +1,118 @@ +/*Copyrights to venkys.io +For more information, visite https://venkys.io"/ + +C++ program to sort a given array in order using radix sort algorithm. */ +// Stable : Yes +// Inplace : No +// Adaptive : No + +// Space complexity: O(n+k) where + // n = number of elements in the input array + // k = range of input values (number of unique digits) + +//Time Complexity: O(d*(n+k)) /O(n+k) in simplified version + // n=no. of elements + // k= range of input values + // d= no. of digits in maximum value + +#include +// This line includes the input/output stream header file +using namespace std; +// This line declares that elements from the C++ Standard Library (std). +// Specifically, it allows the usage of elements, such as cout and cin, without needing to prefix them with std:: + +//function to get the maximum value in arr[] +int max(int arr[],int n){ + # Initialize maxele to the first element of the array + int maxele=arr[0]; + for(int i=0;imaxele){ + # If yes, update maxele to the current element + maxele=arr[i]; + } + } + # Return the maximum element found in the array + return maxele; +} +//function to do counting sort of arr[] according to the digit represented by exp. +void countingSort(int arr[],int n,int decimalplace){ + // Initialize an array to store the count of each digit (0 to 9) + int count[10]; + + // Initialize an array to store the sorted output + int output[n]; + // Initialize count array with zeros + for(int i=0;i<10;i++){ + count[i]=0; + } + //processing count array + for(int i=0;i=0;i--){ + int index=arr[i]/decimalplace; + output[count[index%10]-1]=arr[i]; + count[index%10]-=1; + } + + //Cope the output array to arr[] + for(int i=0;i0){ + countingSort(arr,n,decimalplace); + decimalplace*=10; + } + + //Print the sorted array + for(int i=0;i> n) || n <= 0) { + // Check if the input for array size is not an integer + cout << "Error: Please enter a valid integer for the array size." << endl; + return 1; + // Return 1 to indicate an error + } + int arr[n]; + // Prompt the user to enter the elements of the array + cout << "Enter elements in array: "; + // Iterate through each element of the array and input values from the user + for (int i = 0; i < n; i++) { + // Check if the input for array elements is not an integer + if (!(cin >> arr[i])) { + cout << "Error: Please enter valid integers for array elements." << endl; + return 1; // Return 1 to indicate an error + } + } + // Call the radixSort function to sort the array + radixSort(arr, n); + } + return 0; // Return 0 to indicate successful execution of the program +} diff --git a/Sorting/Medium/Radix Sort/radixsort.py b/Sorting/Medium/Radix Sort/radixsort.py new file mode 100644 index 00000000..50b94633 --- /dev/null +++ b/Sorting/Medium/Radix Sort/radixsort.py @@ -0,0 +1,98 @@ +'''Copyrights to venkys.io +For more information, visite https://venkys.io"/ + +Python program to sort a given array in order using radix sort algorithm.''' + +# Stable : Yes +# Inplace : Yes +# Adaptive : No + +# Space complexity: O(n+k) where + # n = number of elements in the input array + # k = range of input values (number of unique digits) + +#Time Complexity: O(d*(n+k)) /O(n+k) in simplified version + # n=no. of elements + # k= range of input values + # d= no. of digits in maximum value + +""" + Perform counting sort on the array based on the given exponent. + + Parameters: + arr (list): The input list to be sorted. + exp (int): The exponent used for counting sort. + + Returns: + None. Modifies the input array in-place. + """ +def counting_sort(arr, exp): + n = len(arr) + # Initialize an output array with zeros + output = [0] * n + # Initialize a count array to store the count of occurrences for each digit (0 to 9) + count = [0] * 10 + + # Count occurrences of each digit based on the given exponent + for i in range(n): + index = arr[i] // exp + count[index % 10] += 1 + + # Modify the count array to store the cumulative count of occurrences + for i in range(1, 10): + count[i] += count[i - 1] + + # Build the output array using the count information + i = n - 1 + while i >= 0: + index = arr[i] // exp + output[count[index % 10] - 1] = arr[i] + count[index % 10] -= 1 + i -= 1 + + # Copy the sorted elements from the output array to the original array + for i in range(n): + arr[i] = output[i] + +""" + Perform radix sort on the given array. + + Parameters: + arr (list): The input list to be sorted. + + Returns: + list: The sorted array. + """ +def radix_sort(arr): + # Find the maximum number in the array to determine the number of digits in it + max_num = max(arr) + # Initialize the exponent (exp) to the least significant digit + exp = 1 + # Loop until all digits are processed, from the least significant to the most significant + while max_num // exp > 0: + # Call the counting_sort function to sort the array based on the current exponent + counting_sort(arr, exp) + # Move to the next significant digit by multiplying the exponent by 10 + exp *= 10 + # Return the sorted array + return arr + + +def main(): + try: + arr = list(map(int, input("Enter the elements of the array separated by space: ").split())) + # Check if the array is empty, and raise a ValueError if it is + if len(arr) == 0: + raise ValueError("Array is empty.") + + print('The given array is', arr)# Display the original array + sorted_arr = radix_sort(arr.copy()) # Sorting a copy to keep the original array intact + print('The sorted order is:', sorted_arr) # Display the sorted array + + except ValueError as e: + # Handle ValueError exceptions (e.g., empty array) + print(f"Error: {e}") + +# Check if the script is being run as the main program +if __name__ == "__main__": + main() diff --git a/Sorting/Medium/Shell Sort/README.md b/Sorting/Medium/Shell Sort/README.md new file mode 100644 index 00000000..a88796c6 --- /dev/null +++ b/Sorting/Medium/Shell Sort/README.md @@ -0,0 +1,522 @@ +# Introduction to Shell Sort: + +--- + +The Shell Sort algorithm is a simple and efficient sorting algorithm that is used to sort an array of elements. It is a divide-and-conquer algorithm, which means that it divides the original array into smaller sub-arrays, sorts each sub-array separately, and then combines the sorted sub-arrays back into a single sorted array. + +The algorithm works by dividing the input array into two halves, then dividing each half into smaller sub-arrays and sorting each sub-array using any sorting algorithm of your choice. The sorted sub-arrays are then merged back into a single sorted array. This process continues, and the size of the sub-arrays is decreased at each iteration until the entire array is sorted. + +The key element in the Shell Sort algorithm is the interval, which represents the range of elements that are compared and sorted at each iteration. The interval is determined based on the gap size, which is the initial distance between elements in the sorted sub-array. The gap size is decreased by a certain factor at each iteration, allowing the algorithm to efficiently sort the array. + +The Shell Sort algorithm is relatively simple and easy to understand. However, it is not the most efficient sorting algorithm, particularly for large arrays. + +# What is a Comparision based and an In-place comparison based Sort? + +--- + +Comparison-based sorting algorithms rely on comparing elements of an array to determine their order. They work by repeatedly iterating through the array and swapping adjacent elements that have the wrong order. There are several comparison-based sorting algorithms, some of the most common ones include : Bubble sort, Quicksort, Mergesort, Selection sort, Insertion sort and Radix Sort + +In-place comparison based sorting, on the other hand, is a type of sorting algorithm that does not use additional memory to sort the array. In contrast with in-place comparison based sorting, sorting algorithms like Radix sort may use additional memory to sort the array. + +In-place comparison-based sorting algorithms are generally not as efficient as non-comparison-based sorting algorithms, such as counting sort or radix sort. This is because comparison-based algorithms, even when in-place, may require additional memory for temporary variables during the sorting process and need to perform multiple swaps. However, in-place comparison-based sorting algorithms are still commonly used, especially for small arrays or when additional memory is constrained. + +# Interval and knuth formula in shell sort + +--- + +Interval is the range of elements to be sorted at each iteration of the Shell Sort algorithm. It determines the number of elements that will be considered in each iteration and how much progress will be made in each step. + +Knuth Formula, on the other hand, is an approach to determine the shell size at each iteration. It is a formula that helps to determine the smallest gap size for a given array. In the Shell Sort algorithm, the gap size is used to divide the array into halves, and to discover the correct gap size is the key to the algorithm. + +The knuth formula is: + +``` + +Explain +gap_size = n/2 + +for j = 0 to log_n(k) - 1 + + gap_size = gap_size/k + +k = 2 +size = size of the array + +``` + +# Understanding Shell Sort through an Example: + +--- + +Consider an array with input elements array[]={8, 12, 4, 25, 9, 6, 2, 20} + +First we need to initally use a large gap and then repeatedly reduce the gap until it become 1. + +The final pass in sorting is done by implementing insertion sort algorithm. + +In the above example the array has 8 elements. + +So initial gap(h) is n/2 and then n/4 and then n/8 and so on. + +### Step by Step Internal Execution: + +Initial array: {8, 12, 4 25, 9, 6, 2, 20} + +- **First Pass(h= n/2=4)** + - Compare elements that are h position apart and then swap them if necessary + - {**8**, 12, 4 25, **9**, 6, 2, 20} here 8 and 9 are compared. Since they are in order there is no swapping + - {8, **12,** 4 25, 9, **6,** 2, 20}: 12 and 6 are compared and swapped + - {8, 12, **4** 25, 9, 6, **2**, 20}: 4 and 2 are compared and swapped + - {8, 12, 4 **25**, 9, 6, 2, **20**}: 25 and 20 are compared and swapped. + - After swapping the array would be {8, 6, 2, 20, 9, 12, 4, 25} +- **Second Pass(h=n/4=2)** + - Compare elements that are h position apart and then swap them if necessary. + - {**8,** 6, **2**, 20, **9**, 12, **4**, 25} + - Compare 8 and 2 and swap them. The array would be {**2**, 6, **8**, 20, **9**, 12, **4**, 25} + - Compare 6 and 20 next. No swapping required. + - Compare and swap 8 and 9. No swapping required. + - Compare and swap 20 and 12. The array would be {**2**, 6, **8**, 12, **9**, 20, **4**, 25} + - Compare and swap 9 and 4 followed by 20 and 25. + - The Resulting array would be {2, 6, 8, 12, 4, 20, 9, 25} +- **Third Pass (h=n/8=1)** + - Since the gap is one. Compare all the adjacent elements. + - Perform insertion sort on entire array with a gap 1. + - After this step the array is fully sorted :{ 2, 4, 6, 8, 9, 12, 20, 25} +- Final Sorted Array : { 2, 4, 6, 8, 9, 12, 20, 25} + +# Advantages of Shell Sort: + +--- + +1. **Adaptability:** + - Shell Sort is adaptive, meaning its performance is influenced by the initial order of the elements. It tends to perform better on partially sorted or nearly sorted datasets compared to algorithms with a fixed gap. +2. **In-Place Sorting:** + - Shell Sort is an in-place sorting algorithm, meaning it doesn't require additional memory space for auxiliary data structures. It sorts the elements within the array itself, making it memory-efficient. +3. **Ease of Implementation:** + - The algorithm is relatively easy to implement, making it accessible for educational purposes and scenarios where a simple sorting algorithm is sufficient. +4. **Efficiency for Small Datasets:** + - Shell Sort can be efficient for small to moderately sized datasets. Its complexity is generally better than simple algorithms like Bubble Sort or Insertion Sort, especially in scenarios where the dataset is not too large. +5. **Time Complexity Improvements:** + - By using diminishing increment sequences (gap sizes), Shell Sort addresses some of the inefficiencies of simple sorting algorithms. It introduces a form of optimization that helps reduce the number of comparisons and swaps. +6. **No Extra Memory Overhead:** + - Unlike some other advanced sorting algorithms, Shell Sort doesn't require additional memory overhead for recursive calls or complex data structures. +7. **Balanced Trade-Offs:** + - Shell Sort provides a balanced trade-off between simplicity and efficiency. It's more efficient than some basic sorting algorithms while maintaining a level of simplicity that makes it suitable for educational purposes and small-scale applications. +8. **Variability in Gap Sequences:** + - The flexibility to choose different gap sequences allows some customization based on the characteristics of the data being sorted. This adaptability can be an advantage in certain scenarios. + +While Shell Sort has these advantages, it's important to note that for very large datasets or datasets with specific patterns, more advanced sorting algorithms like QuickSort or MergeSort might be preferred for optimal performance. The choice of sorting algorithm depends on the specific requirements and characteristics of the data being sorted. + +# Disadvantages of Shell Sort: + +--- + +1. It is not the most efficient sorting algorithm, particularly for large arrays, as it has a time complexity of O(n⁰) where n is the number of elements in the input array, which is not as efficient as other algorithms like merge sort which has a time complexity of O(n log n). +2. It is not suitable for sorting arrays with irregularly spaced values, like dates or names. +3. It is not very stable, meaning that elements with the same value may be rearranged during sorting, unlike other sorting algorithms like merge sort which is a stable sorting algorithm. +4. It is not an algorithm for large datasets. It is not well-suited for large datasets, as it has a time complexity of O(n⁰) which is significant compared to other algorithms like merge sort or quick sort, which have a time complexity of O(n log n) or O(n log n), respectively. +5. It can be difficult to optimize for large datasets and may require a lot of memory to store large data sets. + +# Real Scenarios of Shell Sort: + +--- + +The Shell sort algorithm can be used in a range of real-world applications, including: + +1. GUI sorting - It can be used to sort display items in a graphical user interface (GUI) like a desktop file explorer or an image gallery, to make it easier for the user to find the item they are looking for. +2. Text sorting - It can be used to sort lines of text, such as in a word processor or a code editor, which can be useful for sorting code files or sorting zip files. +3. Sorting line cards - It can be used to sort 2D line cards, such as those found in a card reader for swiping messages. +4. Sorting strings of text - It can be used to sort strings of text, such as names or addresses, to make it easier to sort the data in a spreadsheet or a database. +5. Sorting array of integers - It can be used to sort an array of integers, for example, sort the account balance of a customer in a database of customer information. +6. Sorting the database of company information - It can be used to sort information of companies like their products, services etc. +7. Sorting strings of characters - It can be used to sort strings of characters, such as passwords, to make it easier to manage a password book. +8. Shell sort is used in Linux Kernel because it does not use a call stack.( A call stack is a specialized data structure that stores information about active subroutines or functions in a program. ) +9. Shell sort is used in bzip2 compressor to avoid problems that could come when sorting algorithms exceed a language’s recursion depth. + +# Optimizing Shell Sort: + +--- + +There are several ways to optimize the Shell sort algorithm: + +1. Reduce the number of iterations - One of the most common ways to optimize Shell sort is to reduce the number of iterations. This can be done by choosing a smaller initial shell size or by incrementing the shell size more slowly. The smaller the shell size, the fewer iterations it will take to sort the array. +2. Use a more efficient algorithm for smaller subarrays - Another way to optimize Shell sort is to use a more efficient algorithm for smaller subarrays, such as insertion sort or bubble sort. These algorithms have a time complexity of O(n) and are particularly efficient for small arrays. +3. Parallelize the sorting process - Shell sort can be parallelized, meaning that multiple elements can be sorted at the same time. by dividing the array into multiple chunks and sorting them simultaneously using multiple processors or threads. +4. Use a hybrid approach - Shell sort can be combined with other sorting algorithms, such as quicksort or mergesort, to create a hybrid sorting algorithm. In this approach, Shell sort is used to sort small, irregularly spaced arrays and other sorting algorithm to sort larger, regularly spaced arrays. +5. Implement a more efficient data structure - A more efficient data structure, such as a heap or a priority queue, can also help to optimize the Shell sort algorithm. These data structures allow for more efficient comparison and manipulation of elements, which can lead to faster sorting times. +6. Optimize the memory usage - The memory usage of the shell sort can be sized according to the size of the input array to optimize the computation. + +Time and Space complexity + +The time complexity of the provided VSDShellSort algorithm is O(n log n) on average, and O(n^2) in the worst case, where n is the length of the input array. + +In the worst case, when the shell size is not chosen appropriately, the algorithm would repeatedly compare the first element of the unsorted sub-array with all other elements in the sub-array until it finds the correct position, resulting in O(n^2) worst-case time complexity. + +The space complexity of the VSDShellSort algorithm is O(1) because it sorts the input array in-place, using only a constant amount of additional space. + +# Python code for Shell Sort: + +--- + +``` +'''Copyrights to venkys.io +For more information, visite https://venkys.io"/ + +Python program to sort a given array in order using Shell sort algorithm.''' + +# Stable : No +# Inplace : Yes +# Adaptive : Yes + +# Space complexity: O(1) + +#Time Complexity:O(n^2) in the worst-case scenario, and O(n log n) in the average case scenario. + +def VSDShellSort(arr,n): + shellsize=8 # Initialize the initial gap size for Shell Sort + while(shellsize>=1):# Continue the loop until the gap size becomes 1 + i=shellsize + k=0 + while(i=0: + if(arr[j]>key): + arr[j+shellsize]=arr[j] # Shift elements greater than the key to the right + else: + break + j-=shellsize + arr[j+shellsize]=key # Insert the key at its correct position in the sorted sequence + if(i+shellsize)>=n: + k+=1 + i=k+shellsize # Move to the next group of elements for comparison + else: + i+=shellsize + shellsize=shellsize//2 # Reduce the gap size by half in each iteration + print(*arr,sep=" ") # Print the sorted array + +def main(): + try: + # Input the number of elements + n = int(input("Enter the number of elements: ")) + # Check if the entered number of elements is not a positive integer + if n <= 0: + raise ValueError("Number of elements should be a positive integer.") + + # Input the elements of the array and convert them to integers + arr = list(map(int, input("Enter the elements separated by space: ").split())) + + # Check if the number of elements entered matches the specified count + if len(arr) != n: + raise ValueError("Number of elements entered doesn't match the specified count.") + + # Call the VSDShellSort function to sort the array + VSDShellSort(arr, n) + + except ValueError as e: + # Handle the case where an error occurs (e.g., non-integer input) + print(f"Error: {e}") + +# Check if the script is executed as the main program +if __name__ == "__main__": + main() +``` + +Note: The choice of gap sequence affects its adaptability, and in this case, it uses a fixed gap sequence (**`shellsize=8`** and then halves the gap in each iteration). + +1. We initialize an shell size with a value (shellsize=8) +2. We run a while loop while the value of shellsize is greater than 1. This loop iterates n times. while(shellsize>=1): +3. initialize two variables i and k, starting at their initial values. i=shellsize k=0 +4. Run another while loop while i is less than n and k is less than shellsize. while(i=0: +7. We check if the value at position j in the array is greater than the key. if(arr[j]>key): +8. If it is, we assign the value at position j + shellsize to the variable next\_j. next\_j=arr[j+shellsize] +9. We then align the value at position (j + next\_j) to position j using another while loop, which iterates (shellsize - 1) times. while(next\_j>=j+1): arr[j]=next\_j-1 next\_j=j+shellsize j+=shellsize +10. Once we have iterated the while loop, we exit the inner while loop by using the break statement. This happens if the value at position j is not greater than the key. +11. Finally, we assign the value at position j + shellsize to the variable key and increment the value of j. arr[j+shellsize]=key j+=1 +12. If the value of i is equal to n, we increment the value of k and set the value of i to k + shellsize. if(i+shellsize)>=n + +## Sample Test Cases: + +- **Valid Input Case:** +Enter the number of elements: 5 +Enter the elements separated by space: 12 4 6 8 1 +1 4 6 8 12 +- **Invalid Number of Elements Case:** +Enter the number of elements: -3 +Error: Number of elements should be a positive integer. +- **Mismatched Element Count Case:** +Enter the number of elements: 4 +Enter the elements separated by space: 2 4 6 +Error: Number of elements entered doesn't match the specified count. +- **Non-Integer Element Case:** +Enter the number of elements: 3 +Enter the elements separated by space: 7 a 2 +Error: invalid literal for int() with base 10: 'a' + +# C++ code for Shell Sort: + +--- + +``` +/*Copyrights to venkys.io +For more information, visit https://venkys.io"/ + +C++ program to sort a given array in order using Shell sort algorithm. */ + +// Stable: No +// Inplace: Yes +// Adaptive: Yes + +// Space complexity: O(1) - sorts in place + +// Time Complexity: O(n^2) in the worst-case scenario, and O(n log n) in the average case scenario. + +#include +#include // Container to hold elements +#include // String representation for input +#include // To convert string input into integer +using namespace std; // Namespace identifies the code as part of the standard library + +// Function to perform Shell Sort on the given array +void shellSort(int arr[], int n) { + int shellsize = 8; + + // Iterate through decreasing gap sizes until the gap is 1 + while (shellsize >= 1) { + for (int i = shellsize, k = 0; i < n && k < shellsize;) { + int key = arr[i]; + int j = i - shellsize; + + // Compare and shift elements to make room for the key + for (; j >= 0; j -= shellsize) { + if (arr[j] > key) { + arr[j + shellsize] = arr[j]; + } else { + break; + } + } + + // Insert the key at the correct position in the sorted sequence + arr[j + shellsize] = key; + + // Update indices for the next iteration + if (i + shellsize >= n) { + k += 1; + i = k + shellsize; + } else { + i += shellsize; + } + } + + // Reduce the gap size for the next iteration + shellsize = shellsize / 2; + } + + // Print the sorted array + for (int i = 0; i < n; i++) { + cout << arr[i] << " "; + } + cout << endl; +} + +int main() { + string input; + + // Prompt the user to enter the elements separated by space + cout << "Enter the elements separated by space: "; + + // Read the entire line of input + getline(cin, input); + + // If the input is empty, print an error message and exit + if (input.empty()) { + cout << "Error: Empty input. Please provide elements to sort." << endl; + return 1; // Return 1 to indicate an error + } + + // Parse the input string and convert it into an array of integers + stringstream ss(input); + vector elements; + int num; + + // Continue parsing until the end of the stringstream + while (ss >> num) { + elements.push_back(num); + } + + // If the parsed elements vector is empty, print an error message and exit + if (elements.empty()) { + cout << "Error: No valid integers found in the input. Please provide valid elements." << endl; + return 1; // Return 1 to indicate an error + } + + int n = elements.size(); + + // If the array size is less than or equal to 0, print an error message and exit + if (n <= 0) { + cout << "Error: Invalid array size. Please enter a positive integer for the array size." << endl; + return 1; // Return 1 to indicate an error + } + + int arr[n]; + + // Copy elements from the vector to the array + for (int i = 0; i < n; i++) { + arr[i] = elements[i]; + } + + // Call the shellSort function to sort the array + shellSort(arr, n); + + return 0; // Return 0 to indicate successful execution of the program +} +``` + +- The provided Shell Sort implementation is not guaranteed to be stable. Stability in sorting algorithms means that the relative order of equal elements is preserved, and Shell Sort does not explicitly handle this requirement. +- The **`shellSort`** function implements the Shell Sort algorithm. It starts with a gap size of 8 and iteratively reduces the gap until it becomes 1. +- The outer loop controls the gap size, and the inner loops perform insertion sort within each subset defined by the current gap. +- The sorted array is printed after the sorting process. + +# Java code for Shell sort: + +--- + +``` +/* Copyrights to venkys.io */ +/* For more programs, visit venkys.io */ +/* Java program for Shell sort */ + +// Stable: No +// Inplace: Yes +// Adaptive: Yes + +// Space complexity: O(1) + +// Time Complexity: O(n^2) in the worst-case scenario, and O(n log n) in the average case scenario. + +import java.util.Scanner; // Importing Scanner class from java.util package for user input + +public class ShellSort { + static int n; // Size of the array + static int[] arr; // Array of numbers to be sorted + + // Function to perform shell sort + public static void shellSort() { + int shellSize = 8; // Initial shell size + + // Continue the sorting process until the shell size becomes 0 + while (shellSize >= 1) { + // Iterate through the array with the current shell size + for (int i = shellSize, k = 0; i < n && k < shellSize;) { + int key = arr[i];// Store the current element to be inserted + int j = i - shellSize; + + // Move elements greater than key to the right until a smaller or equal element is found, + // or until the beginning of the subarray is reached. + for (; j >= 0; j -= shellSize) { + if (arr[j] > key) { + arr[j + shellSize] = arr[j];// Shift the current element to the right + } else { + break; // Stop shifting if a smaller or equal element is found + } + } + arr[j + shellSize] = key;// Insert the stored element at its correct position + + // Move to the next position in the array considering the shell size + if (i + shellSize >= n) { + k += 1; + i = k + shellSize; + } else { + i += shellSize; + } + } + + // Reduce the shell size for the next iteration + shellSize = shellSize / 2; + } + } + + // Function to print output + public static void printOutput() { + System.out.println("The sorted order is:"); + for (int i = 0; i < arr.length; i++) { + System.out.print(arr[i] + " "); + } + System.out.println(); + } + + public static void main(String args[]) { + // Create a Scanner object to read user input from the console. + Scanner scanner = new Scanner(System.in); + + try { + // Input the elements separated by space + System.out.print("Enter the elements separated by space: "); + // Read the entire line as input. + String input = scanner.nextLine(); + + // Check for null or empty input + if (input == null || input.trim().isEmpty()) { + System.out.println("Error: Empty input. Please enter valid elements."); + return; // Exit the program to handle the error. + } + + // Split the input string into an array of string elements based on space. + String[] elements = input.split(" "); + n = elements.length;// Set the size of the array based on the number of elements. + arr = new int[n];// Initialize the array to store the parsed integers. + + // Parse input elements to integers + for (int i = 0; i < n; i++) { + try { + // Parse each element as an integer and assign it to the array. + arr[i] = Integer.parseInt(elements[i]); + } catch (NumberFormatException e) { + // Handle the case where an element is not a valid integer. + System.out.println("Error: Invalid input. Please enter valid integers."); + return;// Exit the program to handle the error. + } + } + + // Call the shellSort function to perform the sorting. + shellSort(); + + // Call the printOutput function to display the sorted array. + printOutput(); + } finally { + // Close the scanner to avoid resource leaks + if (scanner != null) { + scanner.close(); + } + } + } +} +``` + +- The **`VSDSort`** function implements the Shell Sort algorithm in Java. It starts with a gap size of 8 and iteratively reduces the gap until it becomes 1. +- The outer loop controls the gap size, and the inner loops perform insertion sort within each subset defined by the current gap. +- The sorted array is printed after the sorting process using the **`VSDprintOutput`** function. + +Sample Test Case 1: +Enter the elements separated by space: 5 2 9 1 5 6 +The sorted order is: +1 2 5 5 6 9 + +Sample Test Case 2: +Enter the elements separated by space: 10 5 3 8 2 7 9 +The sorted order is: +2 3 5 7 8 9 10 + +Sample Test Case 3 (Empty Input): +Enter the elements separated by space: +Error: Empty input. Please enter valid elements. + +Sample Test Case 4 (Invalid Input - Non-Integer Element): +Enter the elements separated by space: 1 2 3 a 5 +Error: Invalid input. Please enter valid integers. + +Sample Test Case 5 (Invalid Input - Empty Element): +Enter the elements separated by space: 1 2 3 5 +Error: Invalid input. Please enter valid integers. diff --git a/Sorting/Medium/Shell Sort/ShellSort.java b/Sorting/Medium/Shell Sort/ShellSort.java new file mode 100644 index 00000000..caafbb72 --- /dev/null +++ b/Sorting/Medium/Shell Sort/ShellSort.java @@ -0,0 +1,109 @@ +/* Copyrights to venkys.io */ +/* For more programs, visit venkys.io */ +/* Java program for Shell sort */ + +// Stable: No +// Inplace: Yes +// Adaptive: Yes + +// Space complexity: O(1) + +// Time Complexity: O(n^2) in the worst-case scenario, and O(n log n) in the average case scenario. + +import java.util.Scanner; // Importing Scanner class from java.util package for user input + +public class ShellSort { + static int n; // Size of the array + static int[] arr; // Array of numbers to be sorted + + // Function to perform shell sort + public static void shellSort() { + int shellSize = 8; // Initial shell size + + // Continue the sorting process until the shell size becomes 0 + while (shellSize >= 1) { + // Iterate through the array with the current shell size + for (int i = shellSize, k = 0; i < n && k < shellSize;) { + int key = arr[i];// Store the current element to be inserted + int j = i - shellSize; + + // Move elements greater than key to the right until a smaller or equal element is found, + // or until the beginning of the subarray is reached. + for (; j >= 0; j -= shellSize) { + if (arr[j] > key) { + arr[j + shellSize] = arr[j];// Shift the current element to the right + } else { + break; // Stop shifting if a smaller or equal element is found + } + } + arr[j + shellSize] = key;// Insert the stored element at its correct position + + // Move to the next position in the array considering the shell size + if (i + shellSize >= n) { + k += 1; + i = k + shellSize; + } else { + i += shellSize; + } + } + + // Reduce the shell size for the next iteration + shellSize = shellSize / 2; + } + } + + // Function to print output + public static void printOutput() { + System.out.println("The sorted order is:"); + for (int i = 0; i < arr.length; i++) { + System.out.print(arr[i] + " "); + } + System.out.println(); + } + + public static void main(String args[]) { + // Create a Scanner object to read user input from the console. + Scanner scanner = new Scanner(System.in); + + try { + // Input the elements separated by space + System.out.print("Enter the elements separated by space: "); + // Read the entire line as input. + String input = scanner.nextLine(); + + // Check for null or empty input + if (input == null || input.trim().isEmpty()) { + System.out.println("Error: Empty input. Please enter valid elements."); + return; // Exit the program to handle the error. + } + + // Split the input string into an array of string elements based on space. + String[] elements = input.split(" "); + n = elements.length;// Set the size of the array based on the number of elements. + arr = new int[n];// Initialize the array to store the parsed integers. + + // Parse input elements to integers + for (int i = 0; i < n; i++) { + try { + // Parse each element as an integer and assign it to the array. + arr[i] = Integer.parseInt(elements[i]); + } catch (NumberFormatException e) { + // Handle the case where an element is not a valid integer. + System.out.println("Error: Invalid input. Please enter valid integers."); + return;// Exit the program to handle the error. + } + } + + // Call the shellSort function to perform the sorting. + shellSort(); + + // Call the printOutput function to display the sorted array. + printOutput(); + } finally { + // Close the scanner to avoid resource leaks + if (scanner != null) { + scanner.close(); + } + } + } +} diff --git a/Sorting/Medium/Shell Sort/shellsort.cpp b/Sorting/Medium/Shell Sort/shellsort.cpp new file mode 100644 index 00000000..e64c7dab --- /dev/null +++ b/Sorting/Medium/Shell Sort/shellsort.cpp @@ -0,0 +1,112 @@ +/*Copyrights to venkys.io +For more information, visit https://venkys.io"/ + +C++ program to sort a given array in order using Shell sort algorithm. */ + +// Stable: No +// Inplace: Yes +// Adaptive: Yes + +// Space complexity: O(1) - sorts in place + +// Time Complexity: O(n^2) in the worst-case scenario, and O(n log n) in the average case scenario. + +#include +#include // Container to hold elements +#include // String representation for input +#include // To convert string input into integer +using namespace std; // Namespace identifies the code as part of the standard library + +// Function to perform Shell Sort on the given array +void shellSort(int arr[], int n) { + int shellsize = 8; + + // Iterate through decreasing gap sizes until the gap is 1 + while (shellsize >= 1) { + for (int i = shellsize, k = 0; i < n && k < shellsize;) { + int key = arr[i]; + int j = i - shellsize; + + // Compare and shift elements to make room for the key + for (; j >= 0; j -= shellsize) { + if (arr[j] > key) { + arr[j + shellsize] = arr[j]; + } else { + break; + } + } + + // Insert the key at the correct position in the sorted sequence + arr[j + shellsize] = key; + + // Update indices for the next iteration + if (i + shellsize >= n) { + k += 1; + i = k + shellsize; + } else { + i += shellsize; + } + } + + // Reduce the gap size for the next iteration + shellsize = shellsize / 2; + } + + // Print the sorted array + for (int i = 0; i < n; i++) { + cout << arr[i] << " "; + } + cout << endl; +} + +int main() { + string input; + + // Prompt the user to enter the elements separated by space + cout << "Enter the elements separated by space: "; + + // Read the entire line of input + getline(cin, input); + + // If the input is empty, print an error message and exit + if (input.empty()) { + cout << "Error: Empty input. Please provide elements to sort." << endl; + return 1; // Return 1 to indicate an error + } + + // Parse the input string and convert it into an array of integers + stringstream ss(input); + vector elements; + int num; + + // Continue parsing until the end of the stringstream + while (ss >> num) { + elements.push_back(num); + } + + // If the parsed elements vector is empty, print an error message and exit + if (elements.empty()) { + cout << "Error: No valid integers found in the input. Please provide valid elements." << endl; + return 1; // Return 1 to indicate an error + } + + int n = elements.size(); + + // If the array size is less than or equal to 0, print an error message and exit + if (n <= 0) { + cout << "Error: Invalid array size. Please enter a positive integer for the array size." << endl; + return 1; // Return 1 to indicate an error + } + + int arr[n]; + + // Copy elements from the vector to the array + for (int i = 0; i < n; i++) { + arr[i] = elements[i]; + } + + // Call the shellSort function to sort the array + shellSort(arr, n); + + return 0; // Return 0 to indicate successful execution of the program +} diff --git a/Sorting/Medium/Shell Sort/shellsort.py b/Sorting/Medium/Shell Sort/shellsort.py new file mode 100644 index 00000000..5222ad52 --- /dev/null +++ b/Sorting/Medium/Shell Sort/shellsort.py @@ -0,0 +1,62 @@ +'''Copyrights to venkys.io +For more information, visite https://venkys.io"/ + +Python program to sort a given array in order using Shell sort algorithm.''' + +# Stable : No +# Inplace : Yes +# Adaptive : Yes + +# Space complexity: O(1) + +#Time Complexity:O(n^2) in the worst-case scenario, and O(n log n) in the average case scenario. + +def VSDShellSort(arr,n): + shellsize=8 # Initialize the initial gap size for Shell Sort + while(shellsize>=1):# Continue the loop until the gap size becomes 1 + i=shellsize + k=0 + while(i=0: + if(arr[j]>key): + arr[j+shellsize]=arr[j] # Shift elements greater than the key to the right + else: + break + j-=shellsize + arr[j+shellsize]=key # Insert the key at its correct position in the sorted sequence + if(i+shellsize)>=n: + k+=1 + i=k+shellsize # Move to the next group of elements for comparison + else: + i+=shellsize + shellsize=shellsize//2 # Reduce the gap size by half in each iteration + print(*arr,sep=" ") # Print the sorted array + + +def main(): + try: + # Input the number of elements + n = int(input("Enter the number of elements: ")) + # Check if the entered number of elements is not a positive integer + if n <= 0: + raise ValueError("Number of elements should be a positive integer.") + + # Input the elements of the array and convert them to integers + arr = list(map(int, input("Enter the elements separated by space: ").split())) + + # Check if the number of elements entered matches the specified count + if len(arr) != n: + raise ValueError("Number of elements entered doesn't match the specified count.") + + # Call the VSDShellSort function to sort the array + VSDShellSort(arr, n) + + except ValueError as e: + # Handle the case where an error occurs (e.g., non-integer input) + print(f"Error: {e}") + +# Check if the script is executed as the main program +if __name__ == "__main__": + main()