Selection sort
Idea
The concept is quite straight.
If we could get the minimal value from list one by one,
then we could re-arrange the list from minimal to maximal values.
Imagine we have two lists L and Lsorted,
the L is a list contains several items with comparable values and
the Lsorted is a sorted list of L.
At first, Lsorted=[] is empty.
Take L=[5,3,1,2,3] as an example:
- At the first round, we get 1 as minimal value,
so we move it into Lsorted. Now,
- Lsorted=[1]
- L=[5,3,2,3]
- At the second round, we get 2 as minimal value, so
- Lsorted=[1,2]
- L=[5,3,3]
- Next, 3 is picked and moved from L to Lsorted, so
- Lsorted=[1,2,3]
- L=[5,3]
- Then, the current minimal value 3 is moved from L to Lsorted, so
- Lsorted=[1,2,3,3]
- L=[5]
- Finally, 5 is moved into Lsorted, so
- Lsorted=[1,2,3,3,5]
- L=[]
See! the idea is quite simple.
In the same way, to sort the list from maximal to minimal values,
the only different is to pick the maximal value from list each round
instead of minimal value.
How to get minimal(or maximal) value
The way to get minimal(or maximal) items in L
is to linearly search the whole list:
Min(L): min=L[1] for i←1 to N: if L[i]<min: min=L[i]
or
Max(L): max=L[1] for i←1 to N: if L[i]>max: max=L[i]
, where L[i] is the ith element in the list L
and N is the length of L.
Dividing one list into unsorted list and sorted list
In implementation, we usually divide the source list,
which needs to be sorted, into two parts. One is sorted, the other is unsorted.
This is better for memory usage than
creating another list to put the sorted results.
That is, if we have a source list L=[5,3,1,2,3],
it will be divided into Lsorted and Lunsorted.
They are initialized to [] and L respectively,
so L=Lsorted∪Lunsorted=[]∪[5,3,1,2,3].
- In the first round, 1 is picked and moved
from Lunsorted to Lsorted, so
- L=Lsorted∪Lunsorted=[1]∪[5,3,2,3]=[1∣5,3,2,3]
- In the second round, 2 is picked and moved
from Lunsorted to Lsorted, so
- L=Lsorted∪Lunsorted=[1,2]∪[5,3,3]=[1,2∣5,3,3]
- Next, 3 is picked, so
- L=Lsorted∪Lunsorted=[1,2,3]∪[5,3]=[1,2,3∣5,3]
- Then, another 3 is picked, so
- L=Lsorted∪Lunsorted=[1,2,3,3]∪[5]=[1,2,3,3∣5]
- Finally, 5 is picked, so
- L=Lsorted∪Lunsorted=[1,2,3,3,5]∪[]=[1,2,3,3,5]
Algorithm
SelectionSort(L): for i←1 to ∣L∣−1: m←i for j←i+1 to ∣L∣: if L[j]<L[m]: m←j swap L[i] and L[m]
The above method will divide L into two parts.
- L[1...i−1]=Lsorted is sorted
- L[i...N]=Lunsorted is unsorted,
- where N=∣L∣ is the length of L
The following are step by step explanation:
- When i=1
- Lsorted=[] and Lunsorted=L[1...N]
- we need to find the minimal element in list L[1...N]
- We use a value m to track the index of the minimal element
- where m is initialized to 1
- m will be updated to j, where 2≤j≤N, if L[j]<L[m]
- Repeatedly above instruction from j=2 to N(searching whole Lunsorted),
L[m] would be the minimal value in L[1...N]
- swap L[m] and L[i=1]
- then L[1] now can be considered as Lsorted
- so Lunsorted=L[2...N]
- When i=2
- Lsorted=L[1] and Lunsorted=L[2...N]
- we need to find the minimal element in list L[2...N]
- Same as above, m is used to keep tracking the index of the minimal
element in Lunsorted
- where m is initialized to 2
- After searching the whole Lunsorted,
L[m] would be the minimal value in L[2...N]
- We can put L[m] into the Lsorted by swapping the L[m] and L[i=2]
- Thus, Lsorted=L[1...2] and Lunsorted=L[3...N]
- When i=k
- Lsorted=[1...k−1] and Lunsorted=L[k...N]
- m is initialized to k
- After searching the whole Lunsorted,
L[m] would be the minimal value in L[k...N]
- Swapping L[m] and L[i=k] would put L[m] into Lsorted
- Then, Lsorted=L[1...k] and Lunsorted=L[k+1...N]
- When i=N−1(final round)
- Lsorted=[1...N−2] and Lunsorted=L[N−1...N]
- m is initialized to N−1
- Pick a smaller one between L[N−1] and L[N]
- and put it into the Lsorted like above(by swapping with L[m])
- Then Lsorted=[1...N−1] and Lunsorted=L[N]
- The left one(now is L[N]) is definitely the maximal item
in L[1...N], so we don't need to do anything
Proof
Proof by contradiction
- Assume this method can not give us an ordered list
- so it exists one L[p]>L[q], where p<q, in the result list L
- Before the result is computed, the unsorted list could be
L[..p..q..] or L[..q..p..]
- It means that L[p] is picked before L[q]
because p<q in the result list L
- It means L[p]<L[q] and it is contradictory to the assumption
- Thus, the assumption is wrong. This method will give us an ordered list.
Complexity
We need to search whole Lunsorted to find a minimal(or maximal) item.
Suppose ∣Lunsorted∣=N at first.
(the length of Lunsorted is N).
At the first round, we need to search N items
to find the minimal(or maximal) item and move it into Lsorted.
After then, ∣Lunsorted∣=N−1.
At the second round, whole N−1 items in Lunsorted would be counted
to find the minimal(or maximal) one.
After the picked one is moved into Lsorted,
the size of Lunsorted is reduced to ∣Lunsorted∣=N−2.
The procedure keep working until the list Lunsorted is empty
(∣Lunsorted∣=0).
Thus, we need to search
N+(N−1)+(N−2)+....+1=2N⋅(N+1)=21⋅N2+21N
times to move all the items into Lsorted.
Thus, the complexity is O(N2),
where the N is the length of the list L.
Implementation
See the files on gist here.