用Python实现基本排序算法04——Shell排序

一、Shell排序的思路

        Shell排序实质上是一种优化的插入排序。D.L.Shell在研究后发现,插入排序存在以下规律:

        1>在元素基本有序时效率较高,

        2>在序列规模较小时效率较高

        为了充分利用这个两个规律,Shell排序的思路是:

a>设定步长,每隔一段距离取一个数,将原来需要排序的序列变成几个较小的部分(姑且称之为子串吧),这样就可以满足2>的条件。

b>将每个子串各自排序

c>减小步长,形成新的子串。此时的子串虽然包含更多地元素,但由于经过b>步骤的排序,此时各部分已基本有序,故满足了1>的设定

d>逐次减小步长,最后进行一次步长为1的排序(也即正常的插入排序),但此时整个串已经基本有序,交换次数不会太多,效率会很高。


二、程序实现

在具体实现时步长(Step)的取法并不固定,在数据量较大时不同的Step取法将带来不同的优化效果(根据网上的说法,PosPro未做研究)。

这里仅仅为了说明算法实现的思路,Step取4,2,1,按照从小到大排列。

#20150901 by PosPro
# http://blog.csdn.net/pospro
def shellSort(alist):
	step=4		#初始步长采用4
	while step>=1:  #step=1时就是最后一次排序
		for i in range(step): # i=0,1,...step-1, 恰好是每一个子串起始值所在位置
			shellSortCore(alist, i, step)
		print 'Num in every %d positon has been sorted'%step  #动态显示之用
		step=step//2


def shellSortCore(alist, startpos, step):
	#这个函数其实就是实现了一个step版的插入算法,
	#不熟悉插入算法的话,可以看前一篇博客:http://blog.csdn.net/pospro/article/details/48091893
	n=len(alist)  #记录alist的长度
	idx=startpos+step  #idx恰好是未排序子串中第一个元素的位置
	while idxval and newpos>startpos: #若待插入位置不合适,则通过平移,继续寻找
			alist[newpos]=alist[newpos-step] #注意这里所有位置的增减都是针对步长值操作的
			newpos-=step
		alist[newpos]=val #退出循环后,newpos指示的就是val该放置的位置
		idx+=step
	print alist  #仅为动态显示过程之用

三、测试用例和输出

可使用以下代码对算法进行测试:

list1=[9,8,11,3,4,10,6,0,2,1,7,5]
print list1
shellSort(list1)
print list1

输出结果如下,仔细分析一下,就可以体会出Shell算法的处理过程。

用Python实现基本排序算法04——Shell排序_第1张图片




你可能感兴趣的:(python,编程实例,算法)