Python的希尔排序、快速排序和归并排序

本秂侑毒 提交于 2020-03-17 07:08:53

目录

一、希尔排序(Shell Sort)

 二、快速排序(Quicksort)

三、归并排序

四、排序算法效率比较

五、搜索

六、二分法查找


一、希尔排序(Shell Sort)

 1、定义:是插入排序的一种,只不过间隔设为gap。希尔排序是非稳定排序算法。该方法因DL.Shell于1959年提出而得名。 希尔排序是把记录按下标的一定增量分组,对每组使用直接插入排序算法排序;随着增量逐渐减少,每组包含的关键词越来越多,当增量减至1时,整个文件恰被分成一组,算法便终止。

 2、原理:将数组列在一个表中并对列分别进行插入排序,重复这过程,不过每次用更长的列(步长更长了,列数更少了)来进行。最后整个表就只有一列了。将数组转换至表是为了更好地理解这算法,算法本身还是使用数组进行排序。

3、希尔排序的实现:

shell_sort(alist):
    """希尔排序法"""
    n = len(alist)
    # 初始步长
    gap = n // 2  #折半设定,若n=9,则gap=4
    while gap > 0:  #gap=1进行最后一次循环
        # 按步长进行插入排序
        for j in range(gap, n):#从gap开始,控制子序列中的所有元素
            i = j
            # 插入排序
            while i > 0:
                if alist[i] < alist[i-gap]:
                    alist[i-gap], alist[i] = alist[i], alist[i-gap]  #gap为步长
                    i -= gap
                else:
                    break
        gap = gap // 2   # 得到新的步长
alist = [54,26,93,17,77,31,44,55,20]
print(alist)
shell_sort(alist)
print(alist)

输出:
[54, 26, 93, 17, 77, 31, 44, 55, 20]
[17, 20, 26, 31, 44, 54, 55, 77, 93]

4、时间复杂度:

  • 最优时间复杂度:根据步长序列的不同而不同
  • 最坏时间复杂度:O(n2)
  • 稳定想:不稳定

 二、快速排序(Quicksort)

 1、定义:快速排序,又称划分交换排序(partition-exchange sort),通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。

2、工作步骤:

(1)从数列中挑出一个元素,称为"基准"(pivot),

(2)重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。在这个分区结束之后,该基准就处于数列的中间位置。这个称为分区(partition)操作。

(3)递归地(recursive)把小于基准值元素的子数列和大于基准值元素的子数列排序。

3、快速排列的实现:

def quick_sort(alist, start, end):
    """快速排序"""
    if start >= end:   #递归的退出条件
        return
    Mid_value = alist[start]
    low = start
    high = end
    while low < high:  #以下移动交替进行
        #high左移
        while low < high and alist[high] >= Mid_value:
            high -= 1
        alist[low] = alist[high]
        # low右移
        while low < high and alist[low] < Mid_value:
            low +=1
        alist[high] = alist[low]
    # 从循环退出时,low=high
    alist[low] = Mid_value
    #Mid_value两边分别快速排序,不断递归
    quick_sort(alist, start, low-1)
    quick_sort(alist, low+1, end)

alist = [54,26,93,17,77,31,44,55,20]
print(alist)
quick_sort(alist, 0, len(alist)-1)
print(alist)

输出:
[54, 26, 93, 17, 77, 31, 44, 55, 20]
[17, 20, 26, 31, 44, 54, 55, 77, 93]

4、时间复杂度

  • 最优时间复杂度:O(nlogn)
  • 最坏时间复杂度:O(n2)
  • 稳定性:不稳定

、归并排序

1、定义:归并排序是采用分治法的一个非常典型的应用。归并排序的思想就是先递归分解数组,再合并数组。将数组分解最小之后,然后合并两个有序数组,基本思路是比较两个数组的最前面的数,谁小就先取谁,取了后相应的指针就往后移一位。然后再比较,直至一个数组为空,最后把另一个数组的剩余部分复制过来即可。

2、归并排序的实现:

def merge_sort(alist):
    """归并排序"""
    n = len(alist)
    if n <= 1:
        return alist
    mid = n//2
    #left采用归并排序后形成的有序的新的列表
    left_li = merge_sort(alist[:mid])
    #right采用归并排序后形成的有序的新的列表
    right_li = merge_sort(alist[mid:])
    #将两个有序的子序列合并成一个整体merge(left,right)
    left_pointer, right_pointer = 0, 0
    result = []
    while left_pointer<len(left_li) and right_pointer<len(right_li):
        if left_li[left_pointer] < right_li[right_pointer]:
            result.append(left_li[left_pointer])
            left_pointer += 1
        else:
            result.append(right_li[right_pointer])
            right_pointer += 1
    result += left_li[left_pointer:]   #左边走到头
    result += right_li[right_pointer:] #右边走到头
    return result
alist = [54,26,93,17,77,31,44,55,20]
print(alist)
sorted_li = merge_sort(alist)
print(alist)
print(sorted_li)

输出:
[54, 26, 93, 17, 77, 31, 44, 55, 20]
[54, 26, 93, 17, 77, 31, 44, 55, 20]
[17, 20, 26, 31, 44, 54, 55, 77, 93]

3、递归工作过程:

4、时间复杂度:

  • 最优时间复杂度:O(nlogn)
  • 最坏时间复杂度:O(nlogn)
  • 稳定性:稳定

、排序算法效率比较

多运用快速排序。

、搜索

搜索的几种常见方法:顺序查找、二分法查找、二叉树查找、哈希查找

、二分法查找

1、定义:二分查找又称折半查找,优点是比较次数少,查找速度快,平均性能好;其缺点是要求待查表为有序表,且插入删除困难。因此,折半查找方法适用于不经常变动而查找频繁的有序列表。

2、原理:首先,假设表中元素是按升序排列,将表中间位置记录的关键字与查找关键字比较如果两者相等,则查找成功;否则利用中间位置记录将表分成前、后两个子表,如果中间位置记录的关键字大于查找关键字,则进一步查找前一子表,否则进一步查找后一子表。重复以上过程,直到找到满足条件的记录,使查找成功,或直到子表不存在为止,此时查找不成功。

3、二分查找的实现:

(1)递归法实现

def binary_search(alist, item):
    """二分查找递归法"""
    n = len(alist)
    if n > 0:
        mid = n//2
        if alist[mid]==item:
          return True
        elif item < alist[mid]:
            return binary_search(alist[:mid], item)
        else:
            return binary_search(alist[mid+1:], item)
    return False
testlist = [0, 1, 2, 8, 13, 17, 19, 32, 42,]
print(binary_search(testlist, 3))
print(binary_search(testlist, 13))

输出:
False
True

(2)非递归法实现

def binary_search(alist, item):
    """二分查找非递归版"""
    n = len(alist)
    first = 0
    last = n-1
    while first <= last:
        mid = (first + last)//2
        if alist[mid] == item:
            return True
        elif item < alist[mid]:
            last = mid-1
        else:
            first = mid+1
    return False
testlist = [0, 1, 2, 8, 13, 17, 19, 32, 42,]
print(binary_search(testlist, 3))
print(binary_search(testlist, 13))

输出:
False
True

4、时间复杂度:

  • 最优时间复杂度:O(1)
  • 最坏时间复杂度:O(logn)

 

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!