一、 排序
(一)希尔排序
希尔排序是把记录按下标的一定增量分组,对每组使用直接插入排序算法排序;随着增量逐渐减少,每组包含的关键词越来越多,当增量减至1时,整个文件恰被分成一组,算法便终止。
希尔排序的基本思想是:将数组列在一个表中并对列分别进行插入排序,重复这过程,不过每次用更长的列(步长更长了,列数更少了)来进行。最后整个表就只有一列了。将数组转换至表是为了更好地理解这算法,算法本身还是使用数组进行排序。
其代码实现如下:
def shell_sort(alist):
"""希尔排序"""
n = len(alist)
gap = int(n / 2)#gap为步长
while gap > 0:
for i in range(gap, n):
j = i
while j >= gap and alist[j - gap] > alist[j]:
alist[j - gap], alist[j] = alist[j], alist[j - gap]#同列之间比较大小,交换位置
j -= gap
gap = int(gap / 2)
print(alist)
list = [1, 3, 2, 7, 5, 9, 4]
shell_sort(list)
(二) 归并排序
归并排序是采用分治法的一个非常典型的应用。归并排序的思想就是先递归分解数组,再合并数组。
将数组分解最小之后,然后合并两个有序数组,基本思路是比较两个数组的最前面的数,谁小就先取谁,取了后相应的指针就往后移一位。然后再比较,直至一个数组为空,最后把另一个数组的剩余部分复制过来即可。
def merge_sort(alist):
n = len(alist)
if n <= 1:
return alist
num = int(n / 2)
# 分解
left = merge_sort(alist[:num])
right = merge_sort(alist[num:])
return merge(left, right)
def merge(left, right):
"""合并"""
l, r = 0, 0
result = []
while l < len(left) and r < len(right):
if left[l] < right[r]:
result.append(left[l])
l += 1
else:
result.append(right[r])
r += 1
result += left[l:]
result += right[r:]
# print(result)
return result
alist = [54,26,93,17,77,31,44,55,20]
sorted_alist = merge_sort(alist)
print(sorted_alist)
二、搜索
二分查找又称折半查找,优点是比较次数少,查找速度快,平均性能好;其缺点是要求待查表为有序表,且插入删除困难。因此,折半查找方法适用于不经常变动而查找频繁的有序列表。首先,假设表中元素是按升序排列,将表中间位置记录的关键字与查找关键字比较,如果两者相等,则查找成功;否则利用中间位置记录将表分成前、后两个子表,如果中间位置记录的关键字大于查找关键字,则进一步查找前一子表,否则进一步查找后一子表。重复以上过程,直到找到满足条件的记录,使查找成功,或直到子表不存在为止,此时查找不成功。
(一)不含递归的二分法
def bin_search(alist, item):
alist = merge_sort(alist)# 此处调用了归并排序函数,将无序列表转为有序。若不调用,则输入的列表必须为有序
first = 0
last = len(alist) - 1#列表从0开始,故需减一
while first < last:
mid = int((first + last) / 2)#中间点
if alist[mid] == item:
return True
elif alist[mid] < item:
first = mid + 1#因为是有序表,故可确定前半段无我们要找的元素
else:
last = mid - 1
return False
list = [8, 1, 3, 2, 7, 5, 9, 4, 6]
print(bin_search(list, 8))
(二)含递归的二分法
def bin_search(alist, item):
if len(alist) == 0:#alist的长度在递归下不断减小,减小至0时可判断无要找的元素
print("%d is not in the list!" % item)
else:
mid_point = len(alist) // 2#确定中间点
if alist[mid_point] == item:
print("%d is in the list!" % item)#中间点恰好为我们找的元素
elif alist[mid_point] < item:
return bin_search(alist[mid_point + 1:], item)#递归调用,此时调用函数的alist为列表后半段
else:
return bin_search(alist[:mid_point], item)#递归调用,此时调用函数的alist为列表前半段
test_list = [1, 2, 3, 4, 5, 6, 7]
bin_search(test_list, 7)