From ba65c9c52b013865b005d3e2a25cd56144ef93e9 Mon Sep 17 00:00:00 2001 From: Yashgabani845 Date: Fri, 7 Jun 2024 10:42:01 +0530 Subject: [PATCH 1/3] sorting algorithm added --- dsa/Algorithms/Sorting/_category_.json | 8 + dsa/Algorithms/Sorting/bubble-sort.md | 179 ++++++++++++++ dsa/Algorithms/Sorting/counting-sort.md | 219 +++++++++++++++++ dsa/Algorithms/Sorting/insertion-sort.md | 182 ++++++++++++++ dsa/Algorithms/Sorting/merge-sort.md | 298 +++++++++++++++++++++++ dsa/Algorithms/Sorting/quick-sort.md | 231 ++++++++++++++++++ dsa/Algorithms/Sorting/selection-sort.md | 188 ++++++++++++++ 7 files changed, 1305 insertions(+) create mode 100644 dsa/Algorithms/Sorting/_category_.json create mode 100644 dsa/Algorithms/Sorting/bubble-sort.md create mode 100644 dsa/Algorithms/Sorting/counting-sort.md create mode 100644 dsa/Algorithms/Sorting/insertion-sort.md create mode 100644 dsa/Algorithms/Sorting/merge-sort.md create mode 100644 dsa/Algorithms/Sorting/quick-sort.md create mode 100644 dsa/Algorithms/Sorting/selection-sort.md diff --git a/dsa/Algorithms/Sorting/_category_.json b/dsa/Algorithms/Sorting/_category_.json new file mode 100644 index 000000000..21c2983cf --- /dev/null +++ b/dsa/Algorithms/Sorting/_category_.json @@ -0,0 +1,8 @@ +{ + "label": "Sorting Algorithms", + "position": 1, + "link": { + "type": "generated-index", + "description": "In This section all the Sortingt Algorithms are defined in DSA " + } + } \ No newline at end of file diff --git a/dsa/Algorithms/Sorting/bubble-sort.md b/dsa/Algorithms/Sorting/bubble-sort.md new file mode 100644 index 000000000..8ffbb3770 --- /dev/null +++ b/dsa/Algorithms/Sorting/bubble-sort.md @@ -0,0 +1,179 @@ +--- +id: bubble-sort +title: Bubble Sort +sidebar_label: Bubble Sort +tags: [python, java, c++, javascript, programming, algorithms, sorting, data structures, tutorial, in-depth] +description: In this tutorial, we will learn about Bubble Sort and its implementation in Python, Java, C++, and JavaScript with detailed explanations and examples. +--- + +# Bubble Sort + +Bubble Sort is a simple comparison-based sorting algorithm. It is named for the way larger elements "bubble" to the top of the list. This tutorial will cover the basics of Bubble Sort, its applications, and how to implement it in Python, Java, C++, and JavaScript. We will also delve into various optimizations and advanced use cases. + +## Introduction to Bubble Sort + +Bubble Sort is an elementary algorithm suitable for small data sets. It repeatedly steps through the list, compares adjacent elements, and swaps them if they are in the wrong order. The pass through the list is repeated until the list is sorted. + +## How Bubble Sort Works + +- **Step 1**: Compare the first two elements of the array. +- **Step 2**: If the first element is greater than the second, swap them. +- **Step 3**: Move to the next pair of elements, compare them and swap if necessary. +- **Step 4**: Continue this process for each pair of adjacent elements until the end of the array. +- **Step 5**: Repeat the process for the entire array until no swaps are needed. + + +![bubble sort](https://runestone.academy/ns/books/published/pythonds/_images/bubblepass.png) +## Pseudocode for Bubble Sort + +Here is the pseudocode for Bubble Sort: + +``` +function bubbleSort(array): + for i from 0 to length(array) - 1: + for j from 0 to length(array) - i - 1: + if array[j] > array[j + 1]: + swap(array[j], array[j + 1]) + return array +``` + +## Implementing Bubble Sort + +### Python Implementation + +```python +def bubble_sort(array): + n = len(array) + for i in range(n): + for j in range(0, n-i-1): + if array[j] > array[j + 1]: + array[j], array[j + 1] = array[j + 1], array[j] + return array + +arr = [64, 34, 25, 12, 22, 11, 90] +print(bubble_sort(arr)) +``` + +### Java Implementation + +```java +public class BubbleSort { + + public static void bubbleSort(int[] array) { + int n = array.length; + for (int i = 0; i < n-1; i++) { + for (int j = 0; j < n-i-1; j++) { + if (array[j] > array[j + 1]) { + int temp = array[j]; + array[j] = array[j + 1]; + array[j + 1] = temp; + } + } + } + } + + public static void main(String[] args) { + int[] arr = {64, 34, 25, 12, 22, 11, 90}; + bubbleSort(arr); + for (int num : arr) { + System.out.print(num + " "); + } + } +} +``` + +### C++ Implementation + +```cpp +#include +using namespace std; + +void bubbleSort(int array[], int length) { + for (int i = 0; i < length-1; i++) { + for (int j = 0; j < length-i-1; j++) { + if (array[j] > array[j + 1]) { + int temp = array[j]; + array[j] = array[j + 1]; + array[j + 1] = temp; + } + } + } +} + +int main() { + int arr[] = {64, 34, 25, 12, 22, 11, 90}; + int length = sizeof(arr) / sizeof(arr[0]); + bubbleSort(arr, length); + for (int i = 0; i < length; i++) { + cout << arr[i] << " "; + } + return 0; +} +``` + +### JavaScript Implementation + +```javascript +function bubbleSort(array) { + let n = array.length; + for (let i = 0; i < n-1; i++) { + for (let j = 0; j < n-i-1; j++) { + if (array[j] > array[j + 1]) { + let temp = array[j]; + array[j] = array[j + 1]; + array[j + 1] = temp; + } + } + } + return array; +} + +let arr = [64, 34, 25, 12, 22, 11, 90]; +console.log(bubbleSort(arr)); +``` + +## Time Complexity Analysis + +- **Best Case**: $O(n)$ (when the array is already sorted) +- **Worst Case**: $O(n^2)$ (when the array is sorted in reverse order) +- **Average Case**: $O(n^2)$ + +## Space Complexity Analysis + +- **Space Complexity**: $O(1)$ (since it sorts in place and requires only a constant amount of extra memory) + +## Applications of Bubble Sort + +- **Educational Tools**: Bubble Sort is often used as an introduction to sorting algorithms due to its simplicity. +- **Small Data Sets**: Efficient for sorting small arrays or lists. +- **Learning Tool**: Useful for educational purposes to understand the basics of sorting algorithms. + +## Optimizations and Variations + +### Optimized Bubble Sort + +An optimized version of Bubble Sort can stop the algorithm if the inner loop didn’t cause any swap, indicating that the array is already sorted. + +### Cocktail Shaker Sort + +Cocktail Shaker Sort, also known as bidirectional Bubble Sort, extends Bubble Sort by operating in both directions on each pass through the list, first left to right, then right to left. + +### Comb Sort + +Comb Sort is an improvement on Bubble Sort. It eliminates turtles, or small values near the end of the list, since these slow the sorting process down. Comb Sort improves on Bubble Sort by using gaps in the comparison. + +## Practical Considerations + +### Stability + +Bubble Sort is a stable sorting algorithm, meaning it maintains the relative order of equal elements. + +### Use Cases + +- Bubble Sort is used when the array size is small. +- It is used when additional memory space is not available. +- It is useful when the array is already partially sorted. + +## Conclusion + +In this tutorial, we covered the fundamentals of Bubble Sort, its implementation in Python, Java, C++, and JavaScript, and various optimizations and applications. Bubble Sort is a simple sorting algorithm, ideal for understanding basic sorting concepts and practicing algorithm implementation. By mastering Bubble Sort, you can effectively handle small sorting tasks in your projects. \ No newline at end of file diff --git a/dsa/Algorithms/Sorting/counting-sort.md b/dsa/Algorithms/Sorting/counting-sort.md new file mode 100644 index 000000000..9b4b20438 --- /dev/null +++ b/dsa/Algorithms/Sorting/counting-sort.md @@ -0,0 +1,219 @@ +--- +id: counting-sort +title: Counting Sort +sidebar_label: Counting Sort +tags: [python, java, c++, javascript, programming, algorithms, sorting, data structures, tutorial, in-depth] +description: In this tutorial, we will learn about Counting Sort and its implementation in Python, Java, C++, and JavaScript with detailed explanations and examples. +--- + +# Counting Sort + +Counting Sort is a non-comparison-based sorting algorithm that works efficiently for sorting integers or objects that can be represented as integers within a specific range. This tutorial will cover the basics of Counting Sort, its applications, and how to implement it in Python, Java, C++, and JavaScript. We will also delve into various optimizations and advanced use cases. + +## Introduction to Counting Sort + +Counting Sort is a stable, non-comparison-based sorting algorithm that was introduced by Harold H. Seward in 1954. It works by counting the occurrences of each unique element in the input array and then using this count information to place the elements in the correct position in the output array. + +## How Counting Sort Works + +- **Step 1: Find the Range**: Determine the range of the input data (i.e., the minimum and maximum values). +- **Step 2: Count Occurrences**: Create a count array to store the count of each unique element. +- **Step 3: Accumulate Counts**: Modify the count array such that each element at each index stores the sum of previous counts. +- **Step 4: Place Elements**: Build the output array by placing elements at their correct positions using the count array. + + +## Pseudocode for Counting Sort + +Here is the pseudocode for Counting Sort: + +``` +function countingSort(arr): + find the maximum element (max) in arr + create a count array of size max + 1 and initialize it with zeros + + for each element in arr: + increment the count of element in count array + + for each index in count array: + accumulate the counts + + for each element in arr (in reverse order): + place the element in the output array using the count array + decrement the count of element in count array + + return output array +``` + +## Implementing Counting Sort + +### Python Implementation + +```python +def counting_sort(arr): + max_val = max(arr) + count = [0] * (max_val + 1) + output = [0] * len(arr) + + for num in arr: + count[num] += 1 + + for i in range(1, len(count)): + count[i] += count[i - 1] + + for num in reversed(arr): + output[count[num] - 1] = num + count[num] -= 1 + + return output + +arr = [4, 2, 2, 8, 3, 3, 1] +sorted_arr = counting_sort(arr) +print(f"Sorted array is: {sorted_arr}") +``` + +### Java Implementation + +```java +import java.util.Arrays; + +public class CountingSort { + + public static void countingSort(int[] arr) { + int max = Arrays.stream(arr).max().getAsInt(); + int[] count = new int[max + 1]; + int[] output = new int[arr.length]; + + for (int num : arr) { + count[num]++; + } + + for (int i = 1; i < count.length; i++) { + count[i] += count[i - 1]; + } + + for (int i = arr.length - 1; i >= 0; i--) { + output[count[arr[i]] - 1] = arr[i]; + count[arr[i]]--; + } + + System.arraycopy(output, 0, arr, 0, arr.length); + } + + public static void main(String[] args) { + int[] arr = {4, 2, 2, 8, 3, 3, 1}; + countingSort(arr); + System.out.println("Sorted array: " + Arrays.toString(arr)); + } +} +``` + +### C++ Implementation + +```cpp +#include +#include +#include + +using namespace std; + +void countingSort(vector& arr) { + int max_val = *max_element(arr.begin(), arr.end()); + vector count(max_val + 1, 0); + vector output(arr.size(), 0); + + for (int num : arr) { + count[num]++; + } + + for (int i = 1; i < count.size(); i++) { + count[i] += count[i - 1]; + } + + for (int i = arr.size() - 1; i >= 0; i--) { + output[count[arr[i]] - 1] = arr[i]; + count[arr[i]]--; + } + + for (int i = 0; i < arr.size(); i++) { + arr[i] = output[i]; + } +} + +int main() { + vector arr = {4, 2, 2, 8, 3, 3, 1}; + countingSort(arr); + cout << "Sorted array: "; + for (int num : arr) { + cout << num << " "; + } + return 0; +} +``` + +### JavaScript Implementation + +```javascript +function countingSort(arr) { + let max = Math.max(...arr); + let count = new Array(max + 1).fill(0); + let output = new Array(arr.length); + + arr.forEach(num => count[num]++); + + for (let i = 1; i < count.length; i++) { + count[i] += count[i - 1]; + } + + for (let i = arr.length - 1; i >= 0; i--) { + output[count[arr[i]] - 1] = arr[i]; + count[arr[i]]--; + } + + return output; +} + +let arr = [4, 2, 2, 8, 3, 3, 1]; +let sortedArr = countingSort(arr); +console.log("Sorted array:", sortedArr); +``` + +## Time Complexity Analysis + +- **Best Case**: $O(n + k)$ (where n is the number of elements and k is the range of the input) +- **Worst Case**: $O(n + k)$ +- **Average Case**: $O(n + k)$ + +## Space Complexity Analysis + +- **Space Complexity**: $O(n + k)$ (for the count and output arrays) + +## Applications of Counting Sort + +- **Sorting Integers**: Counting Sort is ideal for sorting integers or objects that can be represented as integers. +- **Large Data Sets**: Efficient for sorting large data sets with a limited range of values. +- **Stability**: Maintains the relative order of equal elements, making it suitable for sorting data with multiple keys. + +## Optimizations and Variations + +### Improved Counting Sort + +Improved Counting Sort can be implemented to handle negative numbers by offsetting the count array to accommodate the negative values. + +### Radix Sort + +Counting Sort can be used as a subroutine in Radix Sort, which sorts numbers digit by digit. + +## Practical Considerations + +### Stability + +Counting Sort is a stable sorting algorithm, meaning it maintains the relative order of equal elements. + +### Use Cases + +- When the range of input data (k) is not significantly larger than the number of elements (n). +- When stability is required in sorting. + +## Conclusion + +In this tutorial, we covered the fundamentals of Counting Sort, its implementation in Python, Java, C++, and JavaScript, and various optimizations and applications. Counting Sort is a powerful and efficient sorting algorithm for specific use cases, particularly when the range of input values is limited. By mastering Counting Sort, you can handle sorting tasks effectively in your projects. \ No newline at end of file diff --git a/dsa/Algorithms/Sorting/insertion-sort.md b/dsa/Algorithms/Sorting/insertion-sort.md new file mode 100644 index 000000000..338c9333d --- /dev/null +++ b/dsa/Algorithms/Sorting/insertion-sort.md @@ -0,0 +1,182 @@ +--- +id: insertion-sort +title: Insertion Sort +sidebar_label: Insertion Sort +tags: [python, java, c++, javascript, programming, algorithms, sorting, data structures, tutorial, in-depth] +description: In this tutorial, we will learn about Insertion Sort and its implementation in Python, Java, C++, and JavaScript with detailed explanations and examples. +--- + +# Insertion Sort + +Insertion Sort is a simple and intuitive sorting algorithm that builds the final sorted array one item at a time. It is much like sorting playing cards in your hands. This tutorial will cover the basics of Insertion Sort, its applications, and how to implement it in Python, Java, C++, and JavaScript. We will also delve into various optimizations and advanced use cases. + +## Introduction to Insertion Sort + +Insertion Sort is an efficient algorithm for small data sets. It is much less efficient on large lists than more advanced algorithms such as quicksort, heapsort, or merge sort. Insertion Sort works by dividing the input list into two parts: a sorted and an unsorted part. The algorithm iteratively takes an element from the unsorted part and inserts it into the correct position in the sorted part. + +## How Insertion Sort Works + +- **Step 1**: Iterate from the second element to the last element of the array. +- **Step 2**: Compare the current element with the elements in the sorted part and find its correct position. +- **Step 3**: Shift all elements in the sorted part that are greater than the current element one position to the right. +- **Step 4**: Insert the current element into its correct position. +- **Step 5**: Repeat until the array is sorted. + +![insetion sort](https://runestone.academy/ns/books/published/pythonds/_images/insertionsort.png) + +## Pseudocode for Insertion Sort + +Here is the pseudocode for Insertion Sort: + +``` +function insertionSort(array): + for i from 1 to length(array) - 1: + key = array[i] + j = i - 1 + while j >= 0 and array[j] > key: + array[j + 1] = array[j] + j = j - 1 + array[j + 1] = key + return array +``` + +## Implementing Insertion Sort + +### Python Implementation + +```python +def insertion_sort(array): + for i in range(1, len(array)): + key = array[i] + j = i - 1 + while j >= 0 and key < array[j]: + array[j + 1] = array[j] + j -= 1 + array[j + 1] = key + return array + +arr = [12, 11, 13, 5, 6] +print(insertion_sort(arr)) +``` + +### Java Implementation + +```java +public class InsertionSort { + + public static void insertionSort(int[] array) { + for (int i = 1; i < array.length; i++) { + int key = array[i]; + int j = i - 1; + while (j >= 0 && array[j] > key) { + array[j + 1] = array[j]; + j--; + } + array[j + 1] = key; + } + } + + public static void main(String[] args) { + int[] arr = {12, 11, 13, 5, 6}; + insertionSort(arr); + for (int num : arr) { + System.out.print(num + " "); + } + } +} +``` + +### C++ Implementation + +```cpp +#include +using namespace std; + +void insertionSort(int array[], int length) { + for (int i = 1; i < length; i++) { + int key = array[i]; + int j = i - 1; + while (j >= 0 && array[j] > key) { + array[j + 1] = array[j]; + j = j - 1; + } + array[j + 1] = key; + } +} + +int main() { + int arr[] = {12, 11, 13, 5, 6}; + int length = sizeof(arr) / sizeof(arr[0]); + insertionSort(arr, length); + for (int i = 0; i < length; i++) { + cout << arr[i] << " "; + } + return 0; +} +``` + +### JavaScript Implementation + +```javascript +function insertionSort(array) { + for (let i = 1; i < array.length; i++) { + let key = array[i]; + let j = i - 1; + while (j >= 0 && array[j] > key) { + array[j + 1] = array[j]; + j = j - 1; + } + array[j + 1] = key; + } + return array; +} + +let arr = [12, 11, 13, 5, 6]; +console.log(insertionSort(arr)); +``` + +## Time Complexity Analysis + +- **Best Case**: $O(n)$ (when the array is already sorted) +- **Worst Case**: $O(n^2)$ (when the array is sorted in reverse order) +- **Average Case**: $O(n^2)$ + +## Space Complexity Analysis + +- **Space Complexity**: $O(1)$ (since it sorts in place and requires only a constant amount of extra memory) + +## Applications of Insertion Sort + +- **Small Data Sets**: Insertion Sort is efficient for small data sets or arrays that are already partially sorted. +- **Real-Time Systems**: Insertion Sort can be used where the list is being updated in real-time with few elements at a time. +- **Adaptive Sorting**: It is adaptive in nature, meaning it is efficient for data sets that are already substantially sorted. + +## Optimizations and Variations + +### Binary Insertion Sort + +Binary Insertion Sort uses binary search to find the correct location to insert the new element. This reduces the number of comparisons but does not improve the overall time complexity. + +### Shell Sort + +Shell Sort is a generalization of Insertion Sort that allows the exchange of items that are far apart. The idea is to arrange the list of elements so that, starting anywhere, taking every h-th element produces a sorted list. Such a list is said to be h-sorted. If the list is then k-sorted for some smaller integer k, then the list remains h-sorted. The step sizes form a decreasing sequence ending in 1. + +### Adaptive Insertion Sort + +Adaptive Insertion Sort improves performance by identifying runs of already sorted elements in the input array and then merging them. + +## Practical Considerations + +### Stability + +Insertion Sort is a stable sorting algorithm, meaning it maintains the relative order of equal elements. + +### Use Cases + +- Insertion Sort is used when the array size is small. +- It is used when additional memory space is not available. +- It is useful when the array is already partially sorted. + +## Conclusion + +In this tutorial, we covered the fundamentals of Insertion Sort, its implementation in Python, Java, C++, and JavaScript, and various optimizations and applications. Insertion Sort is a powerful tool for sorting small arrays and understanding it provides a foundation for learning more complex sorting algorithms. By mastering Insertion Sort, you can effectively solve a variety of sorting problems in your projects. \ No newline at end of file diff --git a/dsa/Algorithms/Sorting/merge-sort.md b/dsa/Algorithms/Sorting/merge-sort.md new file mode 100644 index 000000000..e6d01163c --- /dev/null +++ b/dsa/Algorithms/Sorting/merge-sort.md @@ -0,0 +1,298 @@ +--- +id: merge-sort +title: Merge Sort +sidebar_label: Merge Sort +tags: [python, java, c++, javascript, programming, algorithms, sorting, data structures, tutorial, in-depth] +description: In this tutorial, we will learn about Merge Sort and its implementation in Python, Java, C++, and JavaScript with detailed explanations and examples. +--- + +# Merge Sort + +Merge Sort is an efficient, stable, comparison-based sorting algorithm. It is particularly useful for sorting large lists and is known for its divide-and-conquer approach. This tutorial will cover the basics of Merge Sort, its applications, and how to implement it in Python, Java, C++, and JavaScript. We will also delve into various optimizations and advanced use cases. + +## Introduction to Merge Sort + +Merge Sort was invented by John von Neumann in 1945. It works by dividing the unsorted list into n sublists, each containing one element, and then repeatedly merging sublists to produce new sorted sublists until there is only one sorted list remaining. + +## How Merge Sort Works + +- **Step 1: Divide**: Divide the unsorted list into n sublists, each containing one element (a list of one element is considered sorted). +- **Step 2: Conquer**: Repeatedly merge sublists to produce new sorted sublists until there is only one sublist remaining. This will be the sorted list. + +![Merge Sort Process](https://upload.wikimedia.org/wikipedia/commons/c/cc/Merge-sort-example-300px.gif) + +## Pseudocode for Merge Sort + +Here is the pseudocode for Merge Sort: + +``` +function mergeSort(array): + if length(array) <= 1: + return array + mid = length(array) // 2 + left = mergeSort(array[:mid]) + right = mergeSort(array[mid:]) + return merge(left, right) + +function merge(left, right): + result = [] + while left and right: + if left[0] <= right[0]: + result.append(left.pop(0)) + else: + result.append(right.pop(0)) + result.extend(left if left else right) + return result +``` + +## Implementing Merge Sort + +### Python Implementation + +```python +def merge_sort(array): + if len(array) <= 1: + return array + + mid = len(array) // 2 + left = merge_sort(array[:mid]) + right = merge_sort(array[mid:]) + + return merge(left, right) + +def merge(left, right): + result = [] + i = j = 0 + + while i < len(left) and j < len(right): + if left[i] < right[j]: + result.append(left[i]) + i += 1 + else: + result.append(right[j]) + j += 1 + + result.extend(left[i:]) + result.extend(right[j:]) + return result + +arr = [38, 27, 43, 3, 9, 82, 10] +print(merge_sort(arr)) +``` + +### Java Implementation + +```java +public class MergeSort { + + public static void mergeSort(int[] array, int left, int right) { + if (left < right) { + int mid = (left + right) / 2; + + mergeSort(array, left, mid); + mergeSort(array, mid + 1, right); + + merge(array, left, mid, right); + } + } + + public static void merge(int[] array, int left, int mid, int right) { + int n1 = mid - left + 1; + int n2 = right - mid; + + int[] L = new int[n1]; + int[] R = new int[n2]; + + for (int i = 0; i < n1; ++i) + L[i] = array[left + i]; + for (int j = 0; j < n2; ++j) + R[j] = array[mid + 1 + j]; + + int i = 0, j = 0; + + int k = left; + while (i < n1 && j < n2) { + if (L[i] <= R[j]) { + array[k] = L[i]; + i++; + } else { + array[k] = R[j]; + j++; + } + k++; + } + + while (i < n1) { + array[k] = L[i]; + i++; + k++; + } + + while (j < n2) { + array[k] = R[j]; + j++; + k++; + } + } + + public static void main(String[] args) { + int[] arr = {38, 27, 43, 3, 9, 82, 10}; + mergeSort(arr, 0, arr.length - 1); + for (int num : arr) { + System.out.print(num + " "); + } + } +} +``` + +### C++ Implementation + +```cpp +#include +using namespace std; + +void merge(int array[], int const left, int const mid, int const right) { + int const subArrayOne = mid - left + 1; + int const subArrayTwo = right - mid; + + int *leftArray = new int[subArrayOne], + *rightArray = new int[subArrayTwo]; + + for (int i = 0; i < subArrayOne; i++) + leftArray[i] = array[left + i]; + for (int j = 0; j < subArrayTwo; j++) + rightArray[j] = array[mid + 1 + j]; + + int indexOfSubArrayOne = 0, + indexOfSubArrayTwo = 0; + int indexOfMergedArray = left; + + while (indexOfSubArrayOne < subArrayOne && indexOfSubArrayTwo < subArrayTwo) { + if (leftArray[indexOfSubArrayOne] <= rightArray[indexOfSubArrayTwo]) { + array[indexOfMergedArray] = leftArray[indexOfSubArrayOne]; + indexOfSubArrayOne++; + } else { + array[indexOfMergedArray] = rightArray[indexOfSubArrayTwo]; + indexOfSubArrayTwo++; + } + indexOfMergedArray++; + } + + while (indexOfSubArrayOne < subArrayOne) { + array[indexOfMergedArray] = leftArray[indexOfSubArrayOne]; + indexOfSubArrayOne++; + indexOfMergedArray++; + } + + while (indexOfSubArrayTwo < subArrayTwo) { + array[indexOfMergedArray] = rightArray[indexOfSubArrayTwo]; + indexOfSubArrayTwo++; + indexOfMergedArray++; + } + delete[] leftArray; + delete[] rightArray; +} + +void mergeSort(int array[], int const begin, int const end) { + if (begin >= end) + return; + + int mid = begin + (end - begin) / 2; + mergeSort(array, begin, mid); + mergeSort(array, mid + 1, end); + merge(array, begin, mid, end); +} + +int main() { + int arr[] = {38, 27, 43, 3, 9, 82, 10}; + int arrSize = sizeof(arr) / sizeof(arr[0]); + + mergeSort(arr, 0, arrSize - 1); + + for (int i = 0; i < arrSize; i++) { + cout << arr[i] << " "; + } + return 0; +} +``` + +### JavaScript Implementation + +```javascript +function mergeSort(array) { + if (array.length <= 1) { + return array; + } + + const mid = Math.floor(array.length / 2); + const left = array.slice(0, mid); + const right = array.slice(mid); + + return merge(mergeSort(left), mergeSort(right)); +} + +function merge(left, right) { + let resultArray = [], leftIndex = 0, rightIndex = 0; + + while (leftIndex < left.length && rightIndex < right.length) { + if (left[leftIndex] < right[rightIndex]) { + resultArray.push(left[leftIndex]); + leftIndex++; + } else { + resultArray.push(right[rightIndex]); + rightIndex++; + } + } + + return resultArray + .concat(left.slice(leftIndex)) + .concat(right.slice(rightIndex)); +} + +let arr = [38, 27, 43, 3, 9, 82, 10]; +console.log(mergeSort(arr)); +``` + +## Time Complexity Analysis + +- **Best Case**: $O(n log n)$ (all cases) +- **Worst Case**: $O(n log n)$ (all cases) +- **Average Case**: $O(n log n)$ (all cases) + +## Space Complexity Analysis + +- **Space Complexity**: $O(n)$ (due to the temporary arrays used during the merge process) + +## Applications of Merge Sort + +- **Large Data Sets**: Efficient for sorting large datasets, especially when the data cannot be held in memory. +- **External Sorting**: Useful for sorting data stored on external storage devices. +- **Stable Sort**: Maintains the relative order of equal elements, making it suitable for sorting linked lists and other data structures where stability is important. + +## Optimizations and Variations + +### Bottom-Up Merge Sort + +Bottom-Up Merge Sort avoids the recursive calls by iteratively sorting sublists of increasing size. + +### Timsort + +Timsort is a hybrid sorting algorithm derived from Merge Sort and Insertion Sort, designed to perform well on many kinds of real-world data. It is used in the standard libraries of Python and Java. + +## Practical Considerations + +### Stability + +Merge Sort is a stable sorting algorithm, maintaining the relative order of equal elements. + +### Use Cases + + + +- When the array size is large. +- When stability is required. +- When dealing with data stored on external storage. + +## Conclusion + +In this tutorial, we covered the fundamentals of Merge Sort, its implementation in Python, Java, C++, and JavaScript, and various optimizations and applications. Merge Sort is a powerful and versatile sorting algorithm, ideal for large datasets and scenarios where stability is crucial. By mastering Merge Sort, you can effectively handle complex sorting tasks in your projects. \ No newline at end of file diff --git a/dsa/Algorithms/Sorting/quick-sort.md b/dsa/Algorithms/Sorting/quick-sort.md new file mode 100644 index 000000000..b2a0cd4cf --- /dev/null +++ b/dsa/Algorithms/Sorting/quick-sort.md @@ -0,0 +1,231 @@ +--- +id: quick-sort +title: Quick Sort +sidebar_label: Quick Sort +tags: [python, java, c++, javascript, programming, algorithms, sorting, data structures, tutorial, in-depth] +description: In this tutorial, we will learn about Quick Sort and its implementation in Python, Java, C++, and JavaScript with detailed explanations and examples. +--- + +# Quick Sort + +Quick Sort is a highly efficient and widely used sorting algorithm. It is a comparison-based algorithm that uses the divide-and-conquer strategy to sort elements. This tutorial will cover the basics of Quick Sort, its applications, and how to implement it in Python, Java, C++, and JavaScript. We will also delve into various optimizations and advanced use cases. + +## Introduction to Quick Sort + +Quick Sort was developed by Tony Hoare in 1959. It is known for its efficiency in practice and has an average-case time complexity of O(n log n). Quick Sort works by selecting a 'pivot' element from the array and partitioning the other elements into two sub-arrays according to whether they are less than or greater than the pivot. + +## How Quick Sort Works + +- **Step 1: Choose a Pivot**: Select a pivot element from the array. +- **Step 2: Partition**: Rearrange the elements in the array so that all elements less than the pivot come before it and all elements greater than the pivot come after it. +- **Step 3: Recursively Sort**: Recursively apply the above steps to the sub-arrays of elements with smaller and larger values. + +![Quick Sort Process](https://runestone.academy/ns/books/published/pythonds/_images/partitionA.png) + +## Pseudocode for Quick Sort + +Here is the pseudocode for Quick Sort: + +``` +function quickSort(arr, low, high): + if low < high: + pi = partition(arr, low, high) + quickSort(arr, low, pi - 1) + quickSort(arr, pi + 1, high) + +function partition(arr, low, high): + pivot = arr[high] + i = low - 1 + for j = low to high - 1: + if arr[j] <= pivot: + i = i + 1 + swap arr[i] with arr[j] + swap arr[i + 1] with arr[high] + return i + 1 +``` + +## Implementing Quick Sort + +### Python Implementation + +```python +def quick_sort(arr, low, high): + if low < high: + pi = partition(arr, low, high) + quick_sort(arr, low, pi - 1) + quick_sort(arr, pi + 1, high) + +def partition(arr, low, high): + pivot = arr[high] + i = low - 1 + for j in range(low, high): + if arr[j] <= pivot: + i += 1 + arr[i], arr[j] = arr[j], arr[i] + arr[i + 1], arr[high] = arr[high], arr[i + 1] + return i + 1 + +arr = [10, 7, 8, 9, 1, 5] +n = len(arr) +quick_sort(arr, 0, n - 1) +print(f"Sorted array is: {arr}") +``` + +### Java Implementation + +```java +public class QuickSort { + + public static void quickSort(int[] arr, int low, int high) { + if (low < high) { + int pi = partition(arr, low, high); + quickSort(arr, low, pi - 1); + quickSort(arr, pi + 1, high); + } + } + + public static int partition(int[] arr, int low, int high) { + int pivot = arr[high]; + int i = (low - 1); + for (int j = low; j < high; j++) { + if (arr[j] <= pivot) { + i++; + int temp = arr[i]; + arr[i] = arr[j]; + arr[j] = temp; + } + } + + int temp = arr[i + 1]; + arr[i + 1] = arr[high]; + arr[high] = temp; + + return i + 1; + } + + public static void main(String[] args) { + int[] arr = {10, 7, 8, 9, 1, 5}; + int n = arr.length; + quickSort(arr, 0, n - 1); + System.out.println("Sorted array: "); + for (int num : arr) { + System.out.print(num + " "); + } + } +} +``` + +### C++ Implementation + +```cpp +#include +using namespace std; + +void swap(int* a, int* b) { + int t = *a; + *a = *b; + *b = t; +} + +int partition(int arr[], int low, int high) { + int pivot = arr[high]; + int i = (low - 1); + for (int j = low; j < high; j++) { + if (arr[j] <= pivot) { + i++; + swap(&arr[i], &arr[j]); + } + } + swap(&arr[i + 1], &arr[high]); + return (i + 1); +} + +void quickSort(int arr[], int low, int high) { + if (low < high) { + int pi = partition(arr, low, high); + quickSort(arr, low, pi - 1); + quickSort(arr, pi + 1, high); + } +} + +int main() { + int arr[] = {10, 7, 8, 9, 1, 5}; + int n = sizeof(arr) / sizeof(arr[0]); + quickSort(arr, 0, n - 1); + cout << "Sorted array: "; + for (int i = 0; i < n; i++) { + cout << arr[i] << " "; + } + return 0; +} +``` + +### JavaScript Implementation + +```javascript +function quickSort(arr, low, high) { + if (low < high) { + let pi = partition(arr, low, high); + quickSort(arr, low, pi - 1); + quickSort(arr, pi + 1, high); + } +} + +function partition(arr, low, high) { + let pivot = arr[high]; + let i = (low - 1); + for (let j = low; j < high; j++) { + if (arr[j] <= pivot) { + i++; + [arr[i], arr[j]] = [arr[j], arr[i]]; + } + } + [arr[i + 1], arr[high]] = [arr[high], arr[i + 1]]; + return (i + 1); +} + +let arr = [10, 7, 8, 9, 1, 5]; +quickSort(arr, 0, arr.length - 1); +console.log("Sorted array:", arr); +``` + +## Time Complexity Analysis + +- **Best Case**: $O(n log n)$ (when the pivot divides the array into two equal halves) +- **Worst Case**: $O(n²)$ (when the pivot is the smallest or largest element) +- **Average Case**: $O(n log n)$ (for random pivot selection) + +## Space Complexity Analysis + +- **Space Complexity**: O(log n) (for recursive stack space) + +## Applications of Quick Sort + +- **Efficient Sorting**: Quick Sort is generally faster than Merge Sort for smaller arrays and is often the go-to algorithm for in-place sorting. +- **Divide and Conquer**: Its divide-and-conquer approach makes it suitable for parallel processing. +- **Memory Efficiency**: Requires minimal additional memory space compared to other sorting algorithms like Merge Sort. + +## Optimizations and Variations + +### Randomized Quick Sort + +Randomized Quick Sort improves performance by randomly selecting the pivot element to minimize the chances of worst-case scenarios. + +### Three-Way Quick Sort + +Three-Way Quick Sort handles arrays with many duplicate elements more efficiently by dividing the array into three parts: elements less than the pivot, equal to the pivot, and greater than the pivot. + +## Practical Considerations + +### Stability + +Quick Sort is not a stable sorting algorithm, which means it does not preserve the relative order of equal elements. + +### Use Cases + +- When the array size is large and average-case performance is more important than worst-case. +- When in-place sorting is required to save memory. + +## Conclusion + +In this tutorial, we covered the fundamentals of Quick Sort, its implementation in Python, Java, C++, and JavaScript, and various optimizations and applications. Quick Sort is a powerful and versatile sorting algorithm that is widely used due to its efficiency and simplicity. By mastering Quick Sort, you can handle complex sorting tasks effectively in your projects. \ No newline at end of file diff --git a/dsa/Algorithms/Sorting/selection-sort.md b/dsa/Algorithms/Sorting/selection-sort.md new file mode 100644 index 000000000..3d32c76e0 --- /dev/null +++ b/dsa/Algorithms/Sorting/selection-sort.md @@ -0,0 +1,188 @@ +--- +id: selection-sort +title: Selection Sort +sidebar_label: Selection Sort +tags: [python, java, c++, javascript, programming, algorithms, sorting, data structures, tutorial, in-depth] +description: In this tutorial, we will learn about Selection Sort and its implementation in Python, Java, C++, and JavaScript with detailed explanations and examples. +--- + +# Selection Sort + +Selection Sort is a simple comparison-based sorting algorithm. It is efficient for small lists and is known for its simplicity and ease of implementation. This tutorial will cover the basics of Selection Sort, its applications, and how to implement it in Python, Java, C++, and JavaScript. We will also delve into various optimizations and advanced use cases. + +## Introduction to Selection Sort + +Selection Sort is an in-place comparison sorting algorithm. It has an O(n²) time complexity, making it inefficient on large lists, and generally performs worse than the similar insertion sort. Selection Sort is noted for its simplicity and is often used as an educational tool. + +## How Selection Sort Works + +- **Step 1**: Start with the first element as the minimum. +- **Step 2**: Compare this element with the next element in the list. If the next element is smaller, update the minimum to this element. +- **Step 3**: Continue this process for the rest of the list. +- **Step 4**: Once the end of the list is reached, swap the minimum element with the first element. +- **Step 5**: Move to the next element in the list and repeat steps 1-4 until the list is sorted. + + +![selection sort](https://runestone.academy/ns/books/published/pythonds/_images/insertionpass.png) +## Pseudocode for Selection Sort + +Here is the pseudocode for Selection Sort: + +``` +function selectionSort(array): + for i from 0 to length(array) - 1: + minIndex = i + for j from i + 1 to length(array): + if array[j] < array[minIndex]: + minIndex = j + if minIndex != i: + swap(array[i], array[minIndex]) + return array +``` + +## Implementing Selection Sort + +### Python Implementation + +```python +def selection_sort(array): + n = len(array) + for i in range(n): + min_index = i + for j in range(i+1, n): + if array[j] < array[min_index]: + min_index = j + if min_index != i: + array[i], array[min_index] = array[min_index], array[i] + return array + +arr = [64, 25, 12, 22, 11] +print(selection_sort(arr)) +``` + +### Java Implementation + +```java +public class SelectionSort { + + public static void selectionSort(int[] array) { + int n = array.length; + for (int i = 0; i < n-1; i++) { + int minIndex = i; + for (int j = i+1; j < n; j++) { + if (array[j] < array[minIndex]) { + minIndex = j; + } + } + int temp = array[minIndex]; + array[minIndex] = array[i]; + array[i] = temp; + } + } + + public static void main(String[] args) { + int[] arr = {64, 25, 12, 22, 11}; + selectionSort(arr); + for (int num : arr) { + System.out.print(num + " "); + } + } +} +``` + +### C++ Implementation + +```cpp +#include +using namespace std; + +void selectionSort(int array[], int length) { + for (int i = 0; i < length-1; i++) { + int minIndex = i; + for (int j = i+1; j < length; j++) { + if (array[j] < array[minIndex]) { + minIndex = j; + } + } + int temp = array[minIndex]; + array[minIndex] = array[i]; + array[i] = temp; + } +} + +int main() { + int arr[] = {64, 25, 12, 22, 11}; + int length = sizeof(arr) / sizeof(arr[0]); + selectionSort(arr, length); + for (int i = 0; i < length; i++) { + cout << arr[i] << " "; + } + return 0; +} +``` + +### JavaScript Implementation + +```javascript +function selectionSort(array) { + let n = array.length; + for (let i = 0; i < n-1; i++) { + let minIndex = i; + for (let j = i+1; j < n; j++) { + if (array[j] < array[minIndex]) { + minIndex = j; + } + } + if (minIndex != i) { + let temp = array[minIndex]; + array[minIndex] = array[i]; + array[i] = temp; + } + } + return array; +} + +let arr = [64, 25, 12, 22, 11]; +console.log(selectionSort(arr)); +``` + +## Time Complexity Analysis + +- **Best Case**: $O(n²)$ (even if the array is already sorted, it still makes n² comparisons) +- **Worst Case**: $O(n²)$ (when the array is sorted in reverse order) +- **Average Case**: $O(n²)$ + +## Space Complexity Analysis + +- **Space Complexity**: $O(1)$ (since it sorts in place and requires only a constant amount of extra memory) + +## Applications of Selection Sort + +- **Small Data Sets**: Efficient for sorting small arrays or lists. +- **When Writing to Memory is Costly**: Selection Sort makes the minimum number of swaps, making it useful in situations where writing to memory is expensive. + +## Optimizations and Variations + +### Min-Heap Sort + +Min-Heap Sort is a variation that uses a min-heap to improve selection of the smallest element, making it more efficient for certain data sets. + +### Double Selection Sort + +Double Selection Sort performs two selection processes simultaneously, selecting both the minimum and maximum elements in a single pass, which can reduce the number of passes by half. + +## Practical Considerations + +### Stability + +Selection Sort is not a stable sorting algorithm, meaning it does not necessarily maintain the relative order of equal elements. + +### Use Cases + +- Selection Sort is used when the array size is small. +- It is used when additional memory space is not available. +- It is useful when the number of writes/swaps must be minimized. + +## Conclusion + +In this tutorial, we covered the fundamentals of Selection Sort, its implementation in Python, Java, C++, and JavaScript, and various optimizations and applications. Selection Sort is a straightforward sorting algorithm, ideal for small data sets and educational purposes. By mastering Selection Sort, you can effectively handle simple sorting tasks in your projects. \ No newline at end of file From 8fc24d8298eb0ccadf7d0b1ba8d84568aad352d6 Mon Sep 17 00:00:00 2001 From: Yashgabani845 Date: Fri, 7 Jun 2024 10:55:25 +0530 Subject: [PATCH 2/3] hashing added --- dsa/Algorithms/hashing.md | 318 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 318 insertions(+) create mode 100644 dsa/Algorithms/hashing.md diff --git a/dsa/Algorithms/hashing.md b/dsa/Algorithms/hashing.md new file mode 100644 index 000000000..e5b965396 --- /dev/null +++ b/dsa/Algorithms/hashing.md @@ -0,0 +1,318 @@ +--- +id: hashing +title: Hashing +sidebar_label: Hashing +tags: [python, java, c++, javascript, programming, algorithms, data structures, tutorial, in-depth] +description: In this tutorial, we will learn about Hash Tables, their uses, how they work, and hashing in general with detailed explanations and examples. +--- + +# Hash Tables + +Hash tables are a fundamental data structure in computer science used for fast data retrieval. This tutorial will cover the basics of hash tables, their uses, how they work, and the concept of hashing in general. + +## Introduction to Hash Tables + +A hash table, also known as a hash map, is a data structure that stores key-value pairs. It provides efficient insertion, deletion, and lookup operations, typically in constant average time complexity, $O(1)$. + +## Uses of Hash Tables + +Hash tables are widely used in various applications due to their efficiency and versatility. Some common uses include: + +- **Databases**: Implementing indexes to speed up data retrieval. +- **Caching**: Storing recently accessed data to quickly serve future requests. +- **Dictionaries**: Implementing associative arrays or dictionaries, where each key is associated with a value. +- **Symbol Tables**: Managing variable names in interpreters and compilers. +- **Sets**: Implementing sets, which allow for fast membership testing. + +## Working of Hash Tables + +A hash table works by mapping keys to indices in an array. This mapping is achieved using a hash function. The hash function takes a key and returns an integer, which is used as an index to store the corresponding value in the array. + +### Components of a Hash Table + +1. **Hash Function**: Converts keys into valid array indices. +2. **Buckets**: Array elements where key-value pairs are stored. +3. **Collision Resolution**: Strategy to handle cases where multiple keys map to the same index. + +![hashing](https://khalilstemmler.com/img/blog/data-structures/hash-tables/hash-table.png) +### Hash Function + +The hash function is crucial for the performance of a hash table. It should be fast to compute and distribute keys uniformly across the array. A common hash function for integers is `h(key) = key % N`, where `N` is the size of the array. + +### Collision Resolution + +Collisions occur when multiple keys hash to the same index. There are several strategies to resolve collisions: + +- **Chaining**: Store multiple key-value pairs in a list at each index. +- **Open Addressing**: Find another index within the array using methods like linear probing, quadratic probing, or double hashing. + +## Hashing in General + +Hashing is the process of converting input data (keys) into a fixed-size integer, which serves as an index for data storage and retrieval. Hashing is widely used beyond hash tables in various fields such as cryptography, data structures, and databases. + +### Properties of a Good Hash Function + +1. **Deterministic**: The hash function must consistently return the same hash value for the same input. +2. **Uniform Distribution**: It should distribute hash values uniformly across the hash table to minimize collisions. +3. **Efficient Computation**: The hash function should be quick to compute. +4. **Minimally Correlated**: Hash values should be independent of each other to avoid clustering. + +### Common Hash Functions + +- **Division Method**: `h(key) = key % N` +- **Multiplication Method**: `h(key) = floor(N * (key * A % 1))`, where `A` is a constant between 0 and 1. +- **Universal Hashing**: Uses a class of hash functions and selects one at random to minimize the chance of collisions. + +## Implementing Hash Tables + +### Python Implementation + +```python +class HashTable: + def __init__(self, size): + self.size = size + self.table = [[] for _ in range(size)] + + def hash_function(self, key): + return hash(key) % self.size + + def insert(self, key, value): + index = self.hash_function(key) + for i, kv in enumerate(self.table[index]): + if kv[0] == key: + self.table[index][i] = (key, value) + return + self.table[index].append((key, value)) + + def lookup(self, key): + index = self.hash_function(key) + for kv in self.table[index]: + if kv[0] == key: + return kv[1] + return None + + def delete(self, key): + index = self.hash_function(key) + for i, kv in enumerate(self.table[index]): + if kv[0] == key: + del self.table[index][i] + return + +# Example usage +ht = HashTable(10) +ht.insert("apple", 1) +ht.insert("banana", 2) +print(ht.lookup("apple")) # Output: 1 +ht.delete("apple") +print(ht.lookup("apple")) # Output: None +``` + +### Java Implementation + +```java +import java.util.LinkedList; + +class HashTable { + private class Entry { + K key; + V value; + Entry(K key, V value) { + this.key = key; + this.value = value; + } + } + + private LinkedList>[] table; + private int size; + + @SuppressWarnings("unchecked") + public HashTable(int size) { + this.size = size; + table = new LinkedList[size]; + for (int i = 0; i < size; i++) { + table[i] = new LinkedList<>(); + } + } + + private int hashFunction(K key) { + return key.hashCode() % size; + } + + public void insert(K key, V value) { + int index = hashFunction(key); + for (Entry entry : table[index]) { + if (entry.key.equals(key)) { + entry.value = value; + return; + } + } + table[index].add(new Entry<>(key, value)); + } + + public V lookup(K key) { + int index = hashFunction(key); + for (Entry entry : table[index]) { + if (entry.key.equals(key)) { + return entry.value; + } + } + return null; + } + + public void delete(K key) { + int index = hashFunction(key); + table[index].removeIf(entry -> entry.key.equals(key)); + } + + public static void main(String[] args) { + HashTable ht = new HashTable<>(10); + ht.insert("apple", 1); + ht.insert("banana", 2); + System.out.println(ht.lookup("apple")); // Output: 1 + ht.delete("apple"); + System.out.println(ht.lookup("apple")); // Output: null + } +} +``` + +### C++ Implementation + +```cpp +#include +#include +#include +#include + +using namespace std; + +class HashTable { +private: + int size; + vector>> table; + + int hashFunction(const string &key) { + return hash{}(key) % size; + } + +public: + HashTable(int size) : size(size), table(size) {} + + void insert(const string &key, int value) { + int index = hashFunction(key); + for (auto &kv : table[index]) { + if (kv.first == key) { + kv.second = value; + return; + } + } + table[index].emplace_back(key, value); + } + + int lookup(const string &key) { + int index = hashFunction(key); + for (const auto &kv : table[index]) { + if (kv.first == key) { + return kv.second; + } + } + return -1; // Return -1 if key not found + } + + void delete_key(const string &key) { + int index = hashFunction(key); + table[index].remove_if([&key](const pair &kv) { return kv.first == key; }); + } +}; + +int main() { + HashTable ht(10); + ht.insert("apple", 1); + ht.insert("banana", 2); + cout << ht.lookup("apple") << endl; // Output: 1 + ht.delete_key("apple"); + cout << ht.lookup("apple") << endl; // Output: -1 + return 0; +} +``` + +### JavaScript Implementation + +```javascript +class HashTable { + constructor(size) { + this.size = size; + this.table = new Array(size).fill(null).map(() => []); + } + + hashFunction(key) { + let hash = 0; + for (let char of key) { + hash += char.charCodeAt(0); + } + return hash % this.size; + } + + insert(key, value) { + const index = this.hashFunction(key); + for (let [k, v] of this.table[index]) { + if (k === key) { + v = value; + return; + } + } + this.table[index].push([key, value]); + } + + lookup(key) { + const index = this.hashFunction(key); + for (let [k, v] of this.table[index]) { + if (k === key) { + return v; + } + } + return null; + } + + delete(key) { + const index = this.hashFunction(key); + this.table[index] = this.table[index].filter(([k, v]) => k !== key); + } +} + +const ht = new HashTable(10); +ht.insert("apple", 1); +ht.insert("banana", 2); +console.log(ht.lookup("apple")); // Output: 1 +ht.delete("apple"); +console.log(ht.lookup("apple")); + + // Output: null +``` + +## Time Complexity Analysis + +- **Insertion**: $O(1)$ on average +- **Deletion**: $O(1)$ on average +- **Lookup**: $O(1)$ on average + +## Space Complexity Analysis + +- **Space Complexity**: O(n) where n is the number of key-value pairs + +## Advanced Topics + +### Dynamic Resizing + +When the load factor (number of elements/size of table) exceeds a threshold, the hash table can be resized to maintain performance. This involves creating a new table with a larger size and rehashing all existing elements. + +### Cryptographic Hash Functions + +In cryptography, hash functions are used to secure data. These hash functions are designed to be irreversible and produce a fixed-size hash value for any input. + +### Bloom Filters + +A Bloom filter is a space-efficient probabilistic data structure used to test whether an element is a member of a set. It uses multiple hash functions to map elements to a bit array. + +## Conclusion + +In this tutorial, we covered the fundamentals of hash tables, their uses, how they work, and the concept of hashing in general. We also provided implementations in Python, Java, C++, and JavaScript. Hash tables are a powerful and efficient data structure that play a crucial role in various applications. Understanding how they work and how to implement them will greatly enhance your programming skills and ability to solve complex problems efficiently. \ No newline at end of file From 80c15b37c35dc59e684ddc976ca586bbf612811f Mon Sep 17 00:00:00 2001 From: Yashgabani845 Date: Fri, 7 Jun 2024 11:01:40 +0530 Subject: [PATCH 3/3] removed unrelated files and complexity chnaged --- dsa/Algorithms/Sorting/_category_.json | 8 - dsa/Algorithms/Sorting/bubble-sort.md | 179 -------------- dsa/Algorithms/Sorting/counting-sort.md | 219 ----------------- dsa/Algorithms/Sorting/insertion-sort.md | 182 -------------- dsa/Algorithms/Sorting/merge-sort.md | 298 ----------------------- dsa/Algorithms/Sorting/quick-sort.md | 231 ------------------ dsa/Algorithms/Sorting/selection-sort.md | 188 -------------- dsa/Algorithms/hashing.md | 2 +- 8 files changed, 1 insertion(+), 1306 deletions(-) delete mode 100644 dsa/Algorithms/Sorting/_category_.json delete mode 100644 dsa/Algorithms/Sorting/bubble-sort.md delete mode 100644 dsa/Algorithms/Sorting/counting-sort.md delete mode 100644 dsa/Algorithms/Sorting/insertion-sort.md delete mode 100644 dsa/Algorithms/Sorting/merge-sort.md delete mode 100644 dsa/Algorithms/Sorting/quick-sort.md delete mode 100644 dsa/Algorithms/Sorting/selection-sort.md diff --git a/dsa/Algorithms/Sorting/_category_.json b/dsa/Algorithms/Sorting/_category_.json deleted file mode 100644 index 21c2983cf..000000000 --- a/dsa/Algorithms/Sorting/_category_.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "label": "Sorting Algorithms", - "position": 1, - "link": { - "type": "generated-index", - "description": "In This section all the Sortingt Algorithms are defined in DSA " - } - } \ No newline at end of file diff --git a/dsa/Algorithms/Sorting/bubble-sort.md b/dsa/Algorithms/Sorting/bubble-sort.md deleted file mode 100644 index 8ffbb3770..000000000 --- a/dsa/Algorithms/Sorting/bubble-sort.md +++ /dev/null @@ -1,179 +0,0 @@ ---- -id: bubble-sort -title: Bubble Sort -sidebar_label: Bubble Sort -tags: [python, java, c++, javascript, programming, algorithms, sorting, data structures, tutorial, in-depth] -description: In this tutorial, we will learn about Bubble Sort and its implementation in Python, Java, C++, and JavaScript with detailed explanations and examples. ---- - -# Bubble Sort - -Bubble Sort is a simple comparison-based sorting algorithm. It is named for the way larger elements "bubble" to the top of the list. This tutorial will cover the basics of Bubble Sort, its applications, and how to implement it in Python, Java, C++, and JavaScript. We will also delve into various optimizations and advanced use cases. - -## Introduction to Bubble Sort - -Bubble Sort is an elementary algorithm suitable for small data sets. It repeatedly steps through the list, compares adjacent elements, and swaps them if they are in the wrong order. The pass through the list is repeated until the list is sorted. - -## How Bubble Sort Works - -- **Step 1**: Compare the first two elements of the array. -- **Step 2**: If the first element is greater than the second, swap them. -- **Step 3**: Move to the next pair of elements, compare them and swap if necessary. -- **Step 4**: Continue this process for each pair of adjacent elements until the end of the array. -- **Step 5**: Repeat the process for the entire array until no swaps are needed. - - -![bubble sort](https://runestone.academy/ns/books/published/pythonds/_images/bubblepass.png) -## Pseudocode for Bubble Sort - -Here is the pseudocode for Bubble Sort: - -``` -function bubbleSort(array): - for i from 0 to length(array) - 1: - for j from 0 to length(array) - i - 1: - if array[j] > array[j + 1]: - swap(array[j], array[j + 1]) - return array -``` - -## Implementing Bubble Sort - -### Python Implementation - -```python -def bubble_sort(array): - n = len(array) - for i in range(n): - for j in range(0, n-i-1): - if array[j] > array[j + 1]: - array[j], array[j + 1] = array[j + 1], array[j] - return array - -arr = [64, 34, 25, 12, 22, 11, 90] -print(bubble_sort(arr)) -``` - -### Java Implementation - -```java -public class BubbleSort { - - public static void bubbleSort(int[] array) { - int n = array.length; - for (int i = 0; i < n-1; i++) { - for (int j = 0; j < n-i-1; j++) { - if (array[j] > array[j + 1]) { - int temp = array[j]; - array[j] = array[j + 1]; - array[j + 1] = temp; - } - } - } - } - - public static void main(String[] args) { - int[] arr = {64, 34, 25, 12, 22, 11, 90}; - bubbleSort(arr); - for (int num : arr) { - System.out.print(num + " "); - } - } -} -``` - -### C++ Implementation - -```cpp -#include -using namespace std; - -void bubbleSort(int array[], int length) { - for (int i = 0; i < length-1; i++) { - for (int j = 0; j < length-i-1; j++) { - if (array[j] > array[j + 1]) { - int temp = array[j]; - array[j] = array[j + 1]; - array[j + 1] = temp; - } - } - } -} - -int main() { - int arr[] = {64, 34, 25, 12, 22, 11, 90}; - int length = sizeof(arr) / sizeof(arr[0]); - bubbleSort(arr, length); - for (int i = 0; i < length; i++) { - cout << arr[i] << " "; - } - return 0; -} -``` - -### JavaScript Implementation - -```javascript -function bubbleSort(array) { - let n = array.length; - for (let i = 0; i < n-1; i++) { - for (let j = 0; j < n-i-1; j++) { - if (array[j] > array[j + 1]) { - let temp = array[j]; - array[j] = array[j + 1]; - array[j + 1] = temp; - } - } - } - return array; -} - -let arr = [64, 34, 25, 12, 22, 11, 90]; -console.log(bubbleSort(arr)); -``` - -## Time Complexity Analysis - -- **Best Case**: $O(n)$ (when the array is already sorted) -- **Worst Case**: $O(n^2)$ (when the array is sorted in reverse order) -- **Average Case**: $O(n^2)$ - -## Space Complexity Analysis - -- **Space Complexity**: $O(1)$ (since it sorts in place and requires only a constant amount of extra memory) - -## Applications of Bubble Sort - -- **Educational Tools**: Bubble Sort is often used as an introduction to sorting algorithms due to its simplicity. -- **Small Data Sets**: Efficient for sorting small arrays or lists. -- **Learning Tool**: Useful for educational purposes to understand the basics of sorting algorithms. - -## Optimizations and Variations - -### Optimized Bubble Sort - -An optimized version of Bubble Sort can stop the algorithm if the inner loop didn’t cause any swap, indicating that the array is already sorted. - -### Cocktail Shaker Sort - -Cocktail Shaker Sort, also known as bidirectional Bubble Sort, extends Bubble Sort by operating in both directions on each pass through the list, first left to right, then right to left. - -### Comb Sort - -Comb Sort is an improvement on Bubble Sort. It eliminates turtles, or small values near the end of the list, since these slow the sorting process down. Comb Sort improves on Bubble Sort by using gaps in the comparison. - -## Practical Considerations - -### Stability - -Bubble Sort is a stable sorting algorithm, meaning it maintains the relative order of equal elements. - -### Use Cases - -- Bubble Sort is used when the array size is small. -- It is used when additional memory space is not available. -- It is useful when the array is already partially sorted. - -## Conclusion - -In this tutorial, we covered the fundamentals of Bubble Sort, its implementation in Python, Java, C++, and JavaScript, and various optimizations and applications. Bubble Sort is a simple sorting algorithm, ideal for understanding basic sorting concepts and practicing algorithm implementation. By mastering Bubble Sort, you can effectively handle small sorting tasks in your projects. \ No newline at end of file diff --git a/dsa/Algorithms/Sorting/counting-sort.md b/dsa/Algorithms/Sorting/counting-sort.md deleted file mode 100644 index 9b4b20438..000000000 --- a/dsa/Algorithms/Sorting/counting-sort.md +++ /dev/null @@ -1,219 +0,0 @@ ---- -id: counting-sort -title: Counting Sort -sidebar_label: Counting Sort -tags: [python, java, c++, javascript, programming, algorithms, sorting, data structures, tutorial, in-depth] -description: In this tutorial, we will learn about Counting Sort and its implementation in Python, Java, C++, and JavaScript with detailed explanations and examples. ---- - -# Counting Sort - -Counting Sort is a non-comparison-based sorting algorithm that works efficiently for sorting integers or objects that can be represented as integers within a specific range. This tutorial will cover the basics of Counting Sort, its applications, and how to implement it in Python, Java, C++, and JavaScript. We will also delve into various optimizations and advanced use cases. - -## Introduction to Counting Sort - -Counting Sort is a stable, non-comparison-based sorting algorithm that was introduced by Harold H. Seward in 1954. It works by counting the occurrences of each unique element in the input array and then using this count information to place the elements in the correct position in the output array. - -## How Counting Sort Works - -- **Step 1: Find the Range**: Determine the range of the input data (i.e., the minimum and maximum values). -- **Step 2: Count Occurrences**: Create a count array to store the count of each unique element. -- **Step 3: Accumulate Counts**: Modify the count array such that each element at each index stores the sum of previous counts. -- **Step 4: Place Elements**: Build the output array by placing elements at their correct positions using the count array. - - -## Pseudocode for Counting Sort - -Here is the pseudocode for Counting Sort: - -``` -function countingSort(arr): - find the maximum element (max) in arr - create a count array of size max + 1 and initialize it with zeros - - for each element in arr: - increment the count of element in count array - - for each index in count array: - accumulate the counts - - for each element in arr (in reverse order): - place the element in the output array using the count array - decrement the count of element in count array - - return output array -``` - -## Implementing Counting Sort - -### Python Implementation - -```python -def counting_sort(arr): - max_val = max(arr) - count = [0] * (max_val + 1) - output = [0] * len(arr) - - for num in arr: - count[num] += 1 - - for i in range(1, len(count)): - count[i] += count[i - 1] - - for num in reversed(arr): - output[count[num] - 1] = num - count[num] -= 1 - - return output - -arr = [4, 2, 2, 8, 3, 3, 1] -sorted_arr = counting_sort(arr) -print(f"Sorted array is: {sorted_arr}") -``` - -### Java Implementation - -```java -import java.util.Arrays; - -public class CountingSort { - - public static void countingSort(int[] arr) { - int max = Arrays.stream(arr).max().getAsInt(); - int[] count = new int[max + 1]; - int[] output = new int[arr.length]; - - for (int num : arr) { - count[num]++; - } - - for (int i = 1; i < count.length; i++) { - count[i] += count[i - 1]; - } - - for (int i = arr.length - 1; i >= 0; i--) { - output[count[arr[i]] - 1] = arr[i]; - count[arr[i]]--; - } - - System.arraycopy(output, 0, arr, 0, arr.length); - } - - public static void main(String[] args) { - int[] arr = {4, 2, 2, 8, 3, 3, 1}; - countingSort(arr); - System.out.println("Sorted array: " + Arrays.toString(arr)); - } -} -``` - -### C++ Implementation - -```cpp -#include -#include -#include - -using namespace std; - -void countingSort(vector& arr) { - int max_val = *max_element(arr.begin(), arr.end()); - vector count(max_val + 1, 0); - vector output(arr.size(), 0); - - for (int num : arr) { - count[num]++; - } - - for (int i = 1; i < count.size(); i++) { - count[i] += count[i - 1]; - } - - for (int i = arr.size() - 1; i >= 0; i--) { - output[count[arr[i]] - 1] = arr[i]; - count[arr[i]]--; - } - - for (int i = 0; i < arr.size(); i++) { - arr[i] = output[i]; - } -} - -int main() { - vector arr = {4, 2, 2, 8, 3, 3, 1}; - countingSort(arr); - cout << "Sorted array: "; - for (int num : arr) { - cout << num << " "; - } - return 0; -} -``` - -### JavaScript Implementation - -```javascript -function countingSort(arr) { - let max = Math.max(...arr); - let count = new Array(max + 1).fill(0); - let output = new Array(arr.length); - - arr.forEach(num => count[num]++); - - for (let i = 1; i < count.length; i++) { - count[i] += count[i - 1]; - } - - for (let i = arr.length - 1; i >= 0; i--) { - output[count[arr[i]] - 1] = arr[i]; - count[arr[i]]--; - } - - return output; -} - -let arr = [4, 2, 2, 8, 3, 3, 1]; -let sortedArr = countingSort(arr); -console.log("Sorted array:", sortedArr); -``` - -## Time Complexity Analysis - -- **Best Case**: $O(n + k)$ (where n is the number of elements and k is the range of the input) -- **Worst Case**: $O(n + k)$ -- **Average Case**: $O(n + k)$ - -## Space Complexity Analysis - -- **Space Complexity**: $O(n + k)$ (for the count and output arrays) - -## Applications of Counting Sort - -- **Sorting Integers**: Counting Sort is ideal for sorting integers or objects that can be represented as integers. -- **Large Data Sets**: Efficient for sorting large data sets with a limited range of values. -- **Stability**: Maintains the relative order of equal elements, making it suitable for sorting data with multiple keys. - -## Optimizations and Variations - -### Improved Counting Sort - -Improved Counting Sort can be implemented to handle negative numbers by offsetting the count array to accommodate the negative values. - -### Radix Sort - -Counting Sort can be used as a subroutine in Radix Sort, which sorts numbers digit by digit. - -## Practical Considerations - -### Stability - -Counting Sort is a stable sorting algorithm, meaning it maintains the relative order of equal elements. - -### Use Cases - -- When the range of input data (k) is not significantly larger than the number of elements (n). -- When stability is required in sorting. - -## Conclusion - -In this tutorial, we covered the fundamentals of Counting Sort, its implementation in Python, Java, C++, and JavaScript, and various optimizations and applications. Counting Sort is a powerful and efficient sorting algorithm for specific use cases, particularly when the range of input values is limited. By mastering Counting Sort, you can handle sorting tasks effectively in your projects. \ No newline at end of file diff --git a/dsa/Algorithms/Sorting/insertion-sort.md b/dsa/Algorithms/Sorting/insertion-sort.md deleted file mode 100644 index 338c9333d..000000000 --- a/dsa/Algorithms/Sorting/insertion-sort.md +++ /dev/null @@ -1,182 +0,0 @@ ---- -id: insertion-sort -title: Insertion Sort -sidebar_label: Insertion Sort -tags: [python, java, c++, javascript, programming, algorithms, sorting, data structures, tutorial, in-depth] -description: In this tutorial, we will learn about Insertion Sort and its implementation in Python, Java, C++, and JavaScript with detailed explanations and examples. ---- - -# Insertion Sort - -Insertion Sort is a simple and intuitive sorting algorithm that builds the final sorted array one item at a time. It is much like sorting playing cards in your hands. This tutorial will cover the basics of Insertion Sort, its applications, and how to implement it in Python, Java, C++, and JavaScript. We will also delve into various optimizations and advanced use cases. - -## Introduction to Insertion Sort - -Insertion Sort is an efficient algorithm for small data sets. It is much less efficient on large lists than more advanced algorithms such as quicksort, heapsort, or merge sort. Insertion Sort works by dividing the input list into two parts: a sorted and an unsorted part. The algorithm iteratively takes an element from the unsorted part and inserts it into the correct position in the sorted part. - -## How Insertion Sort Works - -- **Step 1**: Iterate from the second element to the last element of the array. -- **Step 2**: Compare the current element with the elements in the sorted part and find its correct position. -- **Step 3**: Shift all elements in the sorted part that are greater than the current element one position to the right. -- **Step 4**: Insert the current element into its correct position. -- **Step 5**: Repeat until the array is sorted. - -![insetion sort](https://runestone.academy/ns/books/published/pythonds/_images/insertionsort.png) - -## Pseudocode for Insertion Sort - -Here is the pseudocode for Insertion Sort: - -``` -function insertionSort(array): - for i from 1 to length(array) - 1: - key = array[i] - j = i - 1 - while j >= 0 and array[j] > key: - array[j + 1] = array[j] - j = j - 1 - array[j + 1] = key - return array -``` - -## Implementing Insertion Sort - -### Python Implementation - -```python -def insertion_sort(array): - for i in range(1, len(array)): - key = array[i] - j = i - 1 - while j >= 0 and key < array[j]: - array[j + 1] = array[j] - j -= 1 - array[j + 1] = key - return array - -arr = [12, 11, 13, 5, 6] -print(insertion_sort(arr)) -``` - -### Java Implementation - -```java -public class InsertionSort { - - public static void insertionSort(int[] array) { - for (int i = 1; i < array.length; i++) { - int key = array[i]; - int j = i - 1; - while (j >= 0 && array[j] > key) { - array[j + 1] = array[j]; - j--; - } - array[j + 1] = key; - } - } - - public static void main(String[] args) { - int[] arr = {12, 11, 13, 5, 6}; - insertionSort(arr); - for (int num : arr) { - System.out.print(num + " "); - } - } -} -``` - -### C++ Implementation - -```cpp -#include -using namespace std; - -void insertionSort(int array[], int length) { - for (int i = 1; i < length; i++) { - int key = array[i]; - int j = i - 1; - while (j >= 0 && array[j] > key) { - array[j + 1] = array[j]; - j = j - 1; - } - array[j + 1] = key; - } -} - -int main() { - int arr[] = {12, 11, 13, 5, 6}; - int length = sizeof(arr) / sizeof(arr[0]); - insertionSort(arr, length); - for (int i = 0; i < length; i++) { - cout << arr[i] << " "; - } - return 0; -} -``` - -### JavaScript Implementation - -```javascript -function insertionSort(array) { - for (let i = 1; i < array.length; i++) { - let key = array[i]; - let j = i - 1; - while (j >= 0 && array[j] > key) { - array[j + 1] = array[j]; - j = j - 1; - } - array[j + 1] = key; - } - return array; -} - -let arr = [12, 11, 13, 5, 6]; -console.log(insertionSort(arr)); -``` - -## Time Complexity Analysis - -- **Best Case**: $O(n)$ (when the array is already sorted) -- **Worst Case**: $O(n^2)$ (when the array is sorted in reverse order) -- **Average Case**: $O(n^2)$ - -## Space Complexity Analysis - -- **Space Complexity**: $O(1)$ (since it sorts in place and requires only a constant amount of extra memory) - -## Applications of Insertion Sort - -- **Small Data Sets**: Insertion Sort is efficient for small data sets or arrays that are already partially sorted. -- **Real-Time Systems**: Insertion Sort can be used where the list is being updated in real-time with few elements at a time. -- **Adaptive Sorting**: It is adaptive in nature, meaning it is efficient for data sets that are already substantially sorted. - -## Optimizations and Variations - -### Binary Insertion Sort - -Binary Insertion Sort uses binary search to find the correct location to insert the new element. This reduces the number of comparisons but does not improve the overall time complexity. - -### Shell Sort - -Shell Sort is a generalization of Insertion Sort that allows the exchange of items that are far apart. The idea is to arrange the list of elements so that, starting anywhere, taking every h-th element produces a sorted list. Such a list is said to be h-sorted. If the list is then k-sorted for some smaller integer k, then the list remains h-sorted. The step sizes form a decreasing sequence ending in 1. - -### Adaptive Insertion Sort - -Adaptive Insertion Sort improves performance by identifying runs of already sorted elements in the input array and then merging them. - -## Practical Considerations - -### Stability - -Insertion Sort is a stable sorting algorithm, meaning it maintains the relative order of equal elements. - -### Use Cases - -- Insertion Sort is used when the array size is small. -- It is used when additional memory space is not available. -- It is useful when the array is already partially sorted. - -## Conclusion - -In this tutorial, we covered the fundamentals of Insertion Sort, its implementation in Python, Java, C++, and JavaScript, and various optimizations and applications. Insertion Sort is a powerful tool for sorting small arrays and understanding it provides a foundation for learning more complex sorting algorithms. By mastering Insertion Sort, you can effectively solve a variety of sorting problems in your projects. \ No newline at end of file diff --git a/dsa/Algorithms/Sorting/merge-sort.md b/dsa/Algorithms/Sorting/merge-sort.md deleted file mode 100644 index e6d01163c..000000000 --- a/dsa/Algorithms/Sorting/merge-sort.md +++ /dev/null @@ -1,298 +0,0 @@ ---- -id: merge-sort -title: Merge Sort -sidebar_label: Merge Sort -tags: [python, java, c++, javascript, programming, algorithms, sorting, data structures, tutorial, in-depth] -description: In this tutorial, we will learn about Merge Sort and its implementation in Python, Java, C++, and JavaScript with detailed explanations and examples. ---- - -# Merge Sort - -Merge Sort is an efficient, stable, comparison-based sorting algorithm. It is particularly useful for sorting large lists and is known for its divide-and-conquer approach. This tutorial will cover the basics of Merge Sort, its applications, and how to implement it in Python, Java, C++, and JavaScript. We will also delve into various optimizations and advanced use cases. - -## Introduction to Merge Sort - -Merge Sort was invented by John von Neumann in 1945. It works by dividing the unsorted list into n sublists, each containing one element, and then repeatedly merging sublists to produce new sorted sublists until there is only one sorted list remaining. - -## How Merge Sort Works - -- **Step 1: Divide**: Divide the unsorted list into n sublists, each containing one element (a list of one element is considered sorted). -- **Step 2: Conquer**: Repeatedly merge sublists to produce new sorted sublists until there is only one sublist remaining. This will be the sorted list. - -![Merge Sort Process](https://upload.wikimedia.org/wikipedia/commons/c/cc/Merge-sort-example-300px.gif) - -## Pseudocode for Merge Sort - -Here is the pseudocode for Merge Sort: - -``` -function mergeSort(array): - if length(array) <= 1: - return array - mid = length(array) // 2 - left = mergeSort(array[:mid]) - right = mergeSort(array[mid:]) - return merge(left, right) - -function merge(left, right): - result = [] - while left and right: - if left[0] <= right[0]: - result.append(left.pop(0)) - else: - result.append(right.pop(0)) - result.extend(left if left else right) - return result -``` - -## Implementing Merge Sort - -### Python Implementation - -```python -def merge_sort(array): - if len(array) <= 1: - return array - - mid = len(array) // 2 - left = merge_sort(array[:mid]) - right = merge_sort(array[mid:]) - - return merge(left, right) - -def merge(left, right): - result = [] - i = j = 0 - - while i < len(left) and j < len(right): - if left[i] < right[j]: - result.append(left[i]) - i += 1 - else: - result.append(right[j]) - j += 1 - - result.extend(left[i:]) - result.extend(right[j:]) - return result - -arr = [38, 27, 43, 3, 9, 82, 10] -print(merge_sort(arr)) -``` - -### Java Implementation - -```java -public class MergeSort { - - public static void mergeSort(int[] array, int left, int right) { - if (left < right) { - int mid = (left + right) / 2; - - mergeSort(array, left, mid); - mergeSort(array, mid + 1, right); - - merge(array, left, mid, right); - } - } - - public static void merge(int[] array, int left, int mid, int right) { - int n1 = mid - left + 1; - int n2 = right - mid; - - int[] L = new int[n1]; - int[] R = new int[n2]; - - for (int i = 0; i < n1; ++i) - L[i] = array[left + i]; - for (int j = 0; j < n2; ++j) - R[j] = array[mid + 1 + j]; - - int i = 0, j = 0; - - int k = left; - while (i < n1 && j < n2) { - if (L[i] <= R[j]) { - array[k] = L[i]; - i++; - } else { - array[k] = R[j]; - j++; - } - k++; - } - - while (i < n1) { - array[k] = L[i]; - i++; - k++; - } - - while (j < n2) { - array[k] = R[j]; - j++; - k++; - } - } - - public static void main(String[] args) { - int[] arr = {38, 27, 43, 3, 9, 82, 10}; - mergeSort(arr, 0, arr.length - 1); - for (int num : arr) { - System.out.print(num + " "); - } - } -} -``` - -### C++ Implementation - -```cpp -#include -using namespace std; - -void merge(int array[], int const left, int const mid, int const right) { - int const subArrayOne = mid - left + 1; - int const subArrayTwo = right - mid; - - int *leftArray = new int[subArrayOne], - *rightArray = new int[subArrayTwo]; - - for (int i = 0; i < subArrayOne; i++) - leftArray[i] = array[left + i]; - for (int j = 0; j < subArrayTwo; j++) - rightArray[j] = array[mid + 1 + j]; - - int indexOfSubArrayOne = 0, - indexOfSubArrayTwo = 0; - int indexOfMergedArray = left; - - while (indexOfSubArrayOne < subArrayOne && indexOfSubArrayTwo < subArrayTwo) { - if (leftArray[indexOfSubArrayOne] <= rightArray[indexOfSubArrayTwo]) { - array[indexOfMergedArray] = leftArray[indexOfSubArrayOne]; - indexOfSubArrayOne++; - } else { - array[indexOfMergedArray] = rightArray[indexOfSubArrayTwo]; - indexOfSubArrayTwo++; - } - indexOfMergedArray++; - } - - while (indexOfSubArrayOne < subArrayOne) { - array[indexOfMergedArray] = leftArray[indexOfSubArrayOne]; - indexOfSubArrayOne++; - indexOfMergedArray++; - } - - while (indexOfSubArrayTwo < subArrayTwo) { - array[indexOfMergedArray] = rightArray[indexOfSubArrayTwo]; - indexOfSubArrayTwo++; - indexOfMergedArray++; - } - delete[] leftArray; - delete[] rightArray; -} - -void mergeSort(int array[], int const begin, int const end) { - if (begin >= end) - return; - - int mid = begin + (end - begin) / 2; - mergeSort(array, begin, mid); - mergeSort(array, mid + 1, end); - merge(array, begin, mid, end); -} - -int main() { - int arr[] = {38, 27, 43, 3, 9, 82, 10}; - int arrSize = sizeof(arr) / sizeof(arr[0]); - - mergeSort(arr, 0, arrSize - 1); - - for (int i = 0; i < arrSize; i++) { - cout << arr[i] << " "; - } - return 0; -} -``` - -### JavaScript Implementation - -```javascript -function mergeSort(array) { - if (array.length <= 1) { - return array; - } - - const mid = Math.floor(array.length / 2); - const left = array.slice(0, mid); - const right = array.slice(mid); - - return merge(mergeSort(left), mergeSort(right)); -} - -function merge(left, right) { - let resultArray = [], leftIndex = 0, rightIndex = 0; - - while (leftIndex < left.length && rightIndex < right.length) { - if (left[leftIndex] < right[rightIndex]) { - resultArray.push(left[leftIndex]); - leftIndex++; - } else { - resultArray.push(right[rightIndex]); - rightIndex++; - } - } - - return resultArray - .concat(left.slice(leftIndex)) - .concat(right.slice(rightIndex)); -} - -let arr = [38, 27, 43, 3, 9, 82, 10]; -console.log(mergeSort(arr)); -``` - -## Time Complexity Analysis - -- **Best Case**: $O(n log n)$ (all cases) -- **Worst Case**: $O(n log n)$ (all cases) -- **Average Case**: $O(n log n)$ (all cases) - -## Space Complexity Analysis - -- **Space Complexity**: $O(n)$ (due to the temporary arrays used during the merge process) - -## Applications of Merge Sort - -- **Large Data Sets**: Efficient for sorting large datasets, especially when the data cannot be held in memory. -- **External Sorting**: Useful for sorting data stored on external storage devices. -- **Stable Sort**: Maintains the relative order of equal elements, making it suitable for sorting linked lists and other data structures where stability is important. - -## Optimizations and Variations - -### Bottom-Up Merge Sort - -Bottom-Up Merge Sort avoids the recursive calls by iteratively sorting sublists of increasing size. - -### Timsort - -Timsort is a hybrid sorting algorithm derived from Merge Sort and Insertion Sort, designed to perform well on many kinds of real-world data. It is used in the standard libraries of Python and Java. - -## Practical Considerations - -### Stability - -Merge Sort is a stable sorting algorithm, maintaining the relative order of equal elements. - -### Use Cases - - - -- When the array size is large. -- When stability is required. -- When dealing with data stored on external storage. - -## Conclusion - -In this tutorial, we covered the fundamentals of Merge Sort, its implementation in Python, Java, C++, and JavaScript, and various optimizations and applications. Merge Sort is a powerful and versatile sorting algorithm, ideal for large datasets and scenarios where stability is crucial. By mastering Merge Sort, you can effectively handle complex sorting tasks in your projects. \ No newline at end of file diff --git a/dsa/Algorithms/Sorting/quick-sort.md b/dsa/Algorithms/Sorting/quick-sort.md deleted file mode 100644 index b2a0cd4cf..000000000 --- a/dsa/Algorithms/Sorting/quick-sort.md +++ /dev/null @@ -1,231 +0,0 @@ ---- -id: quick-sort -title: Quick Sort -sidebar_label: Quick Sort -tags: [python, java, c++, javascript, programming, algorithms, sorting, data structures, tutorial, in-depth] -description: In this tutorial, we will learn about Quick Sort and its implementation in Python, Java, C++, and JavaScript with detailed explanations and examples. ---- - -# Quick Sort - -Quick Sort is a highly efficient and widely used sorting algorithm. It is a comparison-based algorithm that uses the divide-and-conquer strategy to sort elements. This tutorial will cover the basics of Quick Sort, its applications, and how to implement it in Python, Java, C++, and JavaScript. We will also delve into various optimizations and advanced use cases. - -## Introduction to Quick Sort - -Quick Sort was developed by Tony Hoare in 1959. It is known for its efficiency in practice and has an average-case time complexity of O(n log n). Quick Sort works by selecting a 'pivot' element from the array and partitioning the other elements into two sub-arrays according to whether they are less than or greater than the pivot. - -## How Quick Sort Works - -- **Step 1: Choose a Pivot**: Select a pivot element from the array. -- **Step 2: Partition**: Rearrange the elements in the array so that all elements less than the pivot come before it and all elements greater than the pivot come after it. -- **Step 3: Recursively Sort**: Recursively apply the above steps to the sub-arrays of elements with smaller and larger values. - -![Quick Sort Process](https://runestone.academy/ns/books/published/pythonds/_images/partitionA.png) - -## Pseudocode for Quick Sort - -Here is the pseudocode for Quick Sort: - -``` -function quickSort(arr, low, high): - if low < high: - pi = partition(arr, low, high) - quickSort(arr, low, pi - 1) - quickSort(arr, pi + 1, high) - -function partition(arr, low, high): - pivot = arr[high] - i = low - 1 - for j = low to high - 1: - if arr[j] <= pivot: - i = i + 1 - swap arr[i] with arr[j] - swap arr[i + 1] with arr[high] - return i + 1 -``` - -## Implementing Quick Sort - -### Python Implementation - -```python -def quick_sort(arr, low, high): - if low < high: - pi = partition(arr, low, high) - quick_sort(arr, low, pi - 1) - quick_sort(arr, pi + 1, high) - -def partition(arr, low, high): - pivot = arr[high] - i = low - 1 - for j in range(low, high): - if arr[j] <= pivot: - i += 1 - arr[i], arr[j] = arr[j], arr[i] - arr[i + 1], arr[high] = arr[high], arr[i + 1] - return i + 1 - -arr = [10, 7, 8, 9, 1, 5] -n = len(arr) -quick_sort(arr, 0, n - 1) -print(f"Sorted array is: {arr}") -``` - -### Java Implementation - -```java -public class QuickSort { - - public static void quickSort(int[] arr, int low, int high) { - if (low < high) { - int pi = partition(arr, low, high); - quickSort(arr, low, pi - 1); - quickSort(arr, pi + 1, high); - } - } - - public static int partition(int[] arr, int low, int high) { - int pivot = arr[high]; - int i = (low - 1); - for (int j = low; j < high; j++) { - if (arr[j] <= pivot) { - i++; - int temp = arr[i]; - arr[i] = arr[j]; - arr[j] = temp; - } - } - - int temp = arr[i + 1]; - arr[i + 1] = arr[high]; - arr[high] = temp; - - return i + 1; - } - - public static void main(String[] args) { - int[] arr = {10, 7, 8, 9, 1, 5}; - int n = arr.length; - quickSort(arr, 0, n - 1); - System.out.println("Sorted array: "); - for (int num : arr) { - System.out.print(num + " "); - } - } -} -``` - -### C++ Implementation - -```cpp -#include -using namespace std; - -void swap(int* a, int* b) { - int t = *a; - *a = *b; - *b = t; -} - -int partition(int arr[], int low, int high) { - int pivot = arr[high]; - int i = (low - 1); - for (int j = low; j < high; j++) { - if (arr[j] <= pivot) { - i++; - swap(&arr[i], &arr[j]); - } - } - swap(&arr[i + 1], &arr[high]); - return (i + 1); -} - -void quickSort(int arr[], int low, int high) { - if (low < high) { - int pi = partition(arr, low, high); - quickSort(arr, low, pi - 1); - quickSort(arr, pi + 1, high); - } -} - -int main() { - int arr[] = {10, 7, 8, 9, 1, 5}; - int n = sizeof(arr) / sizeof(arr[0]); - quickSort(arr, 0, n - 1); - cout << "Sorted array: "; - for (int i = 0; i < n; i++) { - cout << arr[i] << " "; - } - return 0; -} -``` - -### JavaScript Implementation - -```javascript -function quickSort(arr, low, high) { - if (low < high) { - let pi = partition(arr, low, high); - quickSort(arr, low, pi - 1); - quickSort(arr, pi + 1, high); - } -} - -function partition(arr, low, high) { - let pivot = arr[high]; - let i = (low - 1); - for (let j = low; j < high; j++) { - if (arr[j] <= pivot) { - i++; - [arr[i], arr[j]] = [arr[j], arr[i]]; - } - } - [arr[i + 1], arr[high]] = [arr[high], arr[i + 1]]; - return (i + 1); -} - -let arr = [10, 7, 8, 9, 1, 5]; -quickSort(arr, 0, arr.length - 1); -console.log("Sorted array:", arr); -``` - -## Time Complexity Analysis - -- **Best Case**: $O(n log n)$ (when the pivot divides the array into two equal halves) -- **Worst Case**: $O(n²)$ (when the pivot is the smallest or largest element) -- **Average Case**: $O(n log n)$ (for random pivot selection) - -## Space Complexity Analysis - -- **Space Complexity**: O(log n) (for recursive stack space) - -## Applications of Quick Sort - -- **Efficient Sorting**: Quick Sort is generally faster than Merge Sort for smaller arrays and is often the go-to algorithm for in-place sorting. -- **Divide and Conquer**: Its divide-and-conquer approach makes it suitable for parallel processing. -- **Memory Efficiency**: Requires minimal additional memory space compared to other sorting algorithms like Merge Sort. - -## Optimizations and Variations - -### Randomized Quick Sort - -Randomized Quick Sort improves performance by randomly selecting the pivot element to minimize the chances of worst-case scenarios. - -### Three-Way Quick Sort - -Three-Way Quick Sort handles arrays with many duplicate elements more efficiently by dividing the array into three parts: elements less than the pivot, equal to the pivot, and greater than the pivot. - -## Practical Considerations - -### Stability - -Quick Sort is not a stable sorting algorithm, which means it does not preserve the relative order of equal elements. - -### Use Cases - -- When the array size is large and average-case performance is more important than worst-case. -- When in-place sorting is required to save memory. - -## Conclusion - -In this tutorial, we covered the fundamentals of Quick Sort, its implementation in Python, Java, C++, and JavaScript, and various optimizations and applications. Quick Sort is a powerful and versatile sorting algorithm that is widely used due to its efficiency and simplicity. By mastering Quick Sort, you can handle complex sorting tasks effectively in your projects. \ No newline at end of file diff --git a/dsa/Algorithms/Sorting/selection-sort.md b/dsa/Algorithms/Sorting/selection-sort.md deleted file mode 100644 index 3d32c76e0..000000000 --- a/dsa/Algorithms/Sorting/selection-sort.md +++ /dev/null @@ -1,188 +0,0 @@ ---- -id: selection-sort -title: Selection Sort -sidebar_label: Selection Sort -tags: [python, java, c++, javascript, programming, algorithms, sorting, data structures, tutorial, in-depth] -description: In this tutorial, we will learn about Selection Sort and its implementation in Python, Java, C++, and JavaScript with detailed explanations and examples. ---- - -# Selection Sort - -Selection Sort is a simple comparison-based sorting algorithm. It is efficient for small lists and is known for its simplicity and ease of implementation. This tutorial will cover the basics of Selection Sort, its applications, and how to implement it in Python, Java, C++, and JavaScript. We will also delve into various optimizations and advanced use cases. - -## Introduction to Selection Sort - -Selection Sort is an in-place comparison sorting algorithm. It has an O(n²) time complexity, making it inefficient on large lists, and generally performs worse than the similar insertion sort. Selection Sort is noted for its simplicity and is often used as an educational tool. - -## How Selection Sort Works - -- **Step 1**: Start with the first element as the minimum. -- **Step 2**: Compare this element with the next element in the list. If the next element is smaller, update the minimum to this element. -- **Step 3**: Continue this process for the rest of the list. -- **Step 4**: Once the end of the list is reached, swap the minimum element with the first element. -- **Step 5**: Move to the next element in the list and repeat steps 1-4 until the list is sorted. - - -![selection sort](https://runestone.academy/ns/books/published/pythonds/_images/insertionpass.png) -## Pseudocode for Selection Sort - -Here is the pseudocode for Selection Sort: - -``` -function selectionSort(array): - for i from 0 to length(array) - 1: - minIndex = i - for j from i + 1 to length(array): - if array[j] < array[minIndex]: - minIndex = j - if minIndex != i: - swap(array[i], array[minIndex]) - return array -``` - -## Implementing Selection Sort - -### Python Implementation - -```python -def selection_sort(array): - n = len(array) - for i in range(n): - min_index = i - for j in range(i+1, n): - if array[j] < array[min_index]: - min_index = j - if min_index != i: - array[i], array[min_index] = array[min_index], array[i] - return array - -arr = [64, 25, 12, 22, 11] -print(selection_sort(arr)) -``` - -### Java Implementation - -```java -public class SelectionSort { - - public static void selectionSort(int[] array) { - int n = array.length; - for (int i = 0; i < n-1; i++) { - int minIndex = i; - for (int j = i+1; j < n; j++) { - if (array[j] < array[minIndex]) { - minIndex = j; - } - } - int temp = array[minIndex]; - array[minIndex] = array[i]; - array[i] = temp; - } - } - - public static void main(String[] args) { - int[] arr = {64, 25, 12, 22, 11}; - selectionSort(arr); - for (int num : arr) { - System.out.print(num + " "); - } - } -} -``` - -### C++ Implementation - -```cpp -#include -using namespace std; - -void selectionSort(int array[], int length) { - for (int i = 0; i < length-1; i++) { - int minIndex = i; - for (int j = i+1; j < length; j++) { - if (array[j] < array[minIndex]) { - minIndex = j; - } - } - int temp = array[minIndex]; - array[minIndex] = array[i]; - array[i] = temp; - } -} - -int main() { - int arr[] = {64, 25, 12, 22, 11}; - int length = sizeof(arr) / sizeof(arr[0]); - selectionSort(arr, length); - for (int i = 0; i < length; i++) { - cout << arr[i] << " "; - } - return 0; -} -``` - -### JavaScript Implementation - -```javascript -function selectionSort(array) { - let n = array.length; - for (let i = 0; i < n-1; i++) { - let minIndex = i; - for (let j = i+1; j < n; j++) { - if (array[j] < array[minIndex]) { - minIndex = j; - } - } - if (minIndex != i) { - let temp = array[minIndex]; - array[minIndex] = array[i]; - array[i] = temp; - } - } - return array; -} - -let arr = [64, 25, 12, 22, 11]; -console.log(selectionSort(arr)); -``` - -## Time Complexity Analysis - -- **Best Case**: $O(n²)$ (even if the array is already sorted, it still makes n² comparisons) -- **Worst Case**: $O(n²)$ (when the array is sorted in reverse order) -- **Average Case**: $O(n²)$ - -## Space Complexity Analysis - -- **Space Complexity**: $O(1)$ (since it sorts in place and requires only a constant amount of extra memory) - -## Applications of Selection Sort - -- **Small Data Sets**: Efficient for sorting small arrays or lists. -- **When Writing to Memory is Costly**: Selection Sort makes the minimum number of swaps, making it useful in situations where writing to memory is expensive. - -## Optimizations and Variations - -### Min-Heap Sort - -Min-Heap Sort is a variation that uses a min-heap to improve selection of the smallest element, making it more efficient for certain data sets. - -### Double Selection Sort - -Double Selection Sort performs two selection processes simultaneously, selecting both the minimum and maximum elements in a single pass, which can reduce the number of passes by half. - -## Practical Considerations - -### Stability - -Selection Sort is not a stable sorting algorithm, meaning it does not necessarily maintain the relative order of equal elements. - -### Use Cases - -- Selection Sort is used when the array size is small. -- It is used when additional memory space is not available. -- It is useful when the number of writes/swaps must be minimized. - -## Conclusion - -In this tutorial, we covered the fundamentals of Selection Sort, its implementation in Python, Java, C++, and JavaScript, and various optimizations and applications. Selection Sort is a straightforward sorting algorithm, ideal for small data sets and educational purposes. By mastering Selection Sort, you can effectively handle simple sorting tasks in your projects. \ No newline at end of file diff --git a/dsa/Algorithms/hashing.md b/dsa/Algorithms/hashing.md index e5b965396..9d64ef340 100644 --- a/dsa/Algorithms/hashing.md +++ b/dsa/Algorithms/hashing.md @@ -297,7 +297,7 @@ console.log(ht.lookup("apple")); ## Space Complexity Analysis -- **Space Complexity**: O(n) where n is the number of key-value pairs +- **Space Complexity**: $O(n)$ where n is the number of key-value pairs ## Advanced Topics