Copy codeThe Code is as follows:
#-*-Coding: UTF-8 -*-
From random import randint
From math import ceil, floor
Def _ partition (A, l, r, I ):
"Uses A [I] as the primary element to divide the array A [l. r] so that:
A [l .. M-1] <= A [m] <A [m + 1. r]
"""
A [I], A [r] = A [r], A [I] # I is switched to the last r as the principal component
Principal = A [r] # Principal Component
M = l # index tag
For n in xrange (l, r): # l .. R-1
If A [n] <= then:
A [m], A [n] = A [n], A [m] # exchange
M + = 1 # Move back
A [m], A [r] = A [r], A [m] # principal component to m bit
Return m
Def _ rand (A, l, r ):
"Random division of Principal Components """
Return randint (l, r) # A [l. r] Random
Def _ select (A, l, r, k, effect_selector = _ rand ):
"Uses the fast rank to obtain the number of k smaller values in A [l. r], k in [l + 1, r + 1]:
Its tail recursion method, the pseudo code is as follows:
SELECT (A, l, r, k)
1 while true:
2 I branch? // Divide the principal component Position
3 m PARTITION (A, l, r, I) // array Division
4 n then m-l + 1 // A [l. m] Number of Elements
5 if k = n // check whether A [m] is A small k element.
6 then return A [m]
7 elseif k <n // left Partition
8 r = m-1
9 else // right Partition
10 k = k-n
11 l = m + 1
Args:
Effect_selector (Function): Specifies the principal component selection method. The default value is random.
"""
If not:
Return None
If l = r:
Return A [l]
While True:
I = effect_selector (A, l, r)
M = _ partition (A, l, r, I)
N = m-l + 1
If k = n:
Return A [m]
Elif k <n:
R = m-1
Else:
K = k-n
L = m + 1
Def rand_select (A, k ):
"Default random division of principal components, k in [1, len (A)]
E [T (n)] = O (n)
"""
Return _ select (A, 0, len (A)-1, k );
Def _ median (A, l, r ):
"Insert A [l. r] To sort (in situ) and select the position of the digits """
For j in xrange (l, r + 1 ):
K = A [j]
I = j
While I> l and A [I-1]> k:
A [I] = A [I-1]
I-= 1
A [I] = k
Return l + int (r-l) * 0.5) # lower median
Def _ medianOfMedians (A, l, r ):
"Median method:
1. Divided into floor (n/5) 5 tuples, and the rest (n % 5) form the last group.
2. Find the respective median of the ceil (n/5) groups. Insert and sort each group, and then select the median.
3. Repeat the preceding operation on the ceil (n/5) medians found in step 1 until there is only one median.
"""
If l = r:
Return l
N = r-l + 1 # Number of Elements
M = int (ceil (n/5.0) # Number of groups, each with 5 elements
For I in xrange (m ):
# Start and second bits of each group
Sub_l = l + I * 5
Sub_r = sub_l + 4
If sub_r> r:
Sub_r = r
# After each group of elements is inserted and sorted, select the median
Sub_m = _ median (A, sub_l, sub_r) # median Index
# Switch median to the first digit
J = l + I
A [j], A [sub_m] = A [sub_m], A [j]
Return _ medianOfMedians (A, l, l + m-1) # Median
Def bfprt_select (A, k ):
"Median method (BFPRT algorithm)
T (n) = O (n)
"""
Return _ select (A, 0, len (A)-1, k, _ medianOfMedians );
Def _ median3 (A, l, r ):
"Three-digit median method, take l, r, (l + r)/2 three-digit median """
C = (l + r)/2
Keys = [l, c, r]
I = _ median (keys, 0, 2)
Return keys [I]
Def median_select (A, k ):
"Three-digit median approach to Eliminate the Worst Case """
Return _ select (A, 0, len (A)-1, k, _ median3 );
If _ name _ = '_ main __':
Import random, time
From copy import copy
Print ('preparing data ...')
N = 1000000
Nums = range (n)
Random. shuffle (nums)
Print ('ready go! ')
Def timeit (fnc, * args, ** kargs ):
Print ('% s starts processing' % fnc. _ name __)
Begtime = time. clock ()
Retval = fnc (* args, ** kargs)
Endtime = time. clock ()
Print ('% s takes time: % F' % (fnc. _ name __, endtime-begtime ))
Return retval
Test_methods = [rand_select, bfprt_select, median_select]
K = random. randrange (n) + 1
Dashes = '---' * 10
For test in test_methods:
Print (dashes)
Nums_new = copy (nums)
Result = timeit (test, nums_new, k)
Print (the % dth smallest element: % d' % (k, result ))