Skip to content

Commit 9421b0c

Browse files
ClémentClément
authored andcommitted
Adding some explanations on sorting algorithms.
1 parent 165f52c commit 9421b0c

File tree

2 files changed

+93
-22
lines changed

2 files changed

+93
-22
lines changed

source/code/projects/Sorting/Sorting/Sorting.cs

Lines changed: 13 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -53,25 +53,21 @@ private static int LeftChild(int i)
5353
{
5454
return 2 * i + 1;
5555
}
56+
// Done with helper method for Heapsort
5657

57-
// Done with helper method for Heapsort
58-
59-
// Heapsort Algorithm
58+
// Heapsort algorithm
6059
public static void Heapsort(List<T> listP)
6160
{
62-
Heapsort(listP, listP.Count);
63-
}
64-
65-
private static void Heapsort(List<T> listP, int N)
66-
{
67-
for (int i = N / 2; i >= 0; i--) /* BuildHeap */
68-
PercDown(listP, i, N);
69-
for (int i = N - 1; i > 0; i--)
70-
{
71-
Swap(listP, 0, i); /* DeleteMax */
72-
PercDown(listP, 0, i);
61+
// Step 1: heapify, or build heap.
62+
for (int i = listP.Count / 2; i >= 0; i--)
63+
PercDown(listP, i, listP.Count);
64+
// Step 2: recursively extract the largest value.
65+
for (int i = listP.Count - 1; i > 0; i--)
66+
{
67+
Swap(listP, 0, i);
68+
PercDown(listP, 0, i);
69+
}
7370
}
74-
}
7571

7672
private static void PercDown(List<T> listP, int i, int N)
7773
{
@@ -95,14 +91,14 @@ private static void PercDown(List<T> listP, int i, int N)
9591
listP[i] = current;
9692
}
9793

98-
// Done with heapsort Algorithm
94+
// Done with heapsort algorithm
9995

