mirror of
https://git.adityakumar.xyz/dsa.git
synced 2024-11-21 09:42:52 +00:00
add selection sort
This commit is contained in:
parent
810d524abc
commit
8b6289d4f6
4 changed files with 241 additions and 0 deletions
18
.gitignore
vendored
Normal file
18
.gitignore
vendored
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
# ---> Hugo
|
||||||
|
# Generated files by hugo
|
||||||
|
/public/
|
||||||
|
/resources/_gen/
|
||||||
|
/assets/jsconfig.json
|
||||||
|
hugo_stats.json
|
||||||
|
|
||||||
|
# Executable may be added to repository
|
||||||
|
hugo.exe
|
||||||
|
hugo.darwin
|
||||||
|
hugo.linux
|
||||||
|
|
||||||
|
# Temporary lock file while building
|
||||||
|
/.hugo_build.lock
|
||||||
|
|
||||||
|
# Ignore swap files
|
||||||
|
*.swp
|
||||||
|
*~
|
9
content/_index.md
Normal file
9
content/_index.md
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
---
|
||||||
|
title: "Data Strcutures and Algorithms"
|
||||||
|
date: 2024-05-28T08:15:27+05:30
|
||||||
|
type: docs
|
||||||
|
---
|
||||||
|
|
||||||
|
# Data Structures and Algorithms
|
||||||
|
|
||||||
|
On this website, I document my explorations into the realm of Data Structures and Algorithms to serve as a personal resource for future reflection.
|
68
content/docs/dsa/sorting/_index.md
Normal file
68
content/docs/dsa/sorting/_index.md
Normal file
|
@ -0,0 +1,68 @@
|
||||||
|
---
|
||||||
|
title: "Sorting"
|
||||||
|
date: 2024-05-28T07:49:20+05:30
|
||||||
|
bookCollapseSection: true
|
||||||
|
---
|
||||||
|
|
||||||
|
# Sorting
|
||||||
|
|
||||||
|
This section contains entries related to sorting algorithms.
|
||||||
|
|
||||||
|
Sorting in data structures and algorithms involves rearranging a collection of items, such as
|
||||||
|
numbers or strings, into a sequence or list where the elements are organized according to a
|
||||||
|
particular criterion (e.g., ascending numerical value). Various algorithms have been developed for
|
||||||
|
this purpose, each with its own advantages and trade-offs in terms of time complexity, space
|
||||||
|
efficiency, stability, adaptability, and ease of implementation. Some widely known sorting
|
||||||
|
algorithms include:
|
||||||
|
|
||||||
|
1. **Bubble Sort** - A simple comparison-based algorithm that repeatedly steps through the list,
|
||||||
|
compares adjacent elements, and swaps them if they are in the wrong order. It has a time complexity
|
||||||
|
of O(n^2) in its average and worst cases.
|
||||||
|
|
||||||
|
2. **Selection Sort** - This algorithm divides the input list into two parts: a sorted sublist of
|
||||||
|
items that are built up from left to right at the front (or beginning) of the list, and an unsorted
|
||||||
|
sublist. On each iteration, it selects the smallest or largest element (depending on sorting order)
|
||||||
|
from the unsorted sublist and moves that element to the end of the sorted sublist. Its time
|
||||||
|
complexity is O(n^2).
|
||||||
|
|
||||||
|
3. **Insertion Sort** - Builds the final sorted array one item at a time. It has an average and
|
||||||
|
worst-case performance of O(n^2), but it's efficient for small datasets or nearly sorted arrays,
|
||||||
|
with best-case time complexity being O(n).
|
||||||
|
|
||||||
|
4. **Merge Sort** - A divide-and-conquer algorithm that divides the input array into two halves,
|
||||||
|
recursively sorts them, and then merges the two sorted halves together. It has a time complexity of
|
||||||
|
O(n log n) in all cases.
|
||||||
|
|
||||||
|
5. **Quick Sort** - Also utilizes a divide-and-conquer strategy 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. The time complexity in average cases is O(n log n), but it can
|
||||||
|
degrade to O(n^2) if the smallest or largest element is always chosen as the pivot.
|
||||||
|
|
||||||
|
6. **Heap Sort** - Builds a heap data structure from the input data and then repeatedly extracts
|
||||||
|
the maximum (or minimum) element from the heap, swapping it with the last item in the unsorted
|
||||||
|
portion of the array, and re-heaping the reduced array. The time complexity is O(n log n).
|
||||||
|
|
||||||
|
7. **Radix Sort** - This non-comparative integer sorting algorithm sorts data with integer keys by
|
||||||
|
grouping keys by the individual digits which share the same significant position and value (radix).
|
||||||
|
It has a linear time complexity of O(nk) where k is the number of passes of the sorting algorithm
|
||||||
|
and n is the number of elements.
|
||||||
|
|
||||||
|
8. **Counting Sort** - Suitable for sorting integer arrays when the range of potential items in the
|
||||||
|
input (i.e., their possible key values) is relatively small compared to the number of items. Its
|
||||||
|
time complexity varies based on the specific implementation but generally has a linear time
|
||||||
|
complexity, O(n+k), where k is the range of the input.
|
||||||
|
|
||||||
|
9. **Bucket Sort** - Works by distributing elements into several 'buckets' and then sorting these
|
||||||
|
buckets individually using a different sorting algorithm or by recursively applying bucket sort to
|
||||||
|
each bucket. Its time complexity can be as good as O(n+k) where n is the number of elements and k
|
||||||
|
is the number of buckets, but it often performs better than O(n log n).
|
||||||
|
|
||||||
|
10. **Timsort** - A hybrid sorting algorithm derived from merge sort and insertion sort designed to
|
||||||
|
perform well on many kinds of real-world data. It's used as the default sort in Python and Java.
|
||||||
|
Timsort has a time complexity of O(n log n) for average and worst cases.
|
||||||
|
|
||||||
|
The choice of a particular sorting algorithm depends on several factors, including but not limited
|
||||||
|
to: the size and nature of the dataset, the computational resources available (such as CPU and
|
||||||
|
memory), the desired level of stability in the output, whether parallel computing is involved, etc.
|
||||||
|
|
||||||
|
{{<section summary >}}
|
146
content/docs/dsa/sorting/selection-sort.md
Normal file
146
content/docs/dsa/sorting/selection-sort.md
Normal file
|
@ -0,0 +1,146 @@
|
||||||
|
---
|
||||||
|
title: "Selection Sort"
|
||||||
|
date: 2024-05-28T07:49:30+05:30
|
||||||
|
---
|
||||||
|
|
||||||
|
# Selection Sort
|
||||||
|
|
||||||
|
Selection Sort is a simple comparison-based sorting algorithm. It operates by repeatedly finding
|
||||||
|
the minimum element (considering ascending order) from the unsorted part of an array and putting it
|
||||||
|
at the beginning. The process involves dividing the input list into two parts: a sorted sublist
|
||||||
|
which is built up from left to right, and an unsorted sublist where elements are not yet in their
|
||||||
|
final position.
|
||||||
|
|
||||||
|
<!--more-->
|
||||||
|
|
||||||
|
## Algorithm
|
||||||
|
|
||||||
|
Here's how Selection Sort works step by step:
|
||||||
|
|
||||||
|
1. Start with the first element of the array as the minimum.
|
||||||
|
|
||||||
|
2. Compare this "current" minimum with the rest of the array to find a new minimum.
|
||||||
|
|
||||||
|
3. Once you have found the true minimum, swap it with the value at the current position.
|
||||||
|
|
||||||
|
4. Move one position ahead in the array and consider this element as part of the unsorted segment
|
||||||
|
while treating the remaining elements as the sorted sublist.
|
||||||
|
|
||||||
|
5. Repeat steps 2-4 until the entire list is sorted.
|
||||||
|
|
||||||
|
The algorithm's time complexity is O(n<sup>2</sup>) for all cases (worst, average, and best), making it
|
||||||
|
inefficient on large lists compared to more advanced algorithms like quicksort, mergesort or
|
||||||
|
heapsort. However, Selection Sort has its advantages such as simplicity and performing only a
|
||||||
|
minimal number of swaps, which can be beneficial when the cost of swap is high.
|
||||||
|
|
||||||
|
## Code
|
||||||
|
|
||||||
|
Here is an implementation in C++.
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
import <print>;
|
||||||
|
import <vector>;
|
||||||
|
|
||||||
|
constexpr auto sort(std::vector<ssize_t> &vec) -> void {
|
||||||
|
for (auto it1{vec.begin()}; it1 < vec.end(); ++it1) {
|
||||||
|
auto it{it1};
|
||||||
|
for (auto it2{it1 + 1}; it2 < vec.end(); ++it2) {
|
||||||
|
if (*it2 < *it) {
|
||||||
|
it = it2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
auto temp{*it1};
|
||||||
|
*it1 = *it;
|
||||||
|
*it = temp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
std::vector<ssize_t> v{4, 7, 3, 7, 2, 7, 4, 64, 32, 65,
|
||||||
|
32, 4, 5, 5, 6456, 4, 5, 53, 5};
|
||||||
|
sort(v);
|
||||||
|
|
||||||
|
for (const auto &a : v) {
|
||||||
|
std::print("{} ", a);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
## Explanation
|
||||||
|
|
||||||
|
### Function Signature
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
constexpr auto sort(std::vector<ssize_t> &vec) -> void
|
||||||
|
```
|
||||||
|
|
||||||
|
- `constexpr`: This keyword indicates that the function can be evaluated at compile time if provided with constant expressions. This is useful for performance optimization in some cases.
|
||||||
|
- `auto sort`: Uses the auto keyword to automatically deduce the return type. In this case, the return type is explicitly specified as `void`.
|
||||||
|
- `(std::vector<ssize_t> &vec)`: The function takes a reference to a `std::vector` of `ssize_t` integers as its parameter. Using a reference avoids copying the vector and allows the function to modify the original vector.
|
||||||
|
- `-> void`: This specifies the return type of the function, which is `void` (meaning it doesn't return a value).
|
||||||
|
|
||||||
|
### Function Body
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
{
|
||||||
|
for (auto it1{vec.begin()}; it1 < vec.end(); ++it1) {
|
||||||
|
auto it{it1};
|
||||||
|
for (auto it2{it1 + 1}; it2 < vec.end(); ++it2) {
|
||||||
|
if (*it2 < *it) {
|
||||||
|
it = it2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
auto temp{*it1};
|
||||||
|
*it1 = *it;
|
||||||
|
*it = temp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
1. **Outer Loop (Selection Sort)**:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
for (auto it1{vec.begin()}; it1 < vec.end(); ++it1)
|
||||||
|
```
|
||||||
|
|
||||||
|
- This loop iterates over each element of the vector from the beginning to the end.
|
||||||
|
- `it1` is an iterator starting from the beginning of the vector and moving towards the end.
|
||||||
|
|
||||||
|
2. **Inner Loop (Finding Minimum)**
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
auto it{it1};
|
||||||
|
for (auto it2{it1 + 1}; it2 < vec.end(); ++it2) {
|
||||||
|
if (*it2 < *it) {
|
||||||
|
it = it2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
- The inner loop starts from the next element after `it1` and iterates to the end of the vector.
|
||||||
|
- `it` initially points to `it1`, which is the current element in the outer loop.
|
||||||
|
- `it2` iterates over the remaining elements to find the smallest element.
|
||||||
|
- If `*it2` (the value pointed to by `it2`) is smaller than `*it` (the value pointed to by `it`), `it` is updated to point to `it2`.
|
||||||
|
|
||||||
|
3. **Swapping Elements**:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
auto temp{*it1};
|
||||||
|
*it1 = *it;
|
||||||
|
*it = temp;
|
||||||
|
```
|
||||||
|
|
||||||
|
- After finding the smallest element in the unsorted portion of the vector, the smallest element (pointed to by `it`) is swapped with the element at the position `it1`.
|
||||||
|
- `temp` temporarily holds the value of `*it1`.
|
||||||
|
- `*it1` is set to `*it` (the smallest element found).
|
||||||
|
- `*it` is then set to `temp` to complete the swap.
|
||||||
|
|
||||||
|
## Output
|
||||||
|
|
||||||
|
```console
|
||||||
|
❯ ./main
|
||||||
|
2 3 4 4 4 4 5 5 5 5 7 7 7 32 32 53 64 65 6456 [ble: EOF]
|
||||||
|
```
|
Loading…
Reference in a new issue