码迷,mamicode.com
首页 > 编程语言 > 详细

希尔,归并,快速排序

时间:2021-04-29 11:58:13      阅读:0      评论:0      收藏:0      [点我收藏+]

标签:span   大于   排序   str   port   特性   空间   extend   分区函数   

1. 希尔排序

思路: 是优化了的插入排序,可以改进当最值处于头或尾需要多次移动元素的问题,因为它会设置步长k(>=1),初始步长是len/2, 先保证步长为k的每个子数组有序,再进一步缩小步长直到为1的时候,数组基本有序。

‘‘‘
希尔排序
时间复杂度
  平均:O(nlogn)
  最好:O(nlogn)
  最坏:O(nlogn)
空间复杂度: O(1)
‘‘‘

def shellSort(arr):
    if not arr or len(arr) == 1:
        return
    length = len(arr)
    gap = length // 2 # 组的个数
    while gap > 0:
        for i in range (gap, length): # 把arr[i] 插到所在分组的正确位置
            insertSub(arr, gap, i)
            i += 1
        gap = gap // 2

def insertSub(arr, gap, i):
    temp = arr[i]
    k = i - gap
    while (k >= 0 and (temp < arr[k])): # 跟插入排序一样一样的
        arr[k + gap] = arr[k]
        k -= gap
    arr[k + gap] = temp

 

2. 归并排序

自底向上的排序, 是稳定排序,但是效率没有快速排序高。

不管是最好情况、最坏情况,还是平均情况,时间复杂度都是O(nlogn). 空间O(n)

‘‘
时间复杂度:
    最好:O(nlog n)
    最坏:O(n*n)
    平均:O(nlog n)
空间复杂度:O(n)
稳定性:不稳定
‘‘‘
def merge(arr, low, mid, high):
    import copy
    arr1 = copy.deepcopy(arr) # 复制源数组,要用深拷贝
    i = low
    j = mid+1
    index = low
    # [low...mid, mid+1...high] 这里的逻辑跟严蔚敏数据结构教材合并两个有序链表的逻辑一毛一样
    while (i <= mid and j <= high):
        if(arr1[i] > arr1[j]):
            arr[index] = arr1[j]
            j +=1
        else:
            arr[index] = arr1[i]
            i +=1
        index += 1

    while(i <= mid):
        arr[index] = arr1[i]
        index += 1
        i += 1

    while(j <= high):
        arr[index] = arr1[j]
        index += 1
        j += 1

# 递归实现
def merge_sort(arr, first, last):
    if first >= last:
        return
    mid = (first + last) //2
    merge_sort(arr, first, mid)
    merge_sort(arr, mid + 1, last)
    merge(arr, first, mid, last)

# 非递归实现
def merge_sort_no_recursion(arr):
    if len(arr) == 1 or not arr:
        return arr
    length = len(arr)
    step = 2

    while(step <= length):
        cur = 0
        while cur + step <= length:
            high = cur + step -1
            low = cur
            mid = cur + step //2 - 1
            merge(arr, low, mid, high)
            cur += step
        if cur < length - step//2:
            mid = cur + step//2 -1
            merge(arr, cur, mid, length -1)
        step *=2
    mid = step//2 -1
    merge(arr, 0, mid, length -1)

 

3.快速排序

自顶向下的排序

快速排序是目前基于比较的内部排序中最好的方法,当待排序的元素是随机分布时,快速排序的平均时间最短。最好O(nlogn),最坏O(n2)

 

‘‘‘
时间复杂度:
    最好:nlog n
    最坏:n*n
    平均:nlog n
空间复杂度:log n
稳定性:不稳定
‘‘‘
# 分区函数,选取第一个元素为基准值,把小于基准的元素全放在它左边,大于基准的元素放它右边
def partition(arr, low, high):
    pivot = arr[low]
    while low < high:
        while low < high and arr[high] >= pivot:
            high -= 1  # 找到排在后面但是小于基准的最先元素
        arr[low] = arr[high] # 由于比基准还小,把它替换成low的值

        while low < high and arr[low] <= pivot:
            low += 1  # 找到排在前面但是大于基准的最先元素
        arr[high] = arr[low]  # 由于比基准大,所以把它替换成high的值

    arr[low] = pivot  # 此时的low也许已经移位了,替换成基准值
    # print(‘low: {}‘.format(low))
    return low

# 递归实现
def quick_sort(arr, first, last):
    if first >= last:
        return
    pivot = partition(arr, first, last)

    quick_sort(arr, first, pivot - 1)
    quick_sort(arr, pivot + 1, last)

# 非递归实现, 递归本质就是入栈和出栈过程
def quick_sort_no_recursion(arr, first, last):
    if first >= last:
        return arr
    stack = [first, last]
    while stack:
        first, last = stack.pop(0), stack.pop(0)  # 移除列表中的第一个元素
        if first >= last:
            continue
        i, pivot = first - 1, arr[last] # 最后一个元素为基准值
        for j in range(first, last + 1):
            if arr[j] <= pivot: # 从头向后找第一个大于基准的数
                i += 1 # 没找到则i+1, 都是比基准小的数
                arr[i], arr[j] = arr[j], arr[i] # 交换这两数, 利用了python特性,arr[-1]即是数组最后一个元素
        stack.extend([first, i - 1, i + 1, last]) # 在列表后追加
    return arr

 

希尔,归并,快速排序

标签:span   大于   排序   str   port   特性   空间   extend   分区函数   

原文地址:https://www.cnblogs.com/stxz/p/14715129.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!