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 LL and LsortedL_{sorted}, the LL is a list contains several items with comparable values and the LsortedL_{sorted} is a sorted list of LL. At first, Lsorted=[]L_{sorted} = [ ] is empty.

Take L=[5,3,1,2,3]L = [ 5, 3, 1, 2, 3 ] as an example:

  • At the first round, we get 11 as minimal value, so we move it into LsortedL_{sorted}. Now,
    • Lsorted=[1]L_{sorted} = [ 1 ]
    • L=[5,3,2,3]L = [ 5, 3, 2, 3 ]
  • At the second round, we get 22 as minimal value, so
    • Lsorted=[1,2]L_{sorted} = [ 1, 2 ]
    • L=[5,3,3]L = [ 5, 3, 3 ]
  • Next, 33 is picked and moved from LL to LsortedL_{sorted}, so
    • Lsorted=[1,2,3]L_{sorted} = [ 1, 2, 3 ]
    • L=[5,3]L = [ 5, 3 ]
  • Then, the current minimal value 33 is moved from LL to LsortedL_{sorted}, so
    • Lsorted=[1,2,3,3]L_{sorted} = [ 1, 2, 3, 3 ]
    • L=[5]L = [ 5 ]
  • Finally, 55 is moved into LsortedL_{sorted}, so
    • Lsorted=[1,2,3,3,5]L_{sorted} = [ 1, 2, 3, 3, 5 ]
    • L=[]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 LL is to linearly search the whole list: Min(L):    min=L[1]    for i1 to N:        if L[i]<min:            min=L[i] \begin{aligned} & Min(L): \\ & \space \space \space \space min = L[1] \\ & \space \space \space \space \text{for } i \leftarrow 1 \text{ to } N: \\ & \space \space \space \space \space \space \space \space \text{if } L[i] < min: \\ & \space \space \space \space \space \space \space \space \space \space \space \space min = L[i] \\ \end{aligned} or Max(L):    max=L[1]    for i1 to N:        if L[i]>max:            max=L[i] \begin{aligned} & Max(L): \\ & \space \space \space \space max = L[1] \\ & \space \space \space \space \text{for } i \leftarrow 1 \text{ to } N: \\ & \space \space \space \space \space \space \space \space \text{if } L[i] > max: \\ & \space \space \space \space \space \space \space \space \space \space \space \space max = L[i] \\ \end{aligned} , where L[i]L[i] is the iith element in the list LL and NN is the length of LL.

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]L = [ 5, 3, 1, 2, 3 ], it will be divided into LsortedL_{sorted} and LunsortedL_{unsorted}. They are initialized to [][] and LL respectively, so L=LsortedLunsorted=[][5,3,1,2,3]L = L_{sorted} \cup L_{unsorted} = [ ] \cup [ 5, 3, 1, 2, 3 ].

  • In the first round, 11 is picked and moved from LunsortedL_{unsorted} to LsortedL_{sorted}, so
    • L=LsortedLunsorted=[1][5,3,2,3]=[15,3,2,3]L = L_{sorted} \cup L_{unsorted} = [ 1 ] \cup [ 5, 3, 2, 3 ] = [1 \vert 5, 3, 2, 3]
  • In the second round, 22 is picked and moved from LunsortedL_{unsorted} to LsortedL_{sorted}, so
    • L=LsortedLunsorted=[1,2][5,3,3]=[1,25,3,3]L = L_{sorted} \cup L_{unsorted} = [ 1, 2 ] \cup [ 5, 3, 3 ] = [1, 2 \vert 5, 3, 3]
  • Next, 33 is picked, so
    • L=LsortedLunsorted=[1,2,3][5,3]=[1,2,35,3]L = L_{sorted} \cup L_{unsorted} = [ 1, 2, 3 ] \cup [ 5, 3 ] = [1, 2, 3 \vert 5, 3]
  • Then, another 33 is picked, so
    • L=LsortedLunsorted=[1,2,3,3][5]=[1,2,3,35]L = L_{sorted} \cup L_{unsorted} = [ 1, 2, 3, 3 ] \cup [ 5 ] = [1, 2, 3, 3 \vert 5]
  • Finally, 55 is picked, so
    • L=LsortedLunsorted=[1,2,3,3,5][]=[1,2,3,3,5]L = L_{sorted} \cup L_{unsorted} = [ 1, 2, 3, 3, 5 ] \cup [ ] = [1, 2, 3, 3, 5]

Algorithm

SelectionSort(L):    for i1 to L1:        mi        for ji+1 to L:            if L[j]<L[m]:                mj        swap L[i] and L[m] \begin{aligned} & SelectionSort(L): \\ & \space \space \space \space \text{for } i \leftarrow 1 \text{ to } \vert L \vert - 1: \\ & \space \space \space \space \space \space \space \space m \leftarrow i \\ & \space \space \space \space \space \space \space \space \text{for } j \leftarrow i + 1 \text{ to } \vert L \vert: \\ & \space \space \space \space \space \space \space \space \space \space \space \space \text{if } L[j] < L[m]: \\ & \space \space \space \space \space \space \space \space \space \space \space \space \space \space \space \space m \leftarrow j \\ & \space \space \space \space \space \space \space \space \text{swap } L[i] \text{ and } L[m] \\ \end{aligned}

