#算法和数据结构分析#
今天接着排序来讲:1.插入排序(selection sort)
2希尔排序(shell sort)
为何要将它们放在一起讲呢? 因为它们之间存在一定的联系.
那我们先来看看选择排序是什么???
首先假设位置0处的元素是只含单个元素的有序子列表。从元素1到元素n-1,每一轮都将当前元素与有序子列表中的元素进行比较。在有序子列表中,将比它大的元素右移;每当遇到一个比它小的元素或抵达子列表终点的时候,就可以插入当前元素
可能这么说,还是有些模糊,那么上代码
def selection_sort(alist):
for index in range(1,len(alist)):
currentvalue = alist[index]
position = index
#index为新项,插入项
while position > 0 and alist[position-1] > currentvalue:
alist[position] = alist[position-1]
position = position - 1
#比对,移动项,使始终空出一个位置留给插入项
alist[position] = currentvalue
#最后结束一次while循环 插入新项
或者还有一种写法
def insertion_sort(alist):
for i in range(1,len(alist)):
currentvalue = alist[i]
j = i - 1
#设插入值为currentvalue j作为引索
while j >= o and currentvalue < alist[j]:
alist[j+1] = alist[j]
j = j - 1
#当前值若大于插入值,便向后移一位
#最后找到插入位置,完成一次循环
alist[j+1] = currentvalue
return alist
原理:通过构建有序序列,对于未排序数据在已排序序列中从后向前scan(扫描),从而找到相应的位置并插入进去。
1.从第一个元素开始,该元素可以被认为已经被排序
2.取出下一个元素,在已经排序的元素序列中从后向前扫描
3.如果被扫描的元素(已排序)大于新元素,将该元素后移一位。
4.重复步骤3,直到找到已排序的元素小于或等于新元素的位置
5.将新元素扫描到该位置后
6.重复步骤2-5 直到for循环结束 return来结束函数 返回最终值
注意注意:一定要搞明白---插入排序,再来看希尔排序
希尔排序是更便捷的插入排序,基础是插入排序
希尔排序(shell sort)也叫“递减增量排序”,它对插入排序做了改进,将列表分成数个子列表,并对每一个子列表应用插入排序。
这里的关键就是,我们该如何区切分列表呢???
这里的切分并不是连续切分,而是使用增量(也可以叫步长(step))选取所有间隔为i的元素组成为子列表。
为了进行希尔排序,我们有以下四个步骤:
1.间隔分组(总长度的一半)
2.组内排序
3.重新设置间隔分组(为前一次分组的一半)
4.插入排序
代码实现有两个部分
我们先来看第一个部分,分组吧
def shellsort(alist):
sublistcount = len(alist) // 2 #取半
#不断对半,直到step为1
while sublistcount > 0:
for startposition in range(sublistcount):
gapInsertionSort(alist,startposition,sublistcount)
#此处是进行子列表中的选择排序
sublistcount = sublistcount // 2
#对原先的组进行再次取半
其实我们求出的sublistcount再后面将会用作gap(步长)来使用
可以看到我们在for循环时,调用了一个函数gapInsertionSort()---这个是用来进行小组内的插入排序
那么我们来看看这个函数,它的代码又是如何呢?
def gapInsertionSort(alist,start,gap):
for i in range(start+gap,len(alist),gap):
#设置插入值
currentvalue = alist[i]
position = i
#这里便与我们在上面说的插入排序相似
while position > gap and\
alist[position] > alist[currentvalue]:
alist[position] = alist[position-gap]
position = position - gap
alist[position] = currentvalue
看似希尔排序可能没有插入排序好,因为最后一步要做完整的插入排序。但是,在事实上,列表已经做好了预处理的,则最后一步插入排序,不再需要进行多次的插入和比较。每一轮高效的子列表插入排序,为最后一步的完整列表插入排序做好了准备,最后一步,会非常高效