1.[代码][Python]代码
# -*- coding: utf-8 -*-
def step_half(n):
"""Original sequence: n/2, n/4, ..., 1
a(n) = ceil(n/(2^k)), k >= 1
原始步长:从n/2开始不断减半直至1。
"""
while True:
n = n / 2
v = int(n)
yield v
if v <= 1:
return
def _step_sedgewick():
"""Sedgewick's increments: 1, 5, 19, 41, 109, ...
1, 19, 109, 505, 2161, ..., 9(4^k – 2^k) + 1, k = 0, 1, 2, 3, …
5, 41, 209, 929, 3905, ..., 2^(k+2) (2^(k+2) – 3) + 1, k = 0, 1, 2, 3, …
Sedgewick提出的步长序列:用这样步长串行的希尔排序比插入排序和堆排序都要快,
甚至在小数组中比快速排序还快,但是在涉及大量数据时希尔排序还是比快速排序慢。
"""
def step_a():
k = 0
while True:
yield 9 * (4 ** k - 2 ** k) + 1
k += 1
def step_b():
k = 0
while True:
v = 2 ** (k + 2)
yield v * (v - 3) + 1
k += 1
gen_a, gen_b = step_a(), step_b()
a, b = gen_a.next(), gen_b.next()
small = min(a, b)
yield small
while True:
if small == a:
a = gen_a.next()
else:
b = gen_b.next()
small = min(a, b)
yield small
def step_sedgewick(n):
"""限制步长序列值小于n"""
gen_step = _step_sedgewick()
while True:
v = gen_step.next()
if v < n:
yield v
else:
return
def shell_sort(A, gaps):
"""希尔排序,伪码如下:
SHELL-SORT(A, gaps)
1 n ← length[A] // 数组长度
2 foreach gap in gaps
3 ▷ 为每个步长下各列做插入排序
4 for i ← gap to n-1 // 从步长位至末位
5 do temp ← A[i]
6 j ← i
7 while j >= gap and A[j - gap] > temp // 与步长前一位比较,直至不小于它
8 do A[j] ← A[j - gap] // 大值后移
9 j ← j - gap // 再前一位
10 A[j] = temp
Args:
A (Sequence): 数组
gaps (Iterator): 步长序列
更多步长:http://en.wikipedia.org/wiki/Shellsort
"""
n = len(A)
for gap in gaps:
for i in xrange(gap, n):
temp = A[i]
j = i
while j >= gap and A[j - gap] > temp:
A[j] = A[j - gap]
j = j - gap
A[j] = temp
if __name__ == '__main__':
import random, timeit
items = range(10000)
random.shuffle(items)
def test_sorted():
# print(items)
sorted_items = sorted(items)
# print(sorted_items)
# _gaps = step_half(len(items))
_gaps = reversed([a for a in step_sedgewick(len(items))])
def test_shell_sort():
# print(items)
shell_sort(items, _gaps)
# print(items)
test_methods = [test_sorted, test_shell_sort]
for test in test_methods:
name = test.__name__ # test.func_name
t = timeit.Timer(name + '()', 'from __main__ import ' + name)
print(name + ' takes time : %f' % t.timeit(1))