The above method will divide LL into two parts.

  • L[1...i1]=LsortedL[1...i-1] = L_{sorted} is sorted
  • L[i...N]=LunsortedL[i...N] = L_{unsorted} is unsorted,
  • where N=LN = \vert L \vert is the length of LL

The following are step by step explanation:

  • When i=1i = 1
    • Lsorted=[]L_{sorted} = [] and Lunsorted=L[1...N]L_{unsorted} = L[1...N]
    • we need to find the minimal element in list L[1...N]L[1...N]
    • We use a value mm to track the index of the minimal element
    • where mm is initialized to 11
    • mm will be updated to jj, where 2jN2 \leq j \leq N, if L[j]<L[m]L[j] < L[m]
    • Repeatedly above instruction from j=2j = 2 to NN(searching whole LunsortedL_{unsorted}), L[m]L[m] would be the minimal value in L[1...N]L[1...N]
    • swap L[m]L[m] and L[i=1]L[i = 1]
    • then L[1]L[1] now can be considered as LsortedL_{sorted}
    • so Lunsorted=L[2...N]L_{unsorted} = L[2...N]
  • When i=2i = 2
    • Lsorted=L[1]L_{sorted} = L[1] and Lunsorted=L[2...N]L_{unsorted} = L[2...N]
    • we need to find the minimal element in list L[2...N]L[2...N]
    • Same as above, mm is used to keep tracking the index of the minimal element in LunsortedL_{unsorted}
    • where mm is initialized to 22
    • After searching the whole LunsortedL_{unsorted}, L[m]L[m] would be the minimal value in L[2...N]L[2...N]
    • We can put L[m]L[m] into the LsortedL_{sorted} by swapping the L[m]L[m] and L[i=2]L[i = 2]
    • Thus, Lsorted=L[1...2]L_{sorted} = L[1...2] and Lunsorted=L[3...N]L_{unsorted} = L[3...N]
  • When i=ki = k
    • Lsorted=[1...k1]L_{sorted} = [1...k-1] and Lunsorted=L[k...N]L_{unsorted} = L[k...N]
    • mm is initialized to kk
    • After searching the whole LunsortedL_{unsorted}, L[m]L[m] would be the minimal value in L[k...N]L[k...N]
    • Swapping L[m]L[m] and L[i=k]L[i = k] would put L[m]L[m] into LsortedL_{sorted}
    • Then, Lsorted=L[1...k]L_{sorted} = L[1...k] and Lunsorted=L[k+1...N]L_{unsorted} = L[k+1...N]
  • When i=N1i = N - 1(final round)
    • Lsorted=[1...N2]L_{sorted} = [1...N-2] and Lunsorted=L[N1...N]L_{unsorted} = L[N-1...N]
    • mm is initialized to N1N-1
    • Pick a smaller one between L[N1]L[N-1] and L[N]L[N]
    • and put it into the LsortedL_{sorted} like above(by swapping with L[m]L[m])
    • Then Lsorted=[1...N1]L_{sorted} = [1...N-1] and Lunsorted=L[N]L_{unsorted} = L[N]
    • The left one(now is L[N]L[N]) is definitely the maximal item in L[1...N]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]L[p] > L[q], where p<qp < q, in the result list LL
  • Before the result is computed, the unsorted list could be L[..p..q..]L[..p..q..] or L[..q..p..]L[..q..p..]
  • It means that L[p]L[p] is picked before L[q]L[q] because p<qp < q in the result list LL
  • It means L[p]<L[q]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 LunsortedL_{unsorted} to find a minimal(or maximal) item. Suppose Lunsorted=N\vert L_{unsorted} \vert = N at first. (the length of LunsortedL_{unsorted} is NN).

At the first round, we need to search NN items to find the minimal(or maximal) item and move it into LsortedL_{sorted}. After then, Lunsorted=N1\vert L_{unsorted} \vert = N - 1.

At the second round, whole N1N - 1 items in LunsortedL_{unsorted} would be counted to find the minimal(or maximal) one. After the picked one is moved into LsortedL_{sorted}, the size of LunsortedL_{unsorted} is reduced to Lunsorted=N2\vert L_{unsorted} \vert = N - 2.

The procedure keep working until the list LunsortedL_{unsorted} is empty (Lunsorted=0\vert L_{unsorted} \vert = 0). Thus, we need to search N+(N1)+(N2)+....+1=N(N+1)2=12N2+12N \begin{aligned} N + (N - 1) + (N - 2) + .... + 1 &= \frac{ N \cdot (N + 1) }{ 2 } \\ &= \frac{ 1 }{ 2 } \cdot N^2 + \frac{ 1 }{ 2 } N \end{aligned} times to move all the items into LsortedL_{sorted}. Thus, the complexity is O(N2)\mathcal{O}(N^2), where the NN is the length of the list LL.

Implementation

See the files on gist here.

results matching ""

    No results matching ""