10096
// Bubble Algorithm
10197
public static void BubbleSort(List<T> listP)
10298
{
10399
for (int i = listP.Count - 1; i >= 0; i--)
104100
{
105-
for (int j = 0; j < listP.Count - 1; j++)
101+
for (int j = 0; j < i; j++)
106102
{
107103
if (listP[j].CompareTo(listP[j + 1]) > 0)
108104
Swap(listP, j, j + 1);

source/lectures/misc/sorting.md

Lines changed: 80 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -51,17 +51,28 @@ We start by defining two simple "helper" methods:
5151

5252
## Insertion Sort Algorithm
5353

54+
### Implementation
55+
5456
This algorithm is [nicely explained and illustrated on wikipedia](https://en.wikipedia.org/wiki/Insertion_sort), and can be implemented as follows:
5557

5658
```
5759
!include`snippetStart="// Insertion Algorithm", snippetEnd="// Done with insertion Algorithm"` code/projects/Sorting/Sorting/Sorting.cs
5860
```
5961

62+
### Description
63+
64+
This algorithm moves the `bar` from the beginning of the list to the end, one by one.
65+
At every step, it position a `slot` on the bar and look *back*, moving the value at the `slot` earlier and earlier on as long as its predecessor is smaller than itself.
66+
67+
### Complexity
68+
6069
[As explained on wikipedia](https://en.wikipedia.org/wiki/Insertion_sort#Best,_worst,_and_average_cases), the simplest worst case input is an array sorted in reverse order.
61-
With an array sorted in reverse order, every iteration of the inner loop will scan and shift the entire sorted subsection of the array before inserting the next element. This gives insertion sort a quadratic running time (i.e., $O(n^2)$).
70+
With an array sorted in reverse order, every iteration of the inner loop will scan and shift the entire sorted subsection of the array (i.e., from `bar` to the beginning) before inserting the next element. This gives a quadratic running time (i.e., $O(n^2)$).
6271

6372
## Heapsort Algorithm
6473

74+
### Implementation
75+
6576
We first define some helper methods:
6677

6778
```
@@ -71,25 +82,89 @@ We first define some helper methods:
7182
and then leverage the heap structure to sort:
7283

7384
```
74-
!include`snippetStart="// Heapsort Algorithm", snippetEnd="// Done with heapsort Algorithm"` code/projects/Sorting/Sorting/Sorting.cs
85+
!include`snippetStart="// Heapsort algorithm", snippetEnd="// Done with heapsort algorithm"` code/projects/Sorting/Sorting/Sorting.cs
7586
```
7687

7788
Note that `PercDown` builds a *max heap*: once the values are "pre-sorted **greater value first**", removing the first one to move it to the *end* of the list makes the list sorted from smallest to greatest value once we are done.
7889

79-
The `PercDown` is first called $N / 2$ times, which is equivalent to $O(n)$.
80-
Its complexity is $O(\log(n))$, and it is called a second time $O(n)$ times.
81-
So, we get an overall performance of $O((n + n) \times \log n) = O(n \times \log(n))$.
90+
### Description
91+
92+
This algorithm works in two steps:
93+
94+
- First, it constructs the heap "in-place", by arranging the elements from the last-to-lower level (`listP.Count / 2` corresponds to "the last parent") to the first level (`i >=0`), in increasing order (i.e., this is a max heap, the greater value is first),
95+
- Then, it recursively extract the first element, and place it after the end of the heap: note that `PercDown(listP, 0, i)` makes it so that the heap is considered to stop at index `i`, as it decreases in size by 1 at every iteration.
96+
97+
### Complexity
98+
99+
- The `PercDown` method has complexity $O(\log(n))$, since it iterates through the tree from top to bottom, i.e., it is relative to the tree height, which is $O(\log(n))$.
100+
- The first step calls `PercDown` $n / 2$ times, which is equivalent to $O(n)$, so overall this first step is $O(n \times \log(n))$.
101+
- The second step also calls `PercDown` $n$ times, so it is overall $O(n \times \log(n))$ as well.
102+
103+
Hence, the complexity of heapsort is $O(n \times \log(n))$ by [the sum rule](./docs/programming_and_computer_usage/complexity#simplifications).
82104

83105
## Bubble Algorithm
84106

107+
### Implementation
85108

86109
```
87110
!include`snippetStart="// Bubble Algorithm", snippetEnd="// Done with bubble algorithm."` code/projects/Sorting/Sorting/Sorting.cs
88111
```
89112

113+
### Description
114+
115+
The nested loop accomplishes the following: "from the beginning of the list to where I stopped the last time -1, go through the elements one by one and swap them if needed".
116+
117+
### Complexity
118+
119+
Since both loops depends on the size of the list, $n$, the algorithm is overall $O(n^2)$: we need to perform $n$ times $n$ operations.
120+
90121
## ShellSort Algorithm
91122

123+
### Implementation
124+
92125
```
93126
!include`snippetStart="// ShellSort Algorithm", snippetEnd="// Done with shellSort algorithm."` code/projects/Sorting/Sorting/Sorting.cs
94127
```
95128

129+
### Description
130+
131+
Consider a list of size 30, we have (assuming `current.CompareTo(listP[slot - gap]) < 0` is always `true`):
132+
133+
`gap` | `next` | `slot` | `slot - gap`
134+
---- | ---- | ----- | ----- |
135+
11 | 11 | 11 | 0
136+
" | 12 | 12 | 1
137+
" | 13 | 13 | 2
138+
… | … | … | … |
139+
" | 22 | 22 | 11
140+
" | " | 11 | 0
141+
" | 23 | 23 | 12
142+
" | " | 12 | 1
143+
… | … | … | … |
144+
11 | 30 | 30 | 19
145+
" | " | 19 | 8
146+
5 | 5 | 5 | 0
147+
" | " | 6 | 1
148+
" | " | 7 | 2
149+
… | … | … | … |
150+
" | 10 | 10 | 5
151+
" | 10 | 5 | 0
152+
" | 11 | 11 | 6
153+
" | " | 6 | 1
154+
… | … | … | … |
155+
2 |
156+
… | … | … |
157+
1 |
158+
159+
The important point is to understand that we generate the sequences
160+
- *Gap of 11*: (11, 0), (12, 1), (13, 2), … (22, 11), (11, 0), (23, 12), (12, 1), (30, 19), (19, 8),
161+
- *Gap of 5*: (5, 0), (11, 6), (6, 1), …
162+
163+
which are sequences of values we are comparing.
164+
After we are done going through "the $i$ gap", we know that all values $i$ indices apart are sorted.
165+
Reducing the value of $i$ to $1$ makes it so that the whole array is sorted.
166+
167+
168+
### Complexity
169+
170+

0 commit comments

Comments
 (